diff options
Diffstat (limited to 'src')
574 files changed, 29346 insertions, 22058 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 6718b4805..5d21a97eb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -11,11 +11,13 @@ SUBDIRS = \ demuxers \ libffmpeg \ libmpeg2 \ + libmpeg2new \ liba52 \ libspudec \ libspucc \ libspucmml \ libspudvb \ + libspuhdmv \ libsputext \ libdts \ libmad \ diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am index b0c3d292e..745fafadd 100644 --- a/src/audio_out/Makefile.am +++ b/src/audio_out/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CPPFLAGS = -DXINE_COMPILE @@ -49,10 +50,14 @@ if HAVE_JACK jack_module = xineplug_ao_out_jack.la endif +if HAVE_SNDIO +sndio_module = xineplug_ao_out_sndio.la +endif + ## # IMPORTANT: # --------- -# all xine audio out plugins should be named like the +# all xine audio out plugins should be named like the # scheme "xineplug_ao_out_" # xineplug_LTLIBRARIES = xineplug_ao_out_none.la xineplug_ao_out_file.la \ @@ -66,7 +71,8 @@ xineplug_LTLIBRARIES = xineplug_ao_out_none.la xineplug_ao_out_file.la \ $(pulseaudio_module) \ $(directx2_module) \ $(fusionsound_module) \ - $(jack_module) + $(jack_module) \ + $(sndio_module) xineplug_ao_out_none_la_SOURCES = audio_none_out.c xineplug_ao_out_none_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) @@ -88,7 +94,7 @@ xineplug_ao_out_alsa_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) $(PTHREAD_LIBS) $(LTLI xineplug_ao_out_alsa_la_CFLAGS = $(VISIBILITY_FLAG) $(ALSA_CFLAGS) xineplug_ao_out_alsa_la_LDFLAGS = -avoid-version -module -xineplug_ao_out_esd_la_SOURCES = audio_esd_out.c +xineplug_ao_out_esd_la_SOURCES = audio_esd_out.c xineplug_ao_out_esd_la_LIBADD = $(XINE_LIB) $(ESD_LIBS) $(LTLIBINTL) xineplug_ao_out_esd_la_CFLAGS = $(VISIBILITY_FLAG) $(ESD_CFLAGS) xineplug_ao_out_esd_la_LDFLAGS = -avoid-version -module @@ -98,7 +104,7 @@ xineplug_ao_out_sun_la_LIBADD = $(XINE_LIB) xineplug_ao_out_sun_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_ao_out_sun_la_LDFLAGS = -avoid-version -module -#xineplug_ao_out_irixal_la_SOURCES = audio_irixal_out.c +#xineplug_ao_out_irixal_la_SOURCES = audio_irixal_out.c #xineplug_ao_out_irixal_la_LIBADD = $(IRIXAL_LIBS) #xineplug_ao_out_irixal_la_CFLAGS = $(VISIBILITY_FLAG) $(IRIXAL_CFLAGS) #xineplug_ao_out_irixal_la_LDFLAGS = -avoid-version -module @@ -110,7 +116,7 @@ xineplug_ao_out_arts_la_LDFLAGS = -avoid-version -module xineplug_ao_out_directx_la_SOURCES = audio_directx_out.c xineplug_ao_out_directx_la_CPPFLAGS = $(DIRECTX_CPPFLAGS) -xineplug_ao_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) +xineplug_ao_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(LTLIBINTL) xineplug_ao_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_ao_out_directx_la_LDFLAGS = -avoid-version -module @@ -131,7 +137,7 @@ xineplug_ao_out_pulseaudio_la_LDFLAGS = -avoid-version -module xineplug_ao_out_directx2_la_SOURCES = audio_directx2_out.c xineplug_ao_out_directx2_la_CPPFLAGS = $(DIRECTX_CPPFLAGS) -xineplug_ao_out_directx2_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(PTHREAD_LIBS) +xineplug_ao_out_directx2_la_LIBADD = $(XINE_LIB) $(DIRECTX_AUDIO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_ao_out_directx2_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_ao_out_directx2_la_LDFLAGS = -avoid-version -module @@ -144,3 +150,8 @@ xineplug_ao_out_jack_la_SOURCES = audio_jack_out.c xineplug_ao_out_jack_la_LIBADD = $(XINE_LIB) $(JACK_LIBS) $(LTLIBINTL) xineplug_ao_out_jack_la_CFLAGS = $(VISIBILITY_FLAG) $(JACK_CFLAGS) xineplug_ao_out_jack_la_LDFLAGS = -avoid-version -module + +xineplug_ao_out_sndio_la_SOURCES = audio_sndio_out.c +xineplug_ao_out_sndio_la_LIBADD = $(XINE_LIB) $(SNDIO_LIBS) +xineplug_ao_out_sndio_la_CFLAGS = $(VISIBILITY_FLAG) $(SNDIO_CFLAGS) +xineplug_ao_out_sndio_la_LDFLAGS = -avoid-version -module diff --git a/src/audio_out/audio_alsa_out.c b/src/audio_out/audio_alsa_out.c index 4ce2b1be3..b18637a7b 100644 --- a/src/audio_out/audio_alsa_out.c +++ b/src/audio_out/audio_alsa_out.c @@ -1,23 +1,23 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * Credits go + * Credits go * - for the SPDIF A/52 sync part * - frame size calculation added (16-08-2001) * (c) 2001 Andy Lo A Foe <andy@alsaplayer.org> @@ -99,7 +99,7 @@ typedef struct alsa_driver_s { uint32_t bytes_per_frame; uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */ snd_pcm_uframes_t buffer_size; - int32_t mmap; + int32_t mmap; struct { pthread_t thread; @@ -136,10 +136,10 @@ static int my_snd_mixer_wait(snd_mixer_t *mixer, int timeout) { if (count < 0) return count; - + if ((unsigned int) count > sizeof(spfds) / sizeof(spfds[0])) { pfds = malloc(count * sizeof(*pfds)); - + if (!pfds) return -ENOMEM; @@ -169,44 +169,44 @@ static void *ao_alsa_handle_event_thread(void *data) { int old_mute; pthread_mutex_lock(&this->mixer.mutex); - + old_mute = (this->mixer.mute & MIXER_MASK_MUTE) ? 1 : 0; if((err = snd_mixer_handle_events(this->mixer.handle)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_handle_events(): %s\n", snd_strerror(err)); pthread_mutex_unlock(&this->mixer.mutex); continue; } - + if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &left_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); pthread_mutex_unlock(&this->mixer.mutex); continue; } - + if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &right_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); pthread_mutex_unlock(&this->mixer.mutex); continue; } - + if(this->mixer.mute & MIXER_HAS_MUTE_SWITCH) { - + if(this->mixer.mute & MIXER_MASK_STEREO) { snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); mute = (swl) ? 0 : 1; } else { - + if (this->mixer.mute & MIXER_MASK_LEFT) snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); - + if ((SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN) && (this->mixer.mute & MIXER_MASK_RIGHT)) snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr); - + mute = (swl || swr) ? 0 : 1; } } @@ -216,26 +216,26 @@ static void *ao_alsa_handle_event_thread(void *data) { xine_audio_level_data_t data; xine_stream_t *stream; xine_list_iterator_t ite; - + this->mixer.right_vol = right_vol; this->mixer.left_vol = left_vol; if(mute) this->mixer.mute |= MIXER_MASK_MUTE; else this->mixer.mute &= ~MIXER_MASK_MUTE; - - data.right = ao_alsa_get_percent_from_volume(this->mixer.right_vol, + + data.right = ao_alsa_get_percent_from_volume(this->mixer.right_vol, this->mixer.min, this->mixer.max); - data.left = ao_alsa_get_percent_from_volume(this->mixer.left_vol, + data.left = ao_alsa_get_percent_from_volume(this->mixer.left_vol, this->mixer.min, this->mixer.max); data.mute = (this->mixer.mute & MIXER_MASK_MUTE) ? 1 : 0; - + event.type = XINE_EVENT_AUDIO_LEVEL; event.data = &data; event.data_length = sizeof(data); - + pthread_mutex_lock(&this->class->xine->streams_lock); - for(ite = xine_list_front(this->class->xine->streams); + for(ite = xine_list_front(this->class->xine->streams); ite; ite = xine_list_next(this->class->xine->streams, ite)) { stream = xine_list_get_value(this->class->xine->streams, ite); event.stream = stream; @@ -243,12 +243,12 @@ static void *ao_alsa_handle_event_thread(void *data) { } pthread_mutex_unlock(&this->class->xine->streams_lock); } - + pthread_mutex_unlock(&this->mixer.mutex); } } while(this->mixer.running); - + pthread_exit(NULL); } @@ -261,11 +261,11 @@ static long ao_alsa_get_volume_from_percent(int val, long min, long max) { } /* - * Error callback, we need to control this, + * Error callback, we need to control this, * error message should be printed only in DEBUG mode. */ static void XINE_FORMAT_PRINTF(5, 6) - error_callback(const char *file, int line, + error_callback(const char *file, int line, const char *function, int err, const char *fmt, ...) { #ifdef DEBUG va_list args; @@ -286,13 +286,13 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int alsa_driver_t *this = (alsa_driver_t *) this_gen; config_values_t *config = this->class->xine->config; char *pcm_device; - snd_pcm_stream_t direction = SND_PCM_STREAM_PLAYBACK; + snd_pcm_stream_t direction = SND_PCM_STREAM_PLAYBACK; snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_access_mask_t *mask; snd_pcm_uframes_t period_size; - snd_pcm_uframes_t period_size_min; - snd_pcm_uframes_t period_size_max; + snd_pcm_uframes_t period_size_min; + snd_pcm_uframes_t period_size_max; snd_pcm_uframes_t buffer_size_min; snd_pcm_uframes_t buffer_size_max; snd_pcm_format_t format; @@ -310,7 +310,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); err = snd_output_stdio_attach(&jcd_out, stdout, 0); - + switch (mode) { case AO_CAP_MODE_MONO: this->num_channels = 1; @@ -336,10 +336,10 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int pcm_device = config->lookup_entry(config, "audio.device.alsa_passthrough_device")->str_value; break; default: - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: ALSA Driver does not support the requested mode: 0x%X\n",mode); return 0; - } + } #ifdef ALSA_LOG printf("audio_alsa_out: Audio Device name = %s\n",pcm_device); @@ -362,25 +362,25 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int */ gettimeofday(&start_time, NULL); do { - err = snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode); + err = snd_pcm_open(&this->audio_fd, pcm_device, direction, open_mode); gettimeofday(&end_time, NULL); if( err == -EBUSY ) { - if( (double)end_time.tv_sec + 1E-6*end_time.tv_usec + if( (double)end_time.tv_sec + 1E-6*end_time.tv_usec - (double)start_time.tv_sec - 1E-6*start_time.tv_usec > 0.8) break; else usleep(10000); } } while( err == -EBUSY ); - - if(err <0 ) { - xprintf (this->class->xine, XINE_VERBOSITY_LOG, - _("audio_alsa_out: snd_pcm_open() of %s failed: %s\n"), pcm_device, snd_strerror(err)); - xprintf (this->class->xine, XINE_VERBOSITY_LOG, + + if(err <0 ) { + xprintf (this->class->xine, XINE_VERBOSITY_LOG, + _("audio_alsa_out: snd_pcm_open() of %s failed: %s\n"), pcm_device, snd_strerror(err)); + xprintf (this->class->xine, XINE_VERBOSITY_LOG, _("audio_alsa_out: >>> check if another program already uses PCM <<<\n")); return 0; } - /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */ + /* printf ("audio_alsa_out: snd_pcm_open() opened %s\n", pcm_device); */ /* We wanted non blocking open but now put it back to normal */ //snd_pcm_nonblock(this->audio_fd, 0); snd_pcm_nonblock(this->audio_fd, 1); @@ -389,7 +389,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int */ err = snd_pcm_hw_params_any(this->audio_fd, params); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_LOG, + xprintf (this->class->xine, XINE_VERBOSITY_LOG, _("audio_alsa_out: broken configuration for this PCM: no configurations available: %s\n"), snd_strerror(err)); goto close; @@ -403,7 +403,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX); err = snd_pcm_hw_params_set_access_mask(this->audio_fd, params, mask); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: mmap not availiable, falling back to compatiblity mode\n"); this->mmap=0; err = snd_pcm_hw_params_set_access(this->audio_fd, params, @@ -413,9 +413,9 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int err = snd_pcm_hw_params_set_access(this->audio_fd, params, SND_PCM_ACCESS_RW_INTERLEAVED); } - + if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: access type not available: %s\n", snd_strerror(err)); goto close; } @@ -438,23 +438,23 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int case 4: format = SND_PCM_FORMAT_FLOAT; break; - default: + default: format = SND_PCM_FORMAT_S16; - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: pcm format bits=%d unknown. failed: %s\n", bits, snd_strerror(err)); break; } err = snd_pcm_hw_params_set_format(this->audio_fd, params, format ); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: sample format non available: %s\n", snd_strerror(err)); goto close; } /* set the number of channels */ err = snd_pcm_hw_params_set_channels(this->audio_fd, params, this->num_channels); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, - "audio_alsa_out: Cannot set number of channels to %d (err=%d:%s)\n", + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + "audio_alsa_out: Cannot set number of channels to %d (err=%d:%s)\n", this->num_channels, err, snd_strerror(err)); goto close; } @@ -466,13 +466,13 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int dir=0; err = snd_pcm_hw_params_set_rate_near(this->audio_fd, params, &rate, &dir); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: rate not available: %s\n", snd_strerror(err)); goto close; } this->output_sample_rate = (uint32_t)rate; if (this->input_sample_rate != this->output_sample_rate) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: audio rate : %d requested, %d provided by device/sec\n", this->input_sample_rate, this->output_sample_rate); } @@ -504,7 +504,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int periods=8; err = snd_pcm_hw_params_set_periods_near(this->audio_fd, params, &periods ,&dir); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: unable to set any periods: %s\n", snd_strerror(err)); goto close; } @@ -512,7 +512,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int dir=0; err = snd_pcm_hw_params_set_buffer_time_near(this->audio_fd, params, &buffer_time, &dir); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: buffer time not available: %s\n", snd_strerror(err)); goto close; } @@ -522,7 +522,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int dir=0; err = snd_pcm_hw_params_set_period_size_near(this->audio_fd, params, &period_size, &dir); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: period time not available: %s\n", snd_strerror(err)); goto close; } @@ -533,7 +533,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int dir=0; err = snd_pcm_hw_params_set_buffer_size_near(this->audio_fd, params, &this->buffer_size); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: buffer time not available: %s\n", snd_strerror(err)); goto close; } @@ -543,22 +543,22 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int printf("was set buffer_size = %ld\n",this->buffer_size); #endif if (2*period_size > this->buffer_size) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: buffer to small, could not use\n"); goto close; } - + /* write the parameters to device */ err = snd_pcm_hw_params(this->audio_fd, params); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: pcm hw_params failed: %s\n", snd_strerror(err)); goto close; } /* Check for pause/resume support */ this->has_pause_resume = ( snd_pcm_hw_params_can_pause (params) && snd_pcm_hw_params_can_resume (params) ); - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out:open pause_resume=%d\n", this->has_pause_resume); this->sample_rate_factor = (double) this->output_sample_rate / (double) this->input_sample_rate; this->bytes_per_frame = snd_pcm_frames_to_bytes (this->audio_fd, 1); @@ -568,28 +568,28 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int /* Copy current parameters into swparams */ err = snd_pcm_sw_params_current(this->audio_fd, swparams); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Unable to determine current swparams: %s\n", snd_strerror(err)); goto close; } /* align all transfers to 1 sample */ err = snd_pcm_sw_params_set_xfer_align(this->audio_fd, swparams, 1); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Unable to set transfer alignment: %s\n", snd_strerror(err)); goto close; } /* allow the transfer when at least period_size samples can be processed */ err = snd_pcm_sw_params_set_avail_min(this->audio_fd, swparams, period_size); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Unable to set available min: %s\n", snd_strerror(err)); goto close; } /* start the transfer when the buffer contains at least period_size samples */ err = snd_pcm_sw_params_set_start_threshold(this->audio_fd, swparams, period_size); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Unable to set start threshold: %s\n", snd_strerror(err)); goto close; } @@ -597,7 +597,7 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int /* never stop the transfer, even on xruns */ err = snd_pcm_sw_params_set_stop_threshold(this->audio_fd, swparams, this->buffer_size); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Unable to set stop threshold: %s\n", snd_strerror(err)); goto close; } @@ -605,15 +605,15 @@ static int ao_alsa_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int /* Install swparams into current parameters */ err = snd_pcm_sw_params(this->audio_fd, swparams); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Unable to set swparams: %s\n", snd_strerror(err)); goto close; } #ifdef ALSA_LOG - snd_pcm_dump_setup(this->audio_fd, jcd_out); + snd_pcm_dump_setup(this->audio_fd, jcd_out); snd_pcm_sw_params_dump(swparams, jcd_out); #endif - + return this->output_sample_rate; close: @@ -648,7 +648,7 @@ static int ao_alsa_get_gap_tolerance (ao_driver_t *this_gen) { /* * Return the delay. is frames measured by looking at pending samples */ -/* FIXME: delay returns invalid data if status is not RUNNING. +/* FIXME: delay returns invalid data if status is not RUNNING. * e.g When there is an XRUN or we are in PREPARED mode. */ static int ao_alsa_delay (ao_driver_t *this_gen) { @@ -678,12 +678,12 @@ static int ao_alsa_delay (ao_driver_t *this_gen) { /* * Handle over/under-run */ -static void xrun(alsa_driver_t *this) +static void xrun(alsa_driver_t *this) { /* snd_pcm_status_t *status; */ int res; - /* + /* snd_pcm_status_alloca(&status); if ((res = snd_pcm_status(this->audio_fd, status))<0) { printf ("audio_alsa_out: status error: %s\n", snd_strerror(res)); @@ -759,7 +759,7 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { #ifdef LOG_DEBUG printf("audio_alsa_out:write:XRUN before\n"); snd_pcm_status(this->audio_fd, pcm_stat); - snd_pcm_status_dump(pcm_stat, jcd_out); + snd_pcm_status_dump(pcm_stat, jcd_out); #endif if ((res = snd_pcm_prepare(this->audio_fd))<0) { return 0; @@ -771,14 +771,14 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { #ifdef LOG_DEBUG printf("audio_alsa_out:write:XRUN after\n"); #endif - } + } if ( (state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING) && (state != SND_PCM_STATE_DRAINING) ) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out:write:BAD STATE, state = %d\n",state); } - + while( number_of_frames > 0) { if ( (state == SND_PCM_STATE_RUNNING) ) { #ifdef LOG_DEBUG @@ -816,7 +816,7 @@ static int ao_alsa_write(ao_driver_t *this_gen, int16_t *data, uint32_t count) { } else if ( (state != SND_PCM_STATE_PREPARED) && (state != SND_PCM_STATE_RUNNING) && (state != SND_PCM_STATE_DRAINING) ) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out:write:BAD STATE2, state = %d, going to try XRUN\n",state); if ((res = snd_pcm_prepare(this->audio_fd))<0) { xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, @@ -895,7 +895,7 @@ static void ao_alsa_exit(ao_driver_t *this_gen) { this->mixer.handle=0; } pthread_mutex_destroy(&this->mixer.mutex); - + if (this->audio_fd) snd_pcm_close(this->audio_fd); this->audio_fd=NULL; free (this); @@ -913,45 +913,45 @@ static int ao_alsa_get_property (ao_driver_t *this_gen, int property) { case AO_PROP_PCM_VOL: if(this->mixer.elem) { int vol; - + pthread_mutex_lock(&this->mixer.mutex); if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &this->mixer.left_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); goto done; } - + if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &this->mixer.right_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); goto done; } - + done: vol = (((ao_alsa_get_percent_from_volume(this->mixer.left_vol, this->mixer.min, this->mixer.max)) + (ao_alsa_get_percent_from_volume(this->mixer.right_vol, this->mixer.min, this->mixer.max))) /2); pthread_mutex_unlock(&this->mixer.mutex); - + return vol; } break; - + case AO_PROP_MUTE_VOL: { int mute; - + pthread_mutex_lock(&this->mixer.mutex); mute = ((this->mixer.mute & MIXER_HAS_MUTE_SWITCH) && (this->mixer.mute & MIXER_MASK_MUTE)) ? 1 : 0; pthread_mutex_unlock(&this->mixer.mutex); - + return mute; } break; } - + return 0; } @@ -970,18 +970,18 @@ static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value) pthread_mutex_lock(&this->mixer.mutex); this->mixer.left_vol = this->mixer.right_vol = ao_alsa_get_volume_from_percent(value, this->mixer.min, this->mixer.max); - + if((err = snd_mixer_selem_set_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, this->mixer.left_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); pthread_mutex_unlock(&this->mixer.mutex); return ~value; } - + if((err = snd_mixer_selem_set_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, this->mixer.right_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); pthread_mutex_unlock(&this->mixer.mutex); return ~value; @@ -997,20 +997,20 @@ static int ao_alsa_set_property (ao_driver_t *this_gen, int property, int value) if(this->mixer.mute & MIXER_HAS_MUTE_SWITCH) { int swl = 0, swr = 0; int old_mute; - + pthread_mutex_lock(&this->mixer.mutex); - + old_mute = this->mixer.mute; if(value) this->mixer.mute |= MIXER_MASK_MUTE; else this->mixer.mute &= ~MIXER_MASK_MUTE; - + if ((this->mixer.mute & MIXER_MASK_MUTE) != (old_mute & MIXER_MASK_MUTE)) { if(this->mixer.mute & MIXER_MASK_STEREO) { snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); snd_mixer_selem_set_playback_switch_all(this->mixer.elem, !swl); - } + } else { if (this->mixer.mute & MIXER_MASK_LEFT) { snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); @@ -1050,7 +1050,7 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) { if (this->audio_fd) { if (this->has_pause_resume) { if ((err=snd_pcm_pause(this->audio_fd, 1)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Pause call failed. (err=%d:%s)\n",err, snd_strerror(err)); this->has_pause_resume = 0; ao_alsa_ctrl(this_gen, AO_CTRL_PLAY_PAUSE, NULL); @@ -1059,15 +1059,15 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) { } } else { if ((err=snd_pcm_reset(this->audio_fd)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Reset call failed. (err=%d:%s)\n",err, snd_strerror(err)); } if ((err=snd_pcm_drain(this->audio_fd)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Drain call failed. (err=%d:%s)\n",err, snd_strerror(err)); } if ((err=snd_pcm_prepare(this->audio_fd)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Prepare call failed. (err=%d:%s)\n",err, snd_strerror(err)); } } @@ -1079,12 +1079,12 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) { if (this->has_pause_resume && this->is_paused) { if ((err=snd_pcm_pause(this->audio_fd, 0)) < 0) { if (err == -77) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Warning: How am I supposed to RESUME, if I am not PAUSED. " "audio_out.c, please don't call me!\n"); break; } - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Resume call failed. (err=%d:%s)\n",err, snd_strerror(err)); this->has_pause_resume = 0; } else { @@ -1097,11 +1097,11 @@ static int ao_alsa_ctrl(ao_driver_t *this_gen, int cmd, ...) { case AO_CTRL_FLUSH_BUFFERS: if (this->audio_fd) { if ((err=snd_pcm_drop(this->audio_fd)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Drop call failed. (err=%d:%s)\n",err, snd_strerror(err)); } if ((err=snd_pcm_prepare(this->audio_fd)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: Prepare call failed. (err=%d:%s)\n",err, snd_strerror(err)); } } @@ -1129,43 +1129,43 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { int found; int swl = 0, swr = 0, send_events; - this->mixer.elem = 0; + this->mixer.elem = 0; snd_ctl_card_info_alloca(&hw_info); pcm_device = config->lookup_entry(config, "audio.device.alsa_default_device")->str_value; if ((err = snd_ctl_open (&ctl_handle, pcm_device, 0)) < 0) { xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_ctl_open(): %s\n", snd_strerror(err)); return; } - + if ((err = snd_ctl_card_info (ctl_handle, hw_info)) < 0) { xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_ctl_card_info(): %s\n", snd_strerror(err)); snd_ctl_close(ctl_handle); return; } - + snd_ctl_close (ctl_handle); - /* + /* * Open mixer device */ if ((err = snd_mixer_open (&this->mixer.handle, 0)) < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_open(): %s\n", snd_strerror(err)); this->mixer.handle=0; return; } - + if ((err = snd_mixer_attach (this->mixer.handle, pcm_device)) < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_attach(): %s\n", snd_strerror(err)); snd_mixer_close(this->mixer.handle); this->mixer.handle=0; return; } - + if ((err = snd_mixer_selem_register (this->mixer.handle, NULL, NULL)) < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_register(): %s\n", snd_strerror(err)); snd_mixer_close(this->mixer.handle); this->mixer.handle=0; @@ -1173,77 +1173,77 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { } if ((err = snd_mixer_load (this->mixer.handle)) < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_load(): %s\n", snd_strerror(err)); snd_mixer_close(this->mixer.handle); this->mixer.handle=0; return; } - + mixer_sid = alloca(snd_mixer_selem_id_sizeof() * snd_mixer_get_count(this->mixer.handle)); if (mixer_sid == NULL) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: alloca() failed: %s\n", strerror(errno)); snd_mixer_close(this->mixer.handle); this->mixer.handle=0; return; } - + again: found = 0; mixer_n_selems = 0; for (elem = snd_mixer_first_elem(this->mixer.handle); elem; elem = snd_mixer_elem_next(elem)) { sid = (snd_mixer_selem_id_t *)(((char *)mixer_sid) + snd_mixer_selem_id_sizeof() * mixer_n_selems); - + if ((snd_mixer_elem_get_type(elem) != SND_MIXER_ELEM_SIMPLE) || !snd_mixer_selem_is_active(elem)) continue; - + snd_mixer_selem_get_id(elem, sid); mixer_n_selems++; if(!strcmp((snd_mixer_selem_get_name(elem)), this->mixer.name)) { /* printf("found %s\n", snd_mixer_selem_get_name(elem)); */ - + this->mixer.elem = elem; - - snd_mixer_selem_get_playback_volume_range(this->mixer.elem, + + snd_mixer_selem_get_playback_volume_range(this->mixer.elem, &this->mixer.min, &this->mixer.max); if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &this->mixer.left_vol)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); this->mixer.elem = NULL; continue; } - + if((err = snd_mixer_selem_get_playback_volume(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &this->mixer.right_vol)) < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: snd_mixer_selem_get_playback_volume(): %s\n", snd_strerror(err)); this->mixer.elem = NULL; continue; } - + /* Channels mute */ this->mixer.mute = 0; if(snd_mixer_selem_has_playback_switch(this->mixer.elem)) { this->mixer.mute |= MIXER_HAS_MUTE_SWITCH; - + if (snd_mixer_selem_has_playback_switch_joined(this->mixer.elem)) { this->mixer.mute |= MIXER_MASK_STEREO; snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); - } + } else { this->mixer.mute |= MIXER_MASK_LEFT; snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_LEFT, &swl); - + if (SND_MIXER_SCHN_FRONT_RIGHT != SND_MIXER_SCHN_UNKNOWN) { this->mixer.mute |= MIXER_MASK_RIGHT; snd_mixer_selem_get_playback_switch(this->mixer.elem, SND_MIXER_SCHN_FRONT_RIGHT, &swr); } - + if(!swl || !swr) this->mixer.mute |= MIXER_MASK_MUTE; } @@ -1256,10 +1256,10 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { goto mixer_found; } } - + if(loop) goto mixer_found; /* Yes, untrue but... ;-) */ - + if(!strcmp(this->mixer.name, "PCM")) { config->update_string(config, "audio.device.alsa_mixer_name", "Master"); loop++; @@ -1267,14 +1267,14 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { else { config->update_string(config, "audio.device.alsa_mixer_name", "PCM"); } - + this->mixer.name = config->lookup_entry(config, "audio.device.alsa_mixer_name")->str_value; - + goto again; mixer_found: - - /* + + /* * Ugly: yes[*] no[ ] */ if(found) { @@ -1301,11 +1301,11 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { if (send_events && found) { pthread_attr_t pth_attrs; struct sched_param pth_params; - + this->mixer.running = 1; pthread_attr_init(&pth_attrs); - + pthread_attr_getschedparam(&pth_attrs, &pth_params); pth_params.sched_priority = sched_get_priority_min(SCHED_OTHER); pthread_attr_setschedparam(&pth_attrs, &pth_params); @@ -1317,7 +1317,7 @@ static void ao_alsa_mixer_init(ao_driver_t *this_gen) { } static void alsa_speaker_arrangement_cb (void *user_data, - xine_cfg_entry_t *entry); + xine_cfg_entry_t *entry); /* * Initialize plugin @@ -1350,7 +1350,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da #define A52_PASSTHRU 12 int speakers; - this = (alsa_driver_t *) xine_xmalloc (sizeof (alsa_driver_t)); + this = calloc(1, sizeof (alsa_driver_t)); if (!this) return NULL; @@ -1358,8 +1358,8 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da err = snd_lib_error_set_handler(error_callback); if(err < 0) - xine_log(this->class->xine, XINE_LOG_MSG, _("snd_lib_error_set_handler() failed: %d"), err); - + xine_log(this->class->xine, XINE_LOG_MSG, _("snd_lib_error_set_handler() failed: %d"), err); + snd_pcm_hw_params_alloca(¶ms); this->mmap = config->register_bool (config, @@ -1424,7 +1424,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da /* Use the default device to open first */ pcm_device = config->lookup_entry(config, "audio.device.alsa_default_device")->str_value; - + /* * find best device driver/channel */ @@ -1434,11 +1434,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da err=snd_pcm_open(&this->audio_fd, pcm_device, SND_PCM_STREAM_PLAYBACK, 1); /* NON-BLOCK mode */ if(err <0 ) { xine_log (this->class->xine, XINE_LOG_MSG, - _("snd_pcm_open() failed:%d:%s\n"), err, snd_strerror(err)); + _("snd_pcm_open() failed:%d:%s\n"), err, snd_strerror(err)); xine_log (this->class->xine, XINE_LOG_MSG, - _(">>> Check if another program already uses PCM <<<\n")); + _(">>> Check if another program already uses PCM <<<\n")); free(this); - return NULL; + return NULL; } /* @@ -1446,7 +1446,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da */ err = snd_pcm_hw_params_any(this->audio_fd, params); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: broken configuration for this PCM: no configurations available\n"); snd_pcm_close(this->audio_fd); free(this); @@ -1455,7 +1455,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da err = snd_pcm_hw_params_set_access(this->audio_fd, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (err < 0) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, "audio_alsa_out: access type not available"); snd_pcm_close(this->audio_fd); free(this); @@ -1497,70 +1497,73 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da "formats you want to play to your sound card's digital output."), 0, alsa_speaker_arrangement_cb, this); - xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_alsa_out : supported modes are ")); + char *logmsg = strdup (_("audio_alsa_out : supported modes are")); + if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_U8))) { this->capabilities |= AO_CAP_8BITS; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("8bit ")); + xine_strcat_realloc (&logmsg, _(" 8bit")); } /* ALSA automatically appends _LE or _BE depending on the CPU */ if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_S16))) { this->capabilities |= AO_CAP_16BITS; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("16bit ")); + xine_strcat_realloc (&logmsg, _(" 16bit")); } if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_S24))) { this->capabilities |= AO_CAP_24BITS; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("24bit ")); + xine_strcat_realloc (&logmsg, _(" 24bit")); } if (!(snd_pcm_hw_params_test_format(this->audio_fd, params, SND_PCM_FORMAT_FLOAT))) { this->capabilities |= AO_CAP_FLOAT32; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("32bit ")); + xine_strcat_realloc (&logmsg, _(" 32bit")); } if (0 == (this->capabilities & (AO_CAP_FLOAT32 | AO_CAP_24BITS | AO_CAP_16BITS | AO_CAP_8BITS))) { - xprintf (this->class->xine, XINE_VERBOSITY_DEBUG, - "\naudio_alsa_out: no supported PCM format found\n"); + xprintf(class->xine, XINE_VERBOSITY_LOG, "%s\n", logmsg); + free (logmsg); + xprintf (class->xine, XINE_VERBOSITY_DEBUG, + "audio_alsa_out: no supported PCM format found\n"); snd_pcm_close(this->audio_fd); free(this); return NULL; } if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 1))) { this->capabilities |= AO_CAP_MODE_MONO; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("mono ")); + xine_strcat_realloc (&logmsg, _(" mono")); } if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 2))) { this->capabilities |= AO_CAP_MODE_STEREO; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("stereo ")); + xine_strcat_realloc (&logmsg, _(" stereo")); } if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 4)) && ( speakers == SURROUND4 )) { this->capabilities |= AO_CAP_MODE_4CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("4-channel ")); - } + xine_strcat_realloc (&logmsg, _(" 4-channel")); + } else - xprintf(class->xine, XINE_VERBOSITY_LOG, _("(4-channel not enabled in xine config) ")); - - if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) && + xine_strcat_realloc (&logmsg, _(" (4-channel not enabled in xine config)")); + + if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) && ( speakers == SURROUND41 )) { this->capabilities |= AO_CAP_MODE_4_1CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("4.1-channel ")); - } + xine_strcat_realloc (&logmsg, _(" 4.1-channel")); + } else - xprintf(class->xine, XINE_VERBOSITY_LOG, _("(4.1-channel not enabled in xine config) ")); + xine_strcat_realloc (&logmsg, _(" (4.1-channel not enabled in xine config)")); - if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) && + if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) && ( speakers == SURROUND5 )) { this->capabilities |= AO_CAP_MODE_5CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("5-channel ")); - } + xine_strcat_realloc (&logmsg, _(" 5-channel")); + } else - xprintf(class->xine, XINE_VERBOSITY_LOG, _("(5-channel not enabled in xine config) ")); + xine_strcat_realloc (&logmsg, _(" (5-channel not enabled in xine config)")); - if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) && + if (!(snd_pcm_hw_params_test_channels(this->audio_fd, params, 6)) && ( speakers >= SURROUND51 )) { this->capabilities |= AO_CAP_MODE_5_1CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("5.1-channel ")); - } + xine_strcat_realloc (&logmsg, _(" 5.1-channel")); + } else - xprintf(class->xine, XINE_VERBOSITY_LOG, _("(5.1-channel not enabled in xine config) ")); + xine_strcat_realloc (&logmsg, _(" (5.1-channel not enabled in xine config)")); this->has_pause_resume = 0; /* This is checked at open time instead */ this->is_paused = 0; @@ -1583,10 +1586,13 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da if ( speakers == A52_PASSTHRU ) { this->capabilities |= AO_CAP_MODE_A52; this->capabilities |= AO_CAP_MODE_AC5; - xprintf(class->xine, XINE_VERBOSITY_LOG, _("a/52 and DTS pass-through\n")); - } + xine_strcat_realloc (&logmsg, _(" a/52 and DTS pass-through")); + } else - xprintf(class->xine, XINE_VERBOSITY_LOG, _("(a/52 and DTS pass-through not enabled in xine config)\n")); + xine_strcat_realloc (&logmsg, _(" (a/52 and DTS pass-through not enabled in xine config)")); + + xprintf(class->xine, XINE_VERBOSITY_LOG, "%s\n", logmsg); + free (logmsg); /* printf("audio_alsa_out: capabilities 0x%X\n",this->capabilities); */ @@ -1616,7 +1622,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da this->ao_driver.num_channels = ao_alsa_num_channels; this->ao_driver.bytes_per_frame = ao_alsa_bytes_per_frame; this->ao_driver.delay = ao_alsa_delay; - this->ao_driver.write = ao_alsa_write; + this->ao_driver.write = ao_alsa_write; this->ao_driver.close = ao_alsa_close; this->ao_driver.exit = ao_alsa_exit; this->ao_driver.get_gap_tolerance = ao_alsa_get_gap_tolerance; @@ -1682,7 +1688,7 @@ static void *init_class (xine_t *xine, void *data) { alsa_class_t *this; - this = (alsa_class_t *) xine_xmalloc (sizeof (alsa_class_t)); + this = calloc(1, sizeof (alsa_class_t)); if (!this) return NULL; @@ -1705,7 +1711,7 @@ static ao_info_t ao_info_alsa = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_ALSA_IFACE_VERSION, "alsa", XINE_VERSION_CODE, &ao_info_alsa, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_arts_out.c b/src/audio_out/audio_arts_out.c index 0f0467b4a..7f796f2b3 100644 --- a/src/audio_out/audio_arts_out.c +++ b/src/audio_out/audio_arts_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -42,7 +42,7 @@ #define AUDIO_NUM_FRAGMENTS 15 #define AUDIO_FRAGMENT_SIZE 8192 -#define GAP_TOLERANCE AO_MAX_GAP +#define GAP_TOLERANCE AO_MAX_GAP typedef struct arts_driver_s { @@ -84,7 +84,7 @@ typedef struct { static void ao_arts_volume(void *buffer, int length, int volume) { int v; short *data = (short *)buffer; - + while (length--) { v=(int) ((*(data) * volume) / 100); *(data)=(v>32767) ? 32767 : ((v<-32768) ? -32768 : v); @@ -118,7 +118,7 @@ static int ao_arts_open(ao_driver_t *this_gen, sleep(2); /* arts might segfault if we are still playing */ arts_close_stream(this->audio_stream); } - + this->mode = mode; this->sample_rate = rate; this->bits_per_sample = bits; @@ -139,7 +139,7 @@ static int ao_arts_open(ao_driver_t *this_gen, this->audio_stream=arts_play_stream(this->sample_rate, bits, this->num_channels, "xine"); this->latency = arts_stream_get (this->audio_stream, ARTS_P_TOTAL_LATENCY); - + /* try to keep latency low, if we don't do this we might end with very high latencies for low quality sound and audio_out will try to fill gaps every time...(values in ms) */ @@ -181,7 +181,7 @@ static int ao_arts_write(ao_driver_t *this_gen, int16_t *data, arts_driver_t *this = (arts_driver_t *) this_gen; int size = num_frames * this->bytes_per_frame; - ao_arts_volume(data, num_frames * this->num_channels, this->mixer.vol_scale ); + ao_arts_volume(data, num_frames * this->num_channels, this->mixer.vol_scale ); arts_write(this->audio_stream, data, size ); return 1; @@ -220,7 +220,7 @@ static uint32_t ao_arts_get_capabilities (ao_driver_t *this_gen) { static void ao_arts_exit(ao_driver_t *this_gen) { arts_driver_t *this = (arts_driver_t *) this_gen; - + ao_arts_close(this_gen); /* FIXME: arts_free() freezes on BSD, so don't use it there */ #if !defined(__OpenBSD__) && !defined (__FreeBSD__) && !defined(__NetBSD__) @@ -233,7 +233,7 @@ static void ao_arts_exit(ao_driver_t *this_gen) static int ao_arts_get_property (ao_driver_t *this_gen, int property) { arts_driver_t *this = (arts_driver_t *) this_gen; - + switch(property) { case AO_PROP_PCM_VOL: case AO_PROP_MIXER_VOL: @@ -269,7 +269,7 @@ static int ao_arts_set_property (ao_driver_t *this_gen, int property, int value) } else { this->mixer.volume = this->mixer.v_mixer; this->mixer.vol_scale = this->mixer.volume; - } + } this->mixer.mute = mute; return value; break; @@ -303,7 +303,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da lprintf ("audio_arts_out: open_plugin called\n"); - this = (arts_driver_t *) xine_xmalloc (sizeof (arts_driver_t)); + this = calloc(1, sizeof (arts_driver_t)); if (!this) return NULL; @@ -323,7 +323,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da free(this); return NULL; } - + /* * set volume control */ @@ -384,7 +384,7 @@ static void *init_class (xine_t *xine, void *data) { lprintf ("audio_arts_out: init class\n"); - this = (arts_class_t *) xine_xmalloc (sizeof (arts_class_t)); + this = calloc(1, sizeof (arts_class_t)); if (!this) return NULL; @@ -409,7 +409,7 @@ static ao_info_t ao_info_arts = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_ARTS_IFACE_VERSION, "arts", XINE_VERSION_CODE, &ao_info_arts, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_coreaudio_out.c b/src/audio_out/audio_coreaudio_out.c index eecab8f95..5e31a15e5 100644 --- a/src/audio_out/audio_coreaudio_out.c +++ b/src/audio_out/audio_coreaudio_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -54,7 +54,7 @@ #define AO_OUT_COREAUDIO_IFACE_VERSION 8 -#define GAP_TOLERANCE AO_MAX_GAP +#define GAP_TOLERANCE AO_MAX_GAP #define BUFSIZE 30720 /* Number of seconds to wait for buffered data to arrive/be used * before giving up. */ @@ -75,7 +75,7 @@ typedef struct coreaudio_driver_s { Component au_component; Component converter_component; - + AudioUnit au_unit; AudioUnit converter_unit; @@ -86,7 +86,7 @@ typedef struct coreaudio_driver_s { int mute; Float32 pre_mute_volume; - + pthread_mutex_t mutex; pthread_cond_t buffer_ready_for_reading; pthread_cond_t buffer_ready_for_writing; @@ -131,7 +131,7 @@ static OSStatus ao_coreaudio_render_proc (coreaudio_driver_t *this, pthread_mutex_lock (&this->mutex); if(this->buf_head < ((BUFSIZE) >> 2)) { set_to_future(&future); - if(pthread_cond_timedwait + if(pthread_cond_timedwait (&this->buffer_ready_for_reading, &this->mutex, &future) == ETIMEDOUT) { /* Timed out, give up and fill remainder with silence. */ @@ -143,13 +143,13 @@ static OSStatus ao_coreaudio_render_proc (coreaudio_driver_t *this, return noErr; } } - + if(this->buf_head < buffer_size - buffer_progress) { chunk_size = this->buf_head; } else { chunk_size = buffer_size - buffer_progress; } - + xine_fast_memcpy (ioData->mBuffers[i].mData, this->buf, chunk_size); if(chunk_size < this->buf_head) { memmove(this->buf, &(this->buf[chunk_size]), this->buf_head - chunk_size); @@ -188,7 +188,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate AudioStreamBasicDescription format; AudioUnitConnection connection; ComponentDescription desc; - + switch (mode) { case AO_CAP_MODE_MONO: this->num_channels = 1; @@ -209,7 +209,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate pthread_cond_init (&this->buffer_ready_for_reading, NULL); pthread_cond_init (&this->buffer_ready_for_writing, NULL); - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_coreaudio_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); /* find an audio output unit */ @@ -218,17 +218,17 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; - + this->au_component = FindNextComponent (NULL, &desc); if (this->au_component == NULL) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_coreaudio_out: Unable to find a usable audio output unit component\n"); return 0; } - + OpenAComponent (this->au_component, &this->au_unit); - + /* find a converter unit */ desc.componentType = kAudioUnitType_FormatConverter; desc.componentSubType = kAudioUnitSubType_AUConverter; @@ -236,11 +236,11 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate this->converter_component = FindNextComponent (NULL, &desc); if (this->converter_component == NULL) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_coreaudio_out: Unable to find a usable audio converter unit component\n"); return 0; } - + OpenAComponent (this->converter_component, &this->converter_unit); /* set up the render procedure */ @@ -258,7 +258,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate connection.destInputNumber = 0; AudioUnitSetProperty (this->au_unit, kAudioUnitProperty_MakeConnection, - kAudioUnitScope_Input, 0, + kAudioUnitScope_Input, 0, &connection, sizeof(connection)); /* set up the audio format we want to use */ @@ -274,7 +274,7 @@ static int ao_coreaudio_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate format.mBytesPerFrame = this->bytes_per_frame; format.mFramesPerPacket = 1; format.mBytesPerPacket = format.mBytesPerFrame; - + AudioUnitSetProperty (this->converter_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, @@ -339,7 +339,7 @@ static int ao_coreaudio_write(ao_driver_t *this_gen, int16_t *data, pthread_mutex_lock (&this->mutex); if(this->buf_head > ((3 * BUFSIZE)>>2)) { set_to_future(&future); - if(pthread_cond_timedwait + if(pthread_cond_timedwait (&this->buffer_ready_for_writing, &this->mutex, &future) == ETIMEDOUT) { /* Timed out, give up. */ @@ -354,10 +354,10 @@ static int ao_coreaudio_write(ao_driver_t *this_gen, int16_t *data, } else { chunk_size = remaining_bytes; } - + xine_fast_memcpy(&(this->buf[this->buf_head]), data, chunk_size); this->buf_head += chunk_size; - remaining_bytes -= chunk_size; + remaining_bytes -= chunk_size; if(this->buf_head > 0) { pthread_cond_broadcast (&this->buffer_ready_for_reading); @@ -389,13 +389,13 @@ static void ao_coreaudio_close(ao_driver_t *this_gen) CloseComponent (this->au_unit); this->au_unit = 0; } - + if (this->converter_unit) { AudioUnitUninitialize (this->converter_unit); CloseComponent (this->converter_unit); this->converter_unit = 0; } - + if (this->au_component) { this->au_component = NULL; } @@ -417,7 +417,7 @@ static uint32_t ao_coreaudio_get_capabilities (ao_driver_t *this_gen) { static void ao_coreaudio_exit(ao_driver_t *this_gen) { coreaudio_driver_t *this = (coreaudio_driver_t *) this_gen; - + ao_coreaudio_close(this_gen); free (this); @@ -436,7 +436,7 @@ static int ao_coreaudio_get_property (ao_driver_t *this_gen, int property) { kAudioUnitScope_Output, 0, &val); } else { - val = this->pre_mute_volume; + val = this->pre_mute_volume; } return (int) (val * 12); break; @@ -472,12 +472,12 @@ static int ao_coreaudio_set_property (ao_driver_t *this_gen, int property, int v kHALOutputParam_Volume, kAudioUnitScope_Output, 0, &(this->pre_mute_volume)); - + AudioUnitSetParameter (this->au_unit, kHALOutputParam_Volume, kAudioUnitScope_Output, 0, 0, 0); - + this->mute = 1; } } else { @@ -487,14 +487,14 @@ static int ao_coreaudio_set_property (ao_driver_t *this_gen, int property, int v kHALOutputParam_Volume, kAudioUnitScope_Output, 0, this->pre_mute_volume, 0); - + this->mute = 0; } } return value; break; } - + return ~value; } @@ -521,7 +521,7 @@ static int ao_coreaudio_ctrl(ao_driver_t *this_gen, int cmd, ...) { return 0; } -static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) { coreaudio_class_t *class = (coreaudio_class_t *) class_gen; @@ -530,7 +530,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, lprintf ("open_plugin called\n"); - this = (coreaudio_driver_t *) xine_xmalloc (sizeof (coreaudio_driver_t)); + this = calloc(1, sizeof (coreaudio_driver_t)); if (!this) return NULL; @@ -582,7 +582,7 @@ static void *init_class (xine_t *xine, void *data) { lprintf ("init class\n"); - this = (coreaudio_class_t *) xine_xmalloc (sizeof (coreaudio_class_t)); + this = calloc(1, sizeof (coreaudio_class_t)); if (!this) return NULL; @@ -606,7 +606,7 @@ static const ao_info_t ao_info_coreaudio = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_COREAUDIO_IFACE_VERSION, "coreaudio", XINE_VERSION_CODE, &ao_info_coreaudio, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_directx2_out.c b/src/audio_out/audio_directx2_out.c index d9688b647..4d7fe4e65 100644 --- a/src/audio_out/audio_directx2_out.c +++ b/src/audio_out/audio_directx2_out.c @@ -31,6 +31,9 @@ * * Authors: * - Frantisek Dvorak <valtri@atlas.cz> + * - Original version with slotted ring buffer + * - Matthias Ringald <mringwal@inf.ethz.ch> + * - non-slotted simpler version for ring buffer handling * * Inspiration: * - mplayer for workarounding -lguid idea @@ -55,8 +58,8 @@ #define LOG_MODULE "audio_directx2_out" #define LOG_VERBOSE /* -#define LOG -*/ + #define LOG + */ #include "xine_internal.h" #include "audio_out.h" @@ -64,29 +67,33 @@ #define AO_OUT_DIRECTX2_IFACE_VERSION 8 -/* - * buffer size in miliseconds - * (one second takes 11-192 KB) + +/* + * If GAP_TOLERANCE is lower than AO_MAX_GAP, xine will + * try to smooth playback without skipping frames or + * inserting silence. + */ +#define GAP_TOLERANCE (AO_MAX_GAP/3) + +/* + * buffer size in miliseconds + * (one second takes 11-192 KB) */ #define BUFFER_MS 1000 -/* - * number of parts in the buffer, - * one is always locked for playing +/* + * buffer below this threshold is considered a buffer underrun */ -#define PARTS 3 +#define BUFFER_MIN_MS 200 -/* +/* * base power factor for volume remapping */ #define FACTOR 60.0 - -/* experiments */ -/*#define EXACT_WAIT*/ -/*#define EXACT_SLEEP*/ -/*#define PANIC_OVERRUN*/ - +/* + * buffer handler status + */ #define STATUS_START 0 #define STATUS_WAIT 1 #define STATUS_RUNNING 2 @@ -108,12 +115,14 @@ typedef struct { LPDIRECTSOUND ds; /* DirectSound device */ LPDIRECTSOUNDBUFFER dsbuffer; /* DirectSound buffer */ - DSBPOSITIONNOTIFY events[PARTS]; /* position events */ - LPDIRECTSOUNDNOTIFY notify; /* notify interface */ size_t buffer_size; /* size of the buffer */ - size_t part_size; /* second half of buffer */ - size_t read_size; /* size of prepared data */ + size_t write_pos; /* positition in ring buffer for writing*/ + + int status; /* current status of the driver */ + int paused; /* paused mode */ + int finished; /* driver finished */ + int failed; /* don't open modal dialog again */ uint32_t bits; uint32_t rate; @@ -123,12 +132,6 @@ typedef struct { int volume; int muted; - int status; /* current status of the driver */ - int paused; /* paused mode */ - int finished; /* driver finished */ - int failed; /* don't open modal dialog again */ - int count; /* current free part number */ - pthread_t buffer_service; /* service thread for operating with DSB */ pthread_cond_t data_cond; /* signals on data */ pthread_mutex_t data_mutex; /* data lock */ @@ -140,17 +143,19 @@ typedef struct { * Defining them here allows us to get rid of the dxguid library during * the linking stage. *****************************************************************************/ -static const GUID IID_IDirectSoundNotify = { - 0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16} +static const GUID xine_IID_IDirectSoundNotify = { +0xB0210783, 0x89CD, 0x11D0, {0xAF, 0x08, 0x00, 0xA0, 0xC9, 0x25, 0xCD, 0x16} }; +#ifdef IID_IDirectSoundNotify +# undef IID_IDirectSoundNotify +#endif +#define IID_IDirectSoundNotify xine_IID_IDirectSoundNotify -static int buffer_ready(dx2_driver_t *this); - /* popup a dialog with error */ static void XINE_FORMAT_PRINTF(1, 2) - error_message(const char *fmt, ...) { +error_message(const char *fmt, ...) { char message[256]; va_list ap; @@ -214,7 +219,7 @@ static LPDIRECTSOUND dsound_create() { /* destroy direct sound object */ static void dsound_destroy(LPDIRECTSOUND ds) { - IDirectSound_Release(ds); + IDirectSound_Release(ds); } @@ -266,12 +271,10 @@ static int audio_create_buffers(dx2_driver_t *this) { HRESULT err; size_t buffer_size; - buffer_size = this->rate * this->frame_size * BUFFER_MS / 1000; + buffer_size = this->rate * BUFFER_MS / 1000 * this->frame_size; if (buffer_size > DSBSIZE_MAX) buffer_size = DSBSIZE_MAX; if (buffer_size < DSBSIZE_MIN) buffer_size = DSBSIZE_MIN; - this->part_size = (buffer_size / PARTS / this->frame_size) * this->frame_size; - if (!this->part_size) this->part_size = this->frame_size; - this->buffer_size = this->part_size * PARTS; + this->buffer_size = buffer_size; flags = DSBCAPS_GLOBALFOCUS | DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY; dsound_fill_wfx(&wfx, this->bits, this->rate, this->channels, this->frame_size); @@ -282,7 +285,7 @@ static int audio_create_buffers(dx2_driver_t *this) { return 0; } - lprintf("created direct sound buffer, size = %u, part = %u\n", this->buffer_size, this->part_size); + lprintf("created direct sound buffer, size = %u\n", this->buffer_size); return 1; } @@ -293,43 +296,6 @@ static void audio_destroy_buffers(dx2_driver_t *this) { } -/* create position events */ -static int audio_create_events(dx2_driver_t *this) { - HANDLE handle[PARTS]; - HRESULT err; - int i; - - for (i = 0; i < PARTS; i++) { - handle[i] = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!handle[i]) { - error_message(_("Unable to create buffer position events.")); - return 0; - } - this->events[i].dwOffset = i * this->part_size; - this->events[i].hEventNotify = handle[i]; - } - - if ((err = IDirectSoundBuffer_QueryInterface(this->dsbuffer, &IID_IDirectSoundNotify, (void **)&this->notify)) != DS_OK) { - audio_error(this, err, _("Unable to get notification interface")); - return 0; - } - - if ((err = IDirectSoundNotify_SetNotificationPositions(this->notify, PARTS, this->events)) != DS_OK) { - audio_error(this, err, _("Unable to set notification positions")); - IDirectSoundNotify_Release(this->notify); - return 0; - } - - return 1; -} - - -/* destroy notification interface */ -static void audio_destroy_events(dx2_driver_t *this) { - IDirectSoundNotify_Release(this->notify); -} - - /* start playback */ static int audio_play(dx2_driver_t *this) { HRESULT err; @@ -385,13 +351,12 @@ static int audio_seek(dx2_driver_t *this, size_t pos) { /* flush audio buffers */ static int audio_flush(dx2_driver_t *this) { this->status = STATUS_WAIT; - this->count = 0; - this->read_size = 0; + this->write_pos = 0; return audio_seek(this, 0); } -/* +/* * set the volume * * DirecSound can only lower the volume by software way. @@ -421,12 +386,12 @@ static int audio_fill(dx2_driver_t *this, char *data, size_t size) { HRESULT err; /* lock a part of the buffer, begin position on free space */ - err = IDirectSoundBuffer_Lock(this->dsbuffer, (this->count * this->part_size + this->read_size) % this->buffer_size, size, &ptr1, &size1, &ptr2, &size2, 0); + err = IDirectSoundBuffer_Lock(this->dsbuffer, this->write_pos, size, &ptr1, &size1, &ptr2, &size2, 0); /* try to restore the buffer, if necessary */ if (err == DSERR_BUFFERLOST) { xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": buffer lost, tryig to restore\n")); IDirectSoundBuffer_Restore(this->dsbuffer); - err = IDirectSoundBuffer_Lock(this->dsbuffer, (this->count * this->part_size + this->read_size) % this->buffer_size, size, &ptr1, &size1, &ptr2, &size2, 0); } + err = IDirectSoundBuffer_Lock(this->dsbuffer, this->write_pos, size, &ptr1, &size1, &ptr2, &size2, 0); } if (err != DS_OK) { audio_error(this, err, _("Couldn't lock direct sound buffer")); return 0; @@ -436,19 +401,15 @@ static int audio_fill(dx2_driver_t *this, char *data, size_t size) { if (ptr1 && size1) xine_fast_memcpy(ptr1, data, size1); if (ptr2 && size2) xine_fast_memcpy(ptr2, data + size1, size2); - this->read_size += size; + // this->read_size += size; + this->write_pos = (this->write_pos + size ) % this->buffer_size; + lprintf("size %u, write_pos %u\n", size, this->write_pos); if ((err = IDirectSoundBuffer_Unlock(this->dsbuffer, ptr1, size1, ptr2, size2)) != DS_OK) { audio_error(this, err, _("Couldn't unlock direct sound buffer")); return 0; } - /* signal, if are waiting and need wake up */ - if ((this->status == STATUS_WAIT) && buffer_ready(this)) { - lprintf("buffer ready, waking up\n"); - pthread_cond_signal(&this->data_cond); - } - return 1; } @@ -458,28 +419,28 @@ static int mode2channels(uint32_t mode) { int channels; switch(mode) { - case AO_CAP_MODE_MONO: - channels = 1; - break; - - case AO_CAP_MODE_STEREO: - channels = 2; - break; - - case AO_CAP_MODE_4CHANNEL: - channels = 4; - break; - - case AO_CAP_MODE_5CHANNEL: - channels = 5; - break; - - case AO_CAP_MODE_5_1CHANNEL: - channels = 6; - break; - - default: - return 0; + case AO_CAP_MODE_MONO: + channels = 1; + break; + + case AO_CAP_MODE_STEREO: + channels = 2; + break; + + case AO_CAP_MODE_4CHANNEL: + channels = 4; + break; + + case AO_CAP_MODE_5CHANNEL: + channels = 5; + break; + + case AO_CAP_MODE_5_1CHANNEL: + channels = 6; + break; + + default: + return 0; } return channels; @@ -506,8 +467,8 @@ static int test_capability(LPDIRECTSOUNDBUFFER buffer, uint32_t bits, uint32_t r } -/* - * test capabilities of driver before opening +/* + * test capabilities of driver before opening * * Passed only 8 bit and 16 bit with mono or stereo. */ @@ -556,109 +517,94 @@ static int test_capabilities(dx2_driver_t *this) { /* size of free space in the ring buffer */ static size_t buffer_free_size(dx2_driver_t *this) { - size_t used_full_size; - used_full_size = this->read_size + ((this->status != STATUS_WAIT) ? this->part_size : 0); - _x_assert(used_full_size <= this->buffer_size); - return this->buffer_size - used_full_size; + int ret; + size_t play_pos; + size_t free_space; + + // get current play pos + ret = audio_tell(this, &play_pos); + if (!ret) + return 0; + + // calc free space (-1) + free_space = (this->buffer_size + play_pos - this->write_pos - 1) % this->buffer_size; + + return free_space; } -/* enough data in the ring buffer for playing next part? */ -static int buffer_ready(dx2_driver_t *this) { - return this->read_size >= this->part_size; +/* size of occupied space in the ring buffer */ +static size_t buffer_occupied_size(dx2_driver_t *this) { + int ret; + size_t play_pos; + size_t used_space; + + // get current play pos + ret = audio_tell(this, &play_pos); + if (!ret) return 0; + + // calc used space + used_space = (this->buffer_size + this->write_pos - play_pos) % this->buffer_size; + + return used_space; } /* service thread working with direct sound buffer */ static void *buffer_service(void *data) { dx2_driver_t *this = (dx2_driver_t *)data; - HANDLE handles[PARTS]; - DWORD ret; - int i; -#if defined(EXACT_SLEEP) || defined(EXACT_WAIT) - size_t play_pos, req_delay; -#endif + size_t buffer_min; + size_t data_in_buffer; /* prepare empty buffer */ audio_flush(this); - for (i = 0; i < PARTS; i++) handles[i] = this->events[i].hEventNotify; - + /* prepare min buffer fill */ + buffer_min = BUFFER_MIN_MS * this->rate / 1000 * this->frame_size; + /* we live! */ pthread_mutex_lock(&this->data_mutex); pthread_cond_signal(&this->data_cond); pthread_mutex_unlock(&this->data_mutex); while (!this->finished) { + pthread_mutex_lock(&this->data_mutex); - if (!buffer_ready(this)) { - if (!audio_stop(this)) goto fail; - lprintf("no data (count=%d,free=%" PRIsizet ",avail=%" PRIsizet "), sleeping...\n", this->count, buffer_free_size(this), this->read_size); - this->status = STATUS_WAIT; - pthread_cond_wait(&this->data_cond, &this->data_mutex); - lprintf("wake up (count=%d,free=%" PRIsizet "--,avail=%" PRIsizet ")\n", this->count, buffer_free_size(this), this->read_size); - if (this->finished) goto finished; - if (!audio_seek(this, this->count * this->part_size)) goto fail; - if (!this->paused) { - if (!audio_play(this)) goto fail; - } - this->status = STATUS_RUNNING; - this->count = (this->count + 1) % PARTS; - this->read_size -= this->part_size; - pthread_mutex_unlock(&this->data_mutex); - lprintf("wait for playback (newcount=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", this->count, buffer_free_size(this), this->read_size); - do { - ret = WaitForMultipleObjects(PARTS, handles, FALSE, 250) - WAIT_OBJECT_0; + switch( this->status){ + + case STATUS_WAIT: + + // pre: stop/buffer flushed + lprintf("no data, sleeping...\n"); + pthread_cond_wait(&this->data_cond, &this->data_mutex); + lprintf("woke up (write_pos=%d,free=%" PRIsizet")\n", this->write_pos, buffer_free_size(this)); if (this->finished) goto finished; - } while (ret > PARTS); - lprintf("playback started (newcount=%d,ev=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", this->count, ret, buffer_free_size(this), this->read_size); - _x_assert(ret == ((PARTS + this->count - 1) % PARTS)); - } else { - this->count = (this->count + 1) % PARTS; - this->read_size -= this->part_size; - pthread_mutex_unlock(&this->data_mutex); + if (!audio_seek(this, 0)) goto fail; + if (!this->paused) { + if (!audio_play(this)) goto fail; + } + this->status = STATUS_RUNNING; + pthread_mutex_unlock(&this->data_mutex); + break; + + case STATUS_RUNNING: + + // check for buffer underrun + data_in_buffer = buffer_occupied_size(this); + if ( data_in_buffer < buffer_min){ + xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": play cursor overran (data %u, min %u), flushing buffers\n"), + data_in_buffer, buffer_min); + if (!audio_stop(this)) goto fail; + if (!audio_flush(this)) goto fail; + } + pthread_mutex_unlock(&this->data_mutex); + + // just wait BUFFER_MIN_MS before next check + xine_usec_sleep(BUFFER_MIN_MS * 1000); + break; } - lprintf("waiting for sound event(count=%d,free=%" PRIsizet ",avail=%" PRIsizet ")...\n", this->count, buffer_free_size(this), this->read_size); - do { - ret = WaitForMultipleObjects(PARTS, handles, FALSE, 250) - WAIT_OBJECT_0; - if (this->finished) goto finished; - } while (ret > PARTS); - lprintf("end wait(ev=%" PRIdword ",count=%d,free=%" PRIsizet ",avail=%" PRIsizet ")\n", ret, this->count, buffer_free_size(this), this->read_size); -#ifdef PANIC_OVERRUN - _x_abort(ret == this->count); -#else - if (ret != this->count) { - xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": play cursor overran, flushing buffers\n")); - pthread_mutex_lock(&this->data_mutex); - if (!audio_stop(this)) goto fail; - if (!audio_flush(this)) goto fail; - pthread_mutex_unlock(&this->data_mutex); - } -#endif - -#if defined(EXACT_SLEEP) || defined(EXACT_WAIT) - /* ugly hack: wait for right time, + little over for sure */ - pthread_mutex_lock(&this->data_mutex); - if (!audio_tell(this, &play_pos)) goto fail; - req_delay = (this->buffer_size + play_pos - this->count * this->part_size) % this->buffer_size; - pthread_mutex_unlock(&this->data_mutex); - if (req_delay > (this->buffer_size >> 1)) { - long delay; - - delay = 1000 * (this->buffer_size - req_delay) / (this->frame_size * this->rate) + 1 + BUFFER_MS / PARTS / 4; - xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": delayed by %ld msec\n"), delay); - printf("should be delayed %ld msec\n", delay); -#ifdef EXACT_SLEEP - xine_usec_sleep(delay * 1000); -#endif -#ifdef EXACT_WAIT - WaitForMultipleObjects(PARTS, handles, FALSE, delay); -#endif - } -#endif } - return NULL; fail: @@ -683,15 +629,15 @@ static int ao_dx2_get_property(ao_driver_t *this_gen, int property) { switch(property) { - case AO_PROP_MIXER_VOL: - case AO_PROP_PCM_VOL: - return this->volume; + case AO_PROP_MIXER_VOL: + case AO_PROP_PCM_VOL: + return this->volume; - case AO_PROP_MUTE_VOL: - return this->muted; + case AO_PROP_MUTE_VOL: + return this->muted; - default: - return 0; + default: + return 0; } } @@ -702,26 +648,26 @@ static int ao_dx2_set_property(ao_driver_t *this_gen, int property, int value) { switch(property) { - case AO_PROP_MIXER_VOL: - case AO_PROP_PCM_VOL: - lprintf("set volume to %d\n", value); - pthread_mutex_lock(&this->data_mutex); - if (!this->muted) { - if (this->dsbuffer && !audio_set_volume(this, value)) return ~value; - } - this->volume = value; - pthread_mutex_unlock(&this->data_mutex); - break; + case AO_PROP_MIXER_VOL: + case AO_PROP_PCM_VOL: + lprintf("set volume to %d\n", value); + pthread_mutex_lock(&this->data_mutex); + if (!this->muted) { + if (this->dsbuffer && !audio_set_volume(this, value)) return ~value; + } + this->volume = value; + pthread_mutex_unlock(&this->data_mutex); + break; - case AO_PROP_MUTE_VOL: - pthread_mutex_lock(&this->data_mutex); - if (this->dsbuffer && !audio_set_volume(this, value ? 0 : this->volume)) return ~value; - this->muted = value; - pthread_mutex_unlock(&this->data_mutex); - break; + case AO_PROP_MUTE_VOL: + pthread_mutex_lock(&this->data_mutex); + if (this->dsbuffer && !audio_set_volume(this, value ? 0 : this->volume)) return ~value; + this->muted = value; + pthread_mutex_unlock(&this->data_mutex); + break; - default: - return ~value; + default: + return ~value; } @@ -747,18 +693,17 @@ static int ao_dx2_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int this->status = STATUS_START; if (!audio_create_buffers(this)) return 0; - if (!audio_create_events(this)) goto fail_buffers; - if (!audio_set_volume(this, this->volume)) goto fail_events; + if (!audio_set_volume(this, this->volume)) goto fail_buffers; if (pthread_cond_init(&this->data_cond, NULL) != 0) { xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't create pthread condition: %s\n"), strerror(errno)); - goto fail_events; + goto fail_buffers; } if (pthread_mutex_init(&this->data_mutex, NULL) != 0) { xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't create pthread mutex: %s\n"), strerror(errno)); goto fail_cond; } - + /* creating the service thread and waiting for its signal */ pthread_mutex_lock(&this->data_mutex); if (pthread_create(&this->buffer_service, NULL, buffer_service, this) != 0) { @@ -775,8 +720,6 @@ fail_mutex: pthread_mutex_destroy(&this->data_mutex); fail_cond: pthread_cond_destroy(&this->data_cond); -fail_events: - audio_destroy_events(this); fail_buffers: audio_destroy_buffers(this); return 0; @@ -803,22 +746,26 @@ static int ao_dx2_bytes_per_frame(ao_driver_t *this_gen) { static int ao_dx2_delay(ao_driver_t *this_gen) { dx2_driver_t *this = (dx2_driver_t *)this_gen; - int frames; - size_t final_pos, play_pos; - - if (this->status != STATUS_RUNNING) return this->read_size / this->frame_size; + int frames = 0; + int ret; + size_t play_pos; pthread_mutex_lock(&this->data_mutex); - if (!audio_tell(this, &play_pos)) { - pthread_mutex_unlock(&this->data_mutex); - return 0; + + if (this->status != STATUS_RUNNING){ + frames = this->write_pos / this->frame_size; + } else { + ret = audio_tell(this, &play_pos); + if (ret){ + frames = buffer_occupied_size(this) / this->frame_size; + } } - final_pos = this->read_size + (((PARTS + this->count - 1) % PARTS) + 1) * this->part_size - 1; - frames = (this->buffer_size + final_pos - play_pos) % this->buffer_size / this->frame_size; + pthread_mutex_unlock(&this->data_mutex); #ifdef LOG - if ((rand() % 10) == 0) lprintf("frames=%d, play_pos=%" PRIdword ", block=%" PRIsizet "..%" PRIsizet "\n", frames, play_pos, final_pos - this->part_size + 1, final_pos); + if ((rand() % 10) == 0) + lprintf("frames=%d, play_pos=%" PRIdword ", write_pos=%u\n", frames, play_pos, this->write_pos); #endif return frames; @@ -840,7 +787,7 @@ static int ao_dx2_write(ao_driver_t *this_gen, int16_t* audio_data, uint32_t num while (((free_size = buffer_free_size(this)) == 0) && !this->finished) { lprintf("buffer full, waiting\n"); pthread_mutex_unlock(&this->data_mutex); - xine_usec_sleep(1000 * BUFFER_MS / PARTS / 5); + xine_usec_sleep(1000 * BUFFER_MS / 10); pthread_mutex_lock(&this->data_mutex); } if (free_size >= input_size) size = input_size; @@ -856,6 +803,12 @@ static int ao_dx2_write(ao_driver_t *this_gen, int16_t* audio_data, uint32_t num input_size -= size; } + /* signal, if are waiting and need wake up */ + if ((this->status == STATUS_WAIT) && (buffer_occupied_size(this) > BUFFER_MIN_MS * this->rate / 1000 * this->frame_size)) { + lprintf("buffer ready, waking up\n"); + pthread_cond_signal(&this->data_cond); + } + return 1; } @@ -881,7 +834,6 @@ static void ao_dx2_close(ao_driver_t *this_gen) { if (pthread_mutex_destroy(&this->data_mutex) != 0) { xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": can't destroy pthread mutex: %s\n"), strerror(errno)); } - audio_destroy_events(this); audio_destroy_buffers(this); } @@ -896,12 +848,8 @@ static void ao_dx2_exit(ao_driver_t *this_gen) { } -/* - * TODO: check - */ static int ao_dx2_get_gap_tolerance(ao_driver_t *this_gen) { - /* half of part of the buffer in pts (1 msec = 90 pts) */ - return (90 * (BUFFER_MS / PARTS)) >> 1; + return GAP_TOLERANCE; } @@ -910,36 +858,36 @@ static int ao_dx2_control(ao_driver_t *this_gen, int cmd, ...) { switch(cmd) { - case AO_CTRL_PLAY_PAUSE: - lprintf("control pause\n"); - pthread_mutex_lock(&this->data_mutex); - if (!this->paused) { - audio_stop(this); - this->paused = 1; - } - pthread_mutex_unlock(&this->data_mutex); - break; + case AO_CTRL_PLAY_PAUSE: + lprintf("control pause\n"); + pthread_mutex_lock(&this->data_mutex); + if (!this->paused) { + audio_stop(this); + this->paused = 1; + } + pthread_mutex_unlock(&this->data_mutex); + break; - case AO_CTRL_PLAY_RESUME: - lprintf("control resume\n"); - pthread_mutex_lock(&this->data_mutex); - if (this->paused) { - if (this->status != STATUS_WAIT) audio_play(this); - this->paused = 0; - } - pthread_mutex_unlock(&this->data_mutex); - break; - - case AO_CTRL_FLUSH_BUFFERS: - lprintf("control flush\n"); - pthread_mutex_lock(&this->data_mutex); - audio_stop(this); - audio_flush(this); - pthread_mutex_unlock(&this->data_mutex); - break; + case AO_CTRL_PLAY_RESUME: + lprintf("control resume\n"); + pthread_mutex_lock(&this->data_mutex); + if (this->paused) { + if (this->status != STATUS_WAIT) audio_play(this); + this->paused = 0; + } + pthread_mutex_unlock(&this->data_mutex); + break; + + case AO_CTRL_FLUSH_BUFFERS: + lprintf("control flush\n"); + pthread_mutex_lock(&this->data_mutex); + audio_stop(this); + audio_flush(this); + pthread_mutex_unlock(&this->data_mutex); + break; - default: - xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": unknown control command %d\n"), cmd); + default: + xine_log(this->class->xine, XINE_LOG_MSG, _(LOG_MODULE ": unknown control command %d\n"), cmd); } @@ -955,7 +903,7 @@ static ao_driver_t *open_plugin(audio_driver_class_t *class_gen, const void *dat lprintf("open plugin called\n"); - this = (dx2_driver_t *)xine_xmalloc(sizeof(dx2_driver_t)); + this = calloc(1, sizeof(dx2_driver_t)); if (!this) return NULL; @@ -1009,7 +957,7 @@ static void *init_class(xine_t *xine, void *data) { lprintf("init class\n"); - this = (dx2_class_t *)xine_xmalloc(sizeof(dx2_class_t)); + this = calloc(1, sizeof(dx2_class_t)); if (!this) return NULL; diff --git a/src/audio_out/audio_directx_out.c b/src/audio_out/audio_directx_out.c index 77e3e15b9..893a11976 100644 --- a/src/audio_out/audio_directx_out.c +++ b/src/audio_out/audio_directx_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2001-2003 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -60,9 +60,13 @@ typedef unsigned char boolean; * the linking stage. *****************************************************************************/ #if 1 -static const GUID IID_IDirectSoundNotify = { +static const GUID xine_IID_IDirectSoundNotify = { 0xB0210783,0x89CD,0x11D0,{0xAF,0x08,0x00,0xA0,0xC9,0x25,0xCD,0x16} }; +#ifdef IID_IDirectSoundNotify +# undef IID_IDirectSoundNotify +#endif +#define IID_IDirectSoundNotify xine_IID_IDirectSoundNotify #endif @@ -77,14 +81,14 @@ typedef struct { int capabilities; xine_t *xine; - + /* directx objects */ LPDIRECTSOUND dsobj; LPDIRECTSOUNDBUFFER dsbuffer; DSBCAPS dsbcaps; LPDIRECTSOUNDNOTIFY notify; DSBPOSITIONNOTIFY notify_events[ 2 ]; - + /* buffer vars */ long buffer_size; int write_status; @@ -92,13 +96,13 @@ typedef struct { uint8_t prebuff[ SOUND_BUFFER_MAX ]; uint32_t prebuff_size; - + /* current buffer properties */ int bits; int rate; int chnn; int frsz; - + /* current mixer settings */ int mute; int volume; @@ -114,7 +118,7 @@ typedef struct { * * BEGIN : Direct Sound and win32 handlers * for xine audio output plugins. - * + * * ------------------------------------------- */ void Error( HWND hwnd, LPSTR szfmt, ... ); @@ -124,7 +128,7 @@ boolean CreateSoundBuffer( ao_directx_t * ao_directx ); void DestroySoundBuffer( ao_directx_t * ao_directx ); uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * samples ); -/* Display formatted error message in +/* Display formatted error message in * popup message box. */ void Error( HWND hwnd, LPSTR szfmt, ... ) @@ -225,25 +229,25 @@ boolean CreateSoundBuffer( ao_directx_t * ao_directx ) * related resources */ DestroySoundBuffer( ao_directx ); - + /* create a secondary sound buffer */ - - memset( &pcmwf, 0, sizeof( PCMWAVEFORMAT ) ); + + memset( &pcmwf, 0, sizeof( PCMWAVEFORMAT ) ); pcmwf.wBitsPerSample = ( unsigned short ) ao_directx->bits; - pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; + pcmwf.wf.wFormatTag = WAVE_FORMAT_PCM; pcmwf.wf.nChannels = ao_directx->chnn; - pcmwf.wf.nSamplesPerSec = ao_directx->rate; + pcmwf.wf.nSamplesPerSec = ao_directx->rate; pcmwf.wf.nBlockAlign = ao_directx->frsz; - pcmwf.wf.nAvgBytesPerSec = ao_directx->rate * ao_directx->frsz; + pcmwf.wf.nAvgBytesPerSec = ao_directx->rate * ao_directx->frsz; - memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) ); - dsbdesc.dwSize = sizeof( DSBUFFERDESC ); - dsbdesc.dwFlags = (DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | + memset( &dsbdesc, 0, sizeof( DSBUFFERDESC ) ); + dsbdesc.dwSize = sizeof( DSBUFFERDESC ); + dsbdesc.dwFlags = (DSBCAPS_CTRLVOLUME | DSBCAPS_GLOBALFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLPOSITIONNOTIFY); dsbdesc.dwBufferBytes = ao_directx->buffer_size; dsbdesc.lpwfxFormat = ( LPWAVEFORMATEX ) &pcmwf; - if( IDirectSound_CreateSoundBuffer( ao_directx->dsobj, &dsbdesc, + if( IDirectSound_CreateSoundBuffer( ao_directx->dsobj, &dsbdesc, &ao_directx->dsbuffer, 0 ) != DS_OK ) { Error( 0, "IDirectSound_CreateSoundBuffer : Unable to create secondary sound buffer" ); @@ -278,7 +282,7 @@ boolean CreateSoundBuffer( ao_directx_t * ao_directx ) /* get the direct sound notification interface */ if( IDirectSoundBuffer_QueryInterface( ao_directx->dsbuffer, - &IID_IDirectSoundNotify, + &IID_IDirectSoundNotify, (LPVOID *)&ao_directx->notify ) != DS_OK ) { Error( 0, "IDirectSoundBuffer_QueryInterface : Unable to get notification interface" ); @@ -376,9 +380,9 @@ uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * s #ifdef LOG if ((void*)samples != (void*)0) - printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code); + printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code); else - printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code); + printf("audio_directx_out: FillSoundBuffer(%08x, %d, Null) Enter\n", (unsigned long)ao_directx, code); #endif half_size = ao_directx->buffer_size / 2; @@ -481,7 +485,7 @@ uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * s } /* write data to our sound buffer */ - + memcpy( buff_pointer, samples, buff_length ); /* unlock our sound buffer */ @@ -508,7 +512,7 @@ uint32_t FillSoundBuffer( ao_directx_t * ao_directx, int code, unsigned char * s * ----------------------------------------- */ static int ao_directx_control(ao_driver_t *this_gen, int cmd, ...) { - switch (cmd) + switch (cmd) { case AO_CTRL_PLAY_PAUSE: @@ -535,7 +539,7 @@ static int ao_directx_open( ao_driver_t * ao_driver, uint32_t bits, uint32_t rat ao_directx->bits = bits; ao_directx->rate = rate; - + /* store channel count */ switch( mode ) @@ -624,7 +628,7 @@ static int ao_directx_write( ao_driver_t * ao_driver, int16_t * frame_buffer, ui uint32_t wrote; /* number of bytes written */ uint32_t half_size; /* half our sound buffer size */ - lprintf("ao_directx_write(%08x, %08x, %d) Enter\n", + lprintf("ao_directx_write(%08x, %08x, %d) Enter\n", (unsigned long)ao_directx, (unsigned long)frame_buffer, num_frames); /* zero write counter */ @@ -741,7 +745,7 @@ static int ao_directx_set_property( ao_driver_t * ao_driver, int property, int v { ao_directx_t *ao_directx = ( ao_directx_t * ) ao_driver; - lprintf("ao_directx_set_property(%08x, %d, %d) Enter\n", + lprintf("ao_directx_set_property(%08x, %d, %d) Enter\n", (unsigned long)ao_directx, property, value); switch( property ) @@ -755,7 +759,7 @@ static int ao_directx_set_property( ao_driver_t * ao_driver, int property, int v if( !ao_directx->mute && ao_directx->dsbuffer ) IDirectSoundBuffer_SetVolume( ao_directx->dsbuffer, ao_directx->volume ); - xprintf(ao_directx->xine, XINE_VERBOSITY_DEBUG, + xprintf(ao_directx->xine, XINE_VERBOSITY_DEBUG, "ao_directx : volume set to %d - directX volume = %d\n", value, ao_directx->volume); return value; @@ -789,11 +793,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da { audiox_class_t *class = (audiox_class_t *) class_gen; ao_directx_t *ao_directx; - - ao_directx = ( ao_directx_t * ) xine_xmalloc( sizeof( ao_directx_t ) ); + + ao_directx = calloc(1, sizeof(ao_directx_t)); if (!ao_directx) return NULL; - + lprintf("open_plugin(%08x, %08x) Enter\n", (unsigned long)class_gen, (unsigned long)data); lprintf("open_plugin: ao_directx=%08x\n", (unsigned long)ao_directx); @@ -841,10 +845,10 @@ static void *init_class (xine_t *xine, void *data) { /* * from this point on, nothing should go wrong anymore */ - audiox = (audiox_class_t *) xine_xmalloc (sizeof (audiox_class_t)); + audiox = calloc(1, sizeof (audiox_class_t)); if (!audiox) return NULL; - + audiox->driver_class.open_plugin = open_plugin; audiox->driver_class.get_identifier = get_identifier; audiox->driver_class.get_description = get_description; @@ -854,7 +858,7 @@ static void *init_class (xine_t *xine, void *data) { audiox->config = xine->config; lprintf("init_class() Exit! Returning audiox=%08x\n", audiox); - + return audiox; } @@ -866,7 +870,7 @@ static const ao_info_t ao_info_directx = { * exported plugin catalog entry */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_DIRECTX_IFACE_VERSION, "directx", XINE_VERSION_CODE, &ao_info_directx, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_esd_out.c b/src/audio_out/audio_esd_out.c index 4b209bea1..ae7576259 100644 --- a/src/audio_out/audio_esd_out.c +++ b/src/audio_out/audio_esd_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -77,7 +77,7 @@ typedef struct esd_driver_s { /* * Temporary sample buffer used to reblock the sample output stream * to writes using buffer sizes of n*ESD_BUF_SIZE bytes. - * + * * The reblocking avoids a bug with esd 0.2.18 servers and reduces * cpu load with newer versions of the esd server. * @@ -99,7 +99,7 @@ typedef struct { /* - * connect to esd + * connect to esd */ static int ao_esd_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int mode) @@ -107,7 +107,7 @@ static int ao_esd_open(ao_driver_t *this_gen, esd_driver_t *this = (esd_driver_t *) this_gen; esd_format_t format; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); if ( (mode & this->capabilities) == 0 ) { @@ -117,12 +117,12 @@ static int ao_esd_open(ao_driver_t *this_gen, if (this->audio_fd>=0) { - if ( (mode == this->mode) && (rate == this->input_sample_rate) ) + if ( (mode == this->mode) && (rate == this->input_sample_rate) ) return this->output_sample_rate; esd_close (this->audio_fd); } - + this->mode = mode; this->input_sample_rate = rate; this->output_sample_rate = rate; @@ -170,7 +170,7 @@ static int ao_esd_open(ao_driver_t *this_gen, return this->output_sample_rate; } -static int ao_esd_num_channels(ao_driver_t *this_gen) +static int ao_esd_num_channels(ao_driver_t *this_gen) { esd_driver_t *this = (esd_driver_t *) this_gen; return this->num_channels; @@ -200,14 +200,14 @@ static int ao_esd_delay(ao_driver_t *this_gen) frames += (tv.tv_sec - this->start_time.tv_sec) * this->output_sample_rate; - frames -= this->latency; + frames -= this->latency; if (frames < 0) frames = 0; - + /* calc delay */ - + bytes_left = this->bytes_in_buffer - frames * this->bytes_per_frame; - + if (bytes_left<=0) /* buffer ran dry */ bytes_left = 0; return bytes_left / this->bytes_per_frame; @@ -230,18 +230,18 @@ static int ao_esd_write(ao_driver_t *this_gen, /* check if simulated buffer ran dry */ gettimeofday(&tv, NULL); - + frames = (tv.tv_usec - this->start_time.tv_usec) * this->output_sample_k_rate / 1000; frames += (tv.tv_sec - this->start_time.tv_sec) * this->output_sample_rate; - - frames -= this->latency; + + frames -= this->latency; if (frames < 0) frames = 0; /* calc delay */ - + simulated_bytes_in_buffer = frames * this->bytes_per_frame; if (this->bytes_in_buffer < simulated_bytes_in_buffer) @@ -296,7 +296,7 @@ static int ao_esd_write(ao_driver_t *this_gen, if (nwritten != num_bytes) { if (nwritten < 0) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: writev failed: %s\n", strerror(errno)); - else + else xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: warning, incomplete write: %d\n", nwritten); } if (nwritten > 0) @@ -337,7 +337,7 @@ static int ao_esd_get_gap_tolerance (ao_driver_t *this_gen) { static void ao_esd_exit(ao_driver_t *this_gen) { esd_driver_t *this = (esd_driver_t *) this_gen; - + if (this->audio_fd != -1) esd_close(this->audio_fd); @@ -351,19 +351,19 @@ static int ao_esd_get_property (ao_driver_t *this_gen, int property) { int mixer_fd; esd_player_info_t *esd_pi; esd_info_t *esd_i; - + switch(property) { case AO_PROP_MIXER_VOL: - + if((mixer_fd = esd_open_sound(NULL)) >= 0) { if((esd_i = esd_get_all_info(mixer_fd)) != NULL) { for(esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) { if(!strcmp(this->pname, esd_pi->name)) { this->mixer.source_id = esd_pi->source_id; - + if(!this->mixer.mute) - this->mixer.volume = (((esd_pi->left_vol_scale * 100) / 256) + + this->mixer.volume = (((esd_pi->left_vol_scale * 100) / 256) + ((esd_pi->right_vol_scale * 100) / 256)) >> 1; } @@ -372,7 +372,7 @@ static int ao_esd_get_property (ao_driver_t *this_gen, int property) { } esd_close(mixer_fd); } - + return this->mixer.volume; break; @@ -390,39 +390,39 @@ static int ao_esd_set_property (ao_driver_t *this_gen, int property, int value) switch(property) { case AO_PROP_MIXER_VOL: - + if(!this->mixer.mute) { - + /* need this to get source_id */ (void) ao_esd_get_property(&this->ao_driver, AO_PROP_MIXER_VOL); if((mixer_fd = esd_open_sound(NULL)) >= 0) { int v = (value * 256) / 100; - + esd_set_stream_pan(mixer_fd, this->mixer.source_id, v, v); - + if(!this->mixer.mute) this->mixer.volume = value; - + esd_close(mixer_fd); } } else this->mixer.volume = value; - + return this->mixer.volume; break; - + case AO_PROP_MUTE_VOL: { int mute = (value) ? 1 : 0; - + /* need this to get source_id */ (void) ao_esd_get_property(&this->ao_driver, AO_PROP_MIXER_VOL); - + if(mute) { if((mixer_fd = esd_open_sound(NULL)) >= 0) { int v = 0; - + esd_set_stream_pan(mixer_fd, this->mixer.source_id, v, v); esd_close(mixer_fd); } @@ -430,14 +430,14 @@ static int ao_esd_set_property (ao_driver_t *this_gen, int property, int value) else { if((mixer_fd = esd_open_sound(NULL)) >= 0) { int v = (this->mixer.volume * 256) / 100; - + esd_set_stream_pan(mixer_fd, this->mixer.source_id, v, v); esd_close(mixer_fd); } } - + this->mixer.mute = mute; - + return value; } break; @@ -465,7 +465,7 @@ static int ao_esd_ctrl(ao_driver_t *this_gen, int cmd, ...) { return 0; } -static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) { esd_class_t *class = (esd_class_t *) class_gen; @@ -491,7 +491,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, sigemptyset(&vo_mask); sigaddset(&vo_mask, SIGALRM); - if (sigprocmask(SIG_UNBLOCK, &vo_mask, &vo_mask_orig)) + if (sigprocmask(SIG_UNBLOCK, &vo_mask, &vo_mask_orig)) xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_esd_out: cannot unblock SIGALRM: %s\n", strerror(errno)); xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_esd_out: connecting to esd server...\n")); @@ -511,7 +511,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, return NULL; } - + esd_svinfo = esd_get_server_info(audio_fd); if (esd_svinfo) { server_sample_rate = esd_svinfo->rate; @@ -521,7 +521,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, esd_close(audio_fd); - this = (esd_driver_t *) xine_xmalloc (sizeof (esd_driver_t)); + this = calloc(1, sizeof (esd_driver_t)); if (!this) return NULL; this->xine = class->xine; @@ -583,7 +583,7 @@ static void *init_class (xine_t *xine, void *data) { esd_class_t *this; - this = (esd_class_t *) xine_xmalloc (sizeof (esd_class_t)); + this = calloc(1, sizeof (esd_class_t)); if (!this) return NULL; @@ -606,7 +606,7 @@ static const ao_info_t ao_info_esd = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_ESD_IFACE_VERSION, "esd", XINE_VERSION_CODE, &ao_info_esd, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_file_out.c b/src/audio_out/audio_file_out.c index 225d64d0e..7b7bfe950 100644 --- a/src/audio_out/audio_file_out.c +++ b/src/audio_out/audio_file_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -46,7 +46,7 @@ struct wavhdr { unsigned char bRiffMagic[4]; // 'RIFF' uint32_t wRiffLength ; // length of file minus the 8 byte riff header unsigned char bWaveMagic[8]; // 'WAVEfmt ' - uint32_t wFmtSize; // length of format chunk minus 8 byte header + uint32_t wFmtSize; // length of format chunk minus 8 byte header uint16_t wFormatTag; // identifies PCM, ULAW etc uint16_t wChannels; uint32_t dwSamplesPerSecond; // samples per second per channel @@ -93,7 +93,7 @@ static int ao_file_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int file_driver_t *this = (file_driver_t *) this_gen; struct wavhdr w; - xprintf (this->xine, XINE_VERBOSITY_LOG, + xprintf (this->xine, XINE_VERBOSITY_LOG, "audio_file_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); this->mode = mode; @@ -314,7 +314,7 @@ static int ao_file_ctrl(ao_driver_t *this_gen, int cmd, ...) { return 0; } -static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) { file_class_t *class = (file_class_t *) class_gen; @@ -323,7 +323,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, lprintf ("open_plugin called\n"); - this = (file_driver_t *) xine_xmalloc (sizeof (file_driver_t)); + this = calloc(1, sizeof (file_driver_t)); if (!this) return NULL; @@ -375,7 +375,7 @@ static void *init_class (xine_t *xine, void *data) { lprintf ("init class\n"); - this = (file_class_t *) xine_xmalloc (sizeof (file_class_t)); + this = calloc(1, sizeof (file_class_t)); if (!this) return NULL; @@ -399,7 +399,7 @@ static const ao_info_t ao_info_file = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_FILE_IFACE_VERSION, "file", XINE_VERSION_CODE, &ao_info_file, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_fusionsound_out.c b/src/audio_out/audio_fusionsound_out.c index 92eadc6cf..873ab32e9 100644 --- a/src/audio_out/audio_fusionsound_out.c +++ b/src/audio_out/audio_fusionsound_out.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2006 the xine project and Claudio Ciccani - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -69,10 +69,10 @@ typedef struct fusionsound_driver_s { float vol; int vol_mute; - + float amp; int amp_mute; - + int paused; } fusionsound_driver_t; @@ -90,12 +90,12 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver, DFBResult ret; lprintf ("ao_open( bits=%d, rate=%d, mode=%d )\n", bits, rate, mode); - - dsc.flags = FSSDF_BUFFERSIZE | FSBDF_CHANNELS | + + dsc.flags = FSSDF_BUFFERSIZE | FSBDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_SAMPLERATE; switch (mode) { - case AO_CAP_MODE_MONO: + case AO_CAP_MODE_MONO: dsc.channels = 1; break; case AO_CAP_MODE_STEREO: @@ -140,13 +140,13 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver, this->playback->Release (this->playback); this->playback = NULL; } - + if (this->stream) { this->stream->Release (this->stream); this->stream = NULL; } - - ret = this->sound->CreateStream (this->sound, &dsc, &this->stream); + + ret = this->sound->CreateStream (this->sound, &dsc, &this->stream); if (ret != DFB_OK) { xprintf (this->xine, XINE_VERBOSITY_LOG, "audio_fusionsound_out: IFusionSound::CreateStream() failed [%s]\n", @@ -160,10 +160,10 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver, this->channels = dsc.channels; this->rate = dsc.samplerate; this->bytes_per_frame = this->channels * FS_BYTES_PER_SAMPLE(this->format); - + ret = this->stream->GetPlayback (this->stream, &this->playback); if (ret == DFB_OK) { - this->playback->SetVolume (this->playback, + this->playback->SetVolume (this->playback, (this->vol_mute ? 0 : this->vol) * (this->amp_mute ? 0 : this->amp)); if (this->paused) @@ -182,22 +182,22 @@ static int ao_fusionsound_open(ao_driver_t *ao_driver, static int ao_fusionsound_num_channels(ao_driver_t *ao_driver) { fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver; - + return this->channels; } static int ao_fusionsound_bytes_per_frame(ao_driver_t *ao_driver) { fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver; - + return this->bytes_per_frame; } static int ao_fusionsound_delay(ao_driver_t *ao_driver) { fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver; int delay = 0; - + this->stream->GetPresentationDelay (this->stream, &delay); - + return (delay * this->rate / 1000); } @@ -209,7 +209,7 @@ static int ao_fusionsound_write(ao_driver_t *ao_driver, int16_t *data, uint32_t num_frames) { fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver; DFBResult ret; - + if (this->paused) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_fusionsound_out: " @@ -226,7 +226,7 @@ static int ao_fusionsound_write(ao_driver_t *ao_driver, FusionSoundErrorString (ret)); return 0; } - + return num_frames; } @@ -264,13 +264,13 @@ static void ao_fusionsound_exit(ao_driver_t *ao_driver) { if (this->playback) this->playback->Release (this->playback); - + if (this->stream) this->stream->Release (this->stream); if (this->sound) this->sound->Release (this->sound); - + free (this); } @@ -287,17 +287,17 @@ static int ao_fusionsound_get_property(ao_driver_t *ao_driver, int property) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_fusionsound_out: volume mute is %d\n", this->vol_mute); return this->vol_mute; - + case AO_PROP_AMP: xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_fusionsound_out: amplifier is %.2f\n", this->amp); return (int) (this->amp * 100.0); - + case AO_PROP_AMP_MUTE: xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_fusionsound_out: amplifier mute is %d\n", this->amp_mute); return this->amp_mute; - + default: break; } @@ -305,10 +305,10 @@ static int ao_fusionsound_get_property(ao_driver_t *ao_driver, int property) { return 0; } -static int ao_fusionsound_set_property(ao_driver_t *ao_driver, +static int ao_fusionsound_set_property(ao_driver_t *ao_driver, int property, int value ) { fusionsound_driver_t *this = (fusionsound_driver_t *) ao_driver; - + if (!this->playback) return 0; @@ -318,11 +318,11 @@ static int ao_fusionsound_set_property(ao_driver_t *ao_driver, xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_fusionsound_out: volume set to %.2f\n", this->vol); break; - + case AO_PROP_MUTE_VOL: this->vol_mute = value ? 1 : 0; xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "audio_fusionsound_out: volume mute set to %d\n", + "audio_fusionsound_out: volume mute set to %d\n", this->vol_mute); break; @@ -331,20 +331,20 @@ static int ao_fusionsound_set_property(ao_driver_t *ao_driver, xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_fusionsound_out: amplifier set to %.2f\n", this->amp); break; - + case AO_PROP_AMP_MUTE: this->amp_mute = value ? 1 : 0; xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "audio_fusionsound_out: amplifier mute set to %d\n", + "audio_fusionsound_out: amplifier mute set to %d\n", this->amp_mute); break; default: return 0; } - + if (this->playback) { - this->playback->SetVolume (this->playback, + this->playback->SetVolume (this->playback, (this->vol_mute ? 0 : this->vol) * (this->amp_mute ? 0 : this->amp)); } @@ -362,10 +362,10 @@ static int ao_fusionsound_control(ao_driver_t *ao_driver, int cmd, ...) { this->playback->Stop (this->playback); this->paused = 1; return 1; - + case AO_CTRL_PLAY_RESUME: lprintf ("Resume()\n"); - if (this->playback) + if (this->playback) this->playback->Continue (this->playback); this->paused = 0; return 1; @@ -384,16 +384,16 @@ static int ao_fusionsound_control(ao_driver_t *ao_driver, int cmd, ...) { } -static ao_driver_t* open_plugin(audio_driver_class_t *ao_class, +static ao_driver_t* open_plugin(audio_driver_class_t *ao_class, const void *data ) { fusionsound_class_t *class = (fusionsound_class_t *) ao_class; fusionsound_driver_t *this; const char *args[] = { "xine", "--dfb:no-sighandler", "--fs:no-banner" }; - int argn = sizeof(args) / sizeof(args[0]); + const size_t argn = sizeof(args) / sizeof(args[0]); char **argp = (char **) args; DFBResult ret; - this = (fusionsound_driver_t *) xine_xmalloc (sizeof(fusionsound_driver_t)); + this = calloc(1, sizeof(fusionsound_driver_t)); if (!this) { xprintf (class->xine, XINE_VERBOSITY_LOG, "audio_fusionsound_out: driver interface allocation failed!\n"); @@ -424,7 +424,7 @@ static ao_driver_t* open_plugin(audio_driver_class_t *ao_class, this->ao_driver.exit = ao_fusionsound_exit; this->ao_driver.get_gap_tolerance = ao_fusionsound_get_gap_tolerance; this->ao_driver.control = ao_fusionsound_control; - + this->vol = this->amp = 1.0; return &this->ao_driver; @@ -449,7 +449,7 @@ static void dispose_class(audio_driver_class_t *ao_class) { static void* init_class(xine_t *xine, void *data) { fusionsound_class_t *class; const char *error; - + /* check FusionSound version */ error = FusionSoundCheckVersion( FUSIONSOUND_MAJOR_VERSION, FUSIONSOUND_MINOR_VERSION, @@ -460,7 +460,7 @@ static void* init_class(xine_t *xine, void *data) { return NULL; } - class = (fusionsound_class_t *) xine_xmalloc (sizeof( fusionsound_class_t)); + class = calloc(1, sizeof( fusionsound_class_t)); if (!class) { xprintf (xine, XINE_VERBOSITY_LOG, "audio_fusionsound_out: class interface allocation failed!\n"); @@ -485,7 +485,7 @@ static const ao_info_t ao_info_fusionsound = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_FS_IFACE_VERSION, "FusionSound", XINE_VERSION_CODE, &ao_info_fusionsound, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/audio_out/audio_irixal_out.c b/src/audio_out/audio_irixal_out.c index 1654cc1a7..336996a99 100644 --- a/src/audio_out/audio_irixal_out.c +++ b/src/audio_out/audio_irixal_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -113,7 +113,7 @@ static int ao_irixal_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, i default: xlerror ("irixal Driver does not support the requested mode: 0x%x",mode); return 0; - } + } if (! (config = alNewConfig ())) { @@ -126,7 +126,7 @@ static int ao_irixal_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, i alFreeConfig (config); return 0; } - + switch (bits) { case 8: if ( (alSetWidth (config, AL_SAMPLE_8)) == -1) @@ -211,7 +211,7 @@ static int ao_irixal_get_gap_tolerance (ao_driver_t *this_gen) return this->gap_tolerance; } -static int ao_irixal_delay (ao_driver_t *this_gen) +static int ao_irixal_delay (ao_driver_t *this_gen) { irixal_driver_t *this = (irixal_driver_t *) this_gen; stamp_t stamp, time; @@ -230,7 +230,7 @@ static int ao_irixal_write(ao_driver_t *this_gen,int16_t *data, uint32_t num_fra { irixal_driver_t *this = (irixal_driver_t *) this_gen; stamp_t stamp; - + /* Grmbf. IRIX audio does not tell us, wenn we run dry. * We have to detect this ourself. */ /* get absolute number of samples played so far @@ -249,7 +249,7 @@ static int ao_irixal_write(ao_driver_t *this_gen,int16_t *data, uint32_t num_fra * alGetFillable() would tell us, whether space was available */ alWriteFrames (this->port, data, num_frames); this->frames_in_buffer += num_frames; - + return num_frames; } @@ -376,9 +376,9 @@ static void *init_audio_out_plugin (config_values_t *config) } } } - + printf (" capabilities 0x%X\n",this->capabilities); - + /* TODO: anything can change during runtime... move check to the right location */ this->gap_tolerance = config->register_range (config, "audio.device.irixal_gap_tolerance", DEFAULT_GAP_TOLERANCE, 0, 90000, @@ -396,7 +396,7 @@ static void *init_audio_out_plugin (config_values_t *config) this->ao_driver.num_channels = ao_irixal_num_channels; this->ao_driver.bytes_per_frame = ao_irixal_bytes_per_frame; this->ao_driver.delay = ao_irixal_delay; - this->ao_driver.write = ao_irixal_write; + this->ao_driver.write = ao_irixal_write; this->ao_driver.close = ao_irixal_close; this->ao_driver.exit = ao_irixal_exit; this->ao_driver.get_gap_tolerance = ao_irixal_get_gap_tolerance; @@ -421,7 +421,7 @@ ao_info_t *get_audio_out_plugin_info() */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_IRIXAL_IFACE_VERSION, "irixal", XINE_VERSION_CODE, &ao_info_irixal, init_audio_out_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_jack_out.c b/src/audio_out/audio_jack_out.c index 1bc070527..a343310f0 100644 --- a/src/audio_out/audio_jack_out.c +++ b/src/audio_out/audio_jack_out.c @@ -1,3 +1,6 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdio.h> #include <errno.h> @@ -17,431 +20,926 @@ #define AO_OUT_JACK_IFACE_VERSION 8 #define GAP_TOLERANCE AO_MAX_GAP -#define BUFSIZE 81920 +/* maximum number of channels supported, avoids lots of mallocs */ +#define MAX_CHANS 6 -typedef struct jack_driver_s { +typedef struct jack_driver_s +{ + ao_driver_t ao_driver; + xine_t *xine; + + int capabilities; + int mode; + int paused; + int underrun; + + int32_t output_sample_rate, input_sample_rate; + uint32_t num_channels; + uint32_t bits_per_sample; + uint32_t bytes_per_frame; + uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */ + uint32_t fragment_size; + + jack_client_t *client; + jack_port_t *ports[MAX_CHANS]; + + /*! buffer for audio data */ + unsigned char *buffer; + + /*! buffer read position, may only be modified by playback thread or while it is stopped */ + uint32_t read_pos; + /*! buffer write position, may only be modified by MPlayer's thread */ + uint32_t write_pos; + + struct + { + int volume; + int mute; + } mixer; - ao_driver_t ao_driver; - xine_t *xine; +} jack_driver_t; - int capabilities; +typedef struct +{ + audio_driver_class_t driver_class; + config_values_t *config; + xine_t *xine; +} jack_class_t; - int32_t sample_rate; - uint32_t num_channels; - uint32_t bits_per_sample; - uint32_t bytes_per_frame; - jack_client_t *client; - jack_port_t *port_1; - jack_port_t *port_2; - float buf_1[BUFSIZE]; - float buf_2[BUFSIZE]; - uint32_t buf_read; - uint32_t buf_write; +/************************************************************** + * + * Simple ringbuffer implementation + * Lifted from mplayer ao_jack.c + * +**************************************************************/ + + +/*! size of one chunk, if this is too small Xine will start to "stutter" */ +/*! after a short time of playback */ +#define CHUNK_SIZE (16 * 1024) +/*! number of "virtual" chunks the buffer consists of */ +#define NUM_CHUNKS 8 +/* This type of ring buffer may never fill up completely, at least */ +/* one byte must always be unused. */ +/* For performance reasons (alignment etc.) one whole chunk always stays */ +/* empty, not only one byte. */ +#define BUFFSIZE ((NUM_CHUNKS + 1) * CHUNK_SIZE) + +/** + * \brief get the number of free bytes in the buffer + * \return number of free bytes in buffer + * + * may only be called by Xine's thread + * return value may change between immediately following two calls, + * and the real number of free bytes might be larger! + */ +static int buf_free (jack_driver_t *this) +{ + int free = this->read_pos - this->write_pos - CHUNK_SIZE; + if (free < 0) + free += BUFFSIZE; + return free; +} - uint32_t volume; - uint32_t mute; +/** + * \brief get amount of data available in the buffer + * \return number of bytes available in buffer + * + * may only be called by the playback thread + * return value may change between immediately following two calls, + * and the real number of buffered bytes might be larger! + */ +static int buf_used (jack_driver_t *this) +{ + int used = this->write_pos - this->read_pos; + if (used < 0) + used += BUFFSIZE; + return used; +} -} jack_driver_t; +/** + * \brief insert len bytes into buffer + * \param data data to insert + * \param len length of data + * \return number of bytes inserted into buffer + * + * If there is not enough room, the buffer is filled up + * + * TODO: Xine should really pass data as float, perhaps in V1.2? + */ +static int write_buffer_32 (jack_driver_t *this, unsigned char *data, int len) +{ + int first_len = BUFFSIZE - this->write_pos; + int free = buf_free (this); + if (len > free) + len = free; + if (first_len > len) + first_len = len; + + /* copy from current write_pos to end of buffer */ + memcpy (&(this->buffer[this->write_pos]), data, first_len); + if (len > first_len) { /* we have to wrap around */ + /* remaining part from beginning of buffer */ + memcpy (this->buffer, &data[first_len], len - first_len); + } + this->write_pos = (this->write_pos + len) % BUFFSIZE; + + return len; +} + +static int write_buffer_16 (jack_driver_t *this, unsigned char *data, int len) +{ + int samples_free = buf_free (this) / (sizeof (float)); + int samples = len / 2; + if (samples > samples_free) + samples = samples_free; + + /* Rename some pointers so that the next bit of gymnastics is easier to read */ + uint32_t write_pos = this->write_pos; + float *p_write; + int16_t *p_read = (int16_t *) data; + int i; + for (i = 0; i < samples; i++) { + /* Read in 16bits, write out floats */ + p_write = (float *) (&(this->buffer[write_pos])); + *p_write = ((float) (p_read[i])) / 32768.0f; + write_pos = (write_pos + sizeof (float)) % BUFFSIZE; + } + this->write_pos = write_pos; + + return samples * 2; +} -typedef struct { - audio_driver_class_t driver_class; - config_values_t *config; - xine_t *xine; -} jack_class_t; -static int jack_process(jack_nframes_t nframes, void *arg) +/** + * \brief read data from buffer and splitting it into channels + * \param bufs num_bufs float buffers, each will contain the data of one channel + * \param cnt number of samples to read per channel + * \param num_bufs number of channels to split the data into + * \return number of samples read per channel, equals cnt unless there was too + * little data in the buffer + * + * Assumes the data in the buffer is of type float, the number of bytes + * read is res * num_bufs * sizeof(float), where res is the return value. + * If there is not enough data in the buffer remaining parts will be filled + * with silence. + */ +static int read_buffer (jack_driver_t *this, float **bufs, int cnt, + int num_bufs, float gain) { - jack_driver_t *this = (jack_driver_t *)arg; - uint32_t local_buf_read = this->buf_read; - uint32_t local_buf_write = this->buf_write; - uint32_t src_channel, target_channel; - uint32_t frame; - float *buf, *out; - float gain = 0; - - if (!this->client) return 0; - - if (!this->mute) { - gain = (float)this->volume / 100.0; + int buffered = buf_used (this); + int i, j; + int orig_cnt = cnt; + if (cnt * sizeof (float) * num_bufs > buffered) + cnt = buffered / (sizeof (float) * num_bufs); + + uint32_t read_pos = this->read_pos; + unsigned char *buffer = this->buffer; + for (i = 0; i < cnt; i++) { + for (j = 0; j < num_bufs; j++) { + bufs[j][i] = *((float *) (&(buffer[read_pos]))) * gain; + read_pos = (read_pos + sizeof (float)) % BUFFSIZE; } + } + this->read_pos = read_pos; + for (i = cnt; i < orig_cnt; i++) + for (j = 0; j < num_bufs; j++) + bufs[j][i] = 0; - for (target_channel = 0; target_channel < 2; ++target_channel) { - - if (target_channel < this->num_channels) src_channel = target_channel; - else src_channel = 0; + return cnt; +} - jack_port_t *port = (target_channel ? this->port_2 : this->port_1); - if (!port) continue; +/** + * \brief fill the buffers with silence + * \param bufs num_bufs float buffers, each will contain the data of one channel + * \param cnt number of samples in each buffer + * \param num_bufs number of buffers + */ +static void silence (float **bufs, int cnt, int num_bufs) +{ + int i, j; + for (i = 0; i < cnt; i++) + for (j = 0; j < num_bufs; j++) + bufs[j][i] = 0; +} - buf = (src_channel ? this->buf_2 : this->buf_1); - out = (float *)jack_port_get_buffer(port, nframes); - local_buf_read = this->buf_read; - frame = 0; +/************************************************************** + * + * Jack interface functions + * +**************************************************************/ - while (frame < nframes && local_buf_read != local_buf_write) { - // local_buf_write doesn't change during this process, - // so we can safely defer updating buf_read until after +/** + * \brief stop playing and empty buffers (for seeking/pause) + */ +static void jack_reset (jack_driver_t *this) +{ + this->paused = 1; + this->read_pos = this->write_pos = 0; + this->paused = 0; +} - out[frame++] = buf[local_buf_read] * gain; - if (++local_buf_read == BUFSIZE) local_buf_read = 0; - } +static int jack_callback (jack_nframes_t nframes, void *arg) +{ + jack_driver_t *this = (jack_driver_t *) arg; - if (frame < nframes) { -// printf("jack_process: underrun: %u required, %u available\n", -// nframes, frame); - while (frame < nframes) { - out[frame++] = 0.0f; - } - } + if (!this->client) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_callback: called without a client parameter? silently trying to continue...\n"); + return 0; + } + + float gain = 0; + if (!this->mixer.mute) { + gain = (float) this->mixer.volume / 100.0; + gain *= gain; /* experiment with increasing volume range */ + } + + float *bufs[MAX_CHANS]; + int i; + for (i = 0; i < this->num_channels; i++) + bufs[i] = jack_port_get_buffer (this->ports[i], nframes); + + if (this->paused || this->underrun) { + silence (bufs, nframes, this->num_channels); + } else { + int frames_read = read_buffer (this, bufs, nframes, this->num_channels, gain); + if (frames_read < nframes) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_callback: underrun - frames read: %d\n", frames_read); + this->underrun = 1; } + } - this->buf_read = local_buf_read; + return 0; +} -// printf("jack_process: buf_read %u, buf_write %u\n", this->buf_read, this->buf_write); +static void jack_shutdown (void *arg) +{ + jack_driver_t *this = (jack_driver_t *) arg; + this->client = NULL; +} - return 0; +/* + * Open the Jack audio device + * Return 1 on success, 0 on failure + * All error handling rests with the caller, we just try to open the device here + */ +static int jack_open_device (ao_driver_t *this_gen, char *jack_device, + int32_t *poutput_sample_rate, int num_channels) +{ + jack_driver_t *this = (jack_driver_t *) this_gen; + const char **matching_ports = NULL; + char *port_name = NULL; + jack_client_t *client = this->client; + + int port_flags = JackPortIsInput; + int i; + int num_ports; + + if (num_channels > MAX_CHANS) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_open_device: Invalid number of channels: %i\n", + num_channels); + goto err_out; + } + /* Try to create a client called "xine[-NN]" */ + if ((client = jack_client_open ("xine", JackNullOption, NULL)) == 0) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "\njack_open_device: Error: Failed to connect to JACK server\n"); + goto err_out; + } + + /* Save the new client */ + this->client = client; + + jack_reset (this); + jack_set_process_callback (client, jack_callback, this); + + /* list matching ports */ + if (!jack_device) + port_flags |= JackPortIsPhysical; + matching_ports = jack_get_ports (client, jack_device, NULL, port_flags); + for (num_ports = 0; matching_ports && matching_ports[num_ports]; + num_ports++); + if (!num_ports) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_open_device: no physical ports available\n"); + goto err_out; + } + if (num_ports < num_channels) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_open_device: not enough physical ports available\n"); + goto err_out; + } + + /* create output ports */ + for (i = 0; i < num_channels; i++) { + char pname[50]; + snprintf (pname, 50, "out_%d", i); + this->ports[i] = + jack_port_register (client, pname, JACK_DEFAULT_AUDIO_TYPE, + JackPortIsOutput, 0); + if (!this->ports[i]) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_open_device: could not create output ports? Why not?\n"); + goto err_out; + } + } + if (jack_activate (client)) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_open_device: jack_activate() failed\n"); + goto err_out; + } + for (i = 0; i < num_channels; i++) { + if (jack_connect + (client, jack_port_name (this->ports[i]), matching_ports[i])) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "jack_open_device: jack_connect() failed\n"); + goto err_out; + } + } + *poutput_sample_rate = jack_get_sample_rate (client); + + free (matching_ports); + return 1; + +err_out: + free (matching_ports); + if (client) { + jack_client_close (client); + this->client = NULL; + } + return 0; } - -static void jack_shutdown(void *arg) + +/************************************************************** + * + * Xine interface functions + * +**************************************************************/ + + +/** + * close the device and reset the play position + */ +static void ao_jack_close (ao_driver_t *this_gen) { - jack_driver_t *this = (jack_driver_t *)arg; - this->client = 0; + jack_driver_t *this = (jack_driver_t *) this_gen; + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "ao_jack_close: closing\n"); + + jack_reset (this); + if (this->client) { + jack_client_close (this->client); + this->client = NULL; + } } /* * open the audio device for writing to */ -static int ao_jack_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int mode) +static int ao_jack_open (ao_driver_t *this_gen, uint32_t bits, uint32_t rate, + int mode) { - jack_driver_t *this = (jack_driver_t *) this_gen; + jack_driver_t *this = (jack_driver_t *) this_gen; + config_values_t *config = this->xine->config; + char *jack_device; - if (bits != 16) { - fprintf(stderr, "ao_jack_open: bits=%u expected %u\n", bits, 16); - return 0; - } + jack_device = + config->lookup_entry (config, "audio.device.jack_device_name")->str_value; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "ao_jack_open: ao_open rate=%d, mode=%d, bits=%d dev=%s\n", rate, + mode, bits, jack_device); - rate = jack_get_sample_rate(this->client); - fprintf(stderr, "ao_jack_open: JACK sample rate is %u\n", rate); + if ((bits != 16) && (bits != 32)) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "ao_jack_open: bits=%u expected 16 or 32bit only\n", bits); + return 0; + } - switch (mode) { - case AO_CAP_MODE_MONO: - this->num_channels = 1; - break; - case AO_CAP_MODE_STEREO: - this->num_channels = 2; - break; + if ((mode & this->capabilities) == 0) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "ao_jack_open: unsupported mode %08x\n", mode); + return 0; + } + + /* If device open already then either re-use it or close it */ + if (this->client) { + if ((mode == this->mode) && (rate == this->input_sample_rate)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "ao_jack_open: device already open, reusing it\n"); + return this->output_sample_rate; } - this->buf_read = this->buf_write = 0; - this->sample_rate = rate; - this->bits_per_sample = bits; - this->capabilities = AO_CAP_16BITS | AO_CAP_MODE_MONO | \ - AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL; - this->bytes_per_frame = this->num_channels * (bits / 8); + ao_jack_close (this_gen); + } + + + this->mode = mode; + this->input_sample_rate = rate; + this->bits_per_sample = bits; + this->bytes_in_buffer = 0; + this->read_pos = this->write_pos = 0; + this->paused = 0; + this->underrun = 0; + + /* + * set number of channels / a52 passthrough + */ + switch (mode) { + case AO_CAP_MODE_MONO: + this->num_channels = 1; + break; + case AO_CAP_MODE_STEREO: + this->num_channels = 2; + break; + case AO_CAP_MODE_4CHANNEL: + this->num_channels = 4; + break; + case AO_CAP_MODE_4_1CHANNEL: + case AO_CAP_MODE_5CHANNEL: + case AO_CAP_MODE_5_1CHANNEL: + this->num_channels = 6; + break; + case AO_CAP_MODE_A52: + case AO_CAP_MODE_AC5: + /* FIXME: Is this correct...? */ + this->num_channels = 2; + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "ao_jack_open: AO_CAP_MODE_A52\n"); + break; + default: + xprintf (this->xine, XINE_VERBOSITY_LOG, + "ao_jack_open: JACK Driver does not support the requested mode: 0x%X\n", + mode); + return 0; + } + + xprintf (this->xine, XINE_VERBOSITY_LOG, + "ao_jack_open: %d channels output\n", this->num_channels); + this->bytes_per_frame = (this->bits_per_sample * this->num_channels) / 8; + + /* + * open audio device + */ + if (!jack_open_device (this_gen, jack_device, &(this->output_sample_rate), + this->num_channels)) + return 0; - fprintf(stderr, "ao_jack_open: bits=%d rate=%d, mode=%d OK\n", bits, rate, mode); + if (this->input_sample_rate != this->output_sample_rate) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "ao_jack_open: audio rate : %d requested, %d provided by device\n", + this->input_sample_rate, this->output_sample_rate); + } - return rate; + return this->output_sample_rate; } -static int ao_jack_num_channels(ao_driver_t *this_gen) +static int ao_jack_num_channels (ao_driver_t *this_gen) { - jack_driver_t *this = (jack_driver_t *) this_gen; - return this->num_channels; + jack_driver_t *this = (jack_driver_t *) this_gen; + return this->num_channels; } -static int ao_jack_bytes_per_frame(ao_driver_t *this_gen) +static int ao_jack_bytes_per_frame (ao_driver_t *this_gen) { - jack_driver_t *this = (jack_driver_t *) this_gen; - return this->bytes_per_frame; + jack_driver_t *this = (jack_driver_t *) this_gen; + return this->bytes_per_frame; } static int ao_jack_get_gap_tolerance (ao_driver_t *this_gen) { - return GAP_TOLERANCE; + return GAP_TOLERANCE; } -static int last_write_space = 0; - -static int ao_jack_write(ao_driver_t *this_gen, int16_t *data, - uint32_t num_frames) +/* + * Return the number of outstanding frames in all output buffers + * need to account for ring buffer plus Jack, plus soundcard + */ +static int ao_jack_delay (ao_driver_t *this_gen) { - jack_driver_t *this = (jack_driver_t *) this_gen; - uint32_t frame, channel; - - uint32_t local_buf_read = this->buf_read; - uint32_t local_buf_write = this->buf_write; - uint32_t space = (local_buf_read + BUFSIZE - local_buf_write - 1) % BUFSIZE; - uint32_t first_frame = 0; - - int c = 0; - while (space < num_frames) { - if (++c == 10) return 0; - usleep(10000); - local_buf_read = this->buf_read; - space = (local_buf_read + BUFSIZE - local_buf_write - 1) % BUFSIZE; - } - -// if (space < num_frames) return 0; - -// printf("ao_jack_write: %u frames on %u channels, space is %u\n", num_frames, this->num_channels, space); - last_write_space = space; - - for (frame = first_frame; frame < num_frames; ++frame) { - for (channel = 0; channel < this->num_channels; ++channel) { - float *buf = (channel ? this->buf_2 : this->buf_1); - int16_t sample = data[frame * this->num_channels + channel]; - buf[local_buf_write] = ((float)sample) / 32767.0f; -// printf("%6f ", buf[local_buf_write]); -// if (++c == 8) { printf("\n"); c = 0; } - } - if (++local_buf_write == BUFSIZE) local_buf_write = 0; - } - - this->buf_write = local_buf_write; + jack_driver_t *this = (jack_driver_t *) this_gen; + int frames_played = jack_frames_since_cycle_start (this->client); -// printf("ao_jack_write: buf_read %u, buf_write %u\n", this->buf_read, this->buf_write); + int delay = 0; + /* Ring Buffer always stores floats */ + /* TODO: Unsure if the delay should be fragment_size*2 or *3? */ + delay = buf_used (this) / (sizeof (float) * this->num_channels) + + this->fragment_size * 3 - frames_played; - return 1; + return delay; } -static int ao_jack_delay (ao_driver_t *this_gen) + /* Write audio samples + * num_frames is the number of audio frames present + * audio frames are equivalent one sample on each channel. + * I.E. Stereo 16 bits audio frames are 4 bytes. + * MUST SIMULATE BLOCKING WRITES + */ +static int ao_jack_write (ao_driver_t *this_gen, int16_t *frame_buffer, + uint32_t num_frames) { - jack_driver_t *this = (jack_driver_t *) this_gen; + jack_driver_t *this = (jack_driver_t *) this_gen; + int written = 0; + int num_bytes = num_frames * this->bytes_per_frame; + + /* First try and write all the bytes in one go */ + this->underrun = 0; + /* TODO: In the future Xine should pass only floats to us, so no conversion needed */ + if (this->bits_per_sample == 16) + written = write_buffer_16 (this, (char *) frame_buffer, num_bytes); + else if (this->bits_per_sample == 32) + written = write_buffer_32 (this, (char *) frame_buffer, num_bytes); + + /* If this fails then need to spin and keep trying until everything written */ + int spin_count = 0; + while ((written < num_bytes) && (spin_count < 40)) { + num_bytes -= written; + frame_buffer += written / 2; + + /* Sleep to save CPU */ + int until_callback = + this->fragment_size - jack_frames_since_cycle_start (this->client); + if ((until_callback < 0) || (until_callback > this->fragment_size)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "ao_jack_write: Invalid until_callback %d\n", until_callback); + until_callback = this->fragment_size; + } + xine_usec_sleep (((until_callback + + 100) * 1000.0 * 1000.0) / this->output_sample_rate); - uint32_t local_buf_read = this->buf_read; - uint32_t local_buf_write = this->buf_write; + if (this->bits_per_sample == 16) + written = write_buffer_16 (this, (char *) frame_buffer, num_bytes); + else if (this->bits_per_sample == 32) + written = write_buffer_32 (this, (char *) frame_buffer, num_bytes); - int delay = 0; + if (written == 0) + spin_count++; + else + spin_count = 0; - if (local_buf_write > local_buf_read) { - delay = local_buf_write - local_buf_read; - } else { - delay = ((local_buf_write + BUFSIZE - local_buf_read) % BUFSIZE); - } + if (written == 0) + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "ao_jack_write: unusual, couldn't write anything\n"); + }; - return delay;// - jack_get_buffer_size(this->client); -} + if (spin_count) + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "Nonzero spin_count...%d\n", spin_count); -static void ao_jack_close(ao_driver_t *this_gen) -{ - // nothing + return spin_count ? 0 : 1; /* return 1 on success, 0 if we got stuck for some reason */ } -static uint32_t ao_jack_get_capabilities (ao_driver_t *this_gen) { - jack_driver_t *this = (jack_driver_t *) this_gen; - return this->capabilities; -} - -static void ao_jack_exit(ao_driver_t *this_gen) +static uint32_t ao_jack_get_capabilities (ao_driver_t *this_gen) { - jack_driver_t *this = (jack_driver_t *) this_gen; - jack_client_t *client = this->client; - ao_jack_close(this_gen); - this->client = 0; - if (client) jack_client_close(client); - free (this); + jack_driver_t *this = (jack_driver_t *) this_gen; + return this->capabilities; } -static int ao_jack_get_property (ao_driver_t *this_gen, int property) { - jack_driver_t *this = (jack_driver_t *) this_gen; - - switch(property) { - case AO_PROP_PCM_VOL: - case AO_PROP_MIXER_VOL: -// printf("ao_jack_get_property(AO_PROP_MIXER_VOL): %u\n", this->volume); - return this->volume; - break; - case AO_PROP_MUTE_VOL: -// printf("ao_jack_get_property(AO_PROP_MUTE_VOL): %u\n", this->mute); - return this->mute; - break; - } +static void ao_jack_exit (ao_driver_t *this_gen) +{ + jack_driver_t *this = (jack_driver_t *) this_gen; - return 0; + ao_jack_close (this_gen); + if (this->buffer) + free (this->buffer); + free (this); } -static int ao_jack_set_property (ao_driver_t *this_gen, int property, int value) { - jack_driver_t *this = (jack_driver_t *) this_gen; - - switch(property) { - case AO_PROP_PCM_VOL: - case AO_PROP_MIXER_VOL: -// printf("ao_jack_set_property(AO_PROP_MIXER_VOL): %u\n", value); - this->volume = value; - break; - case AO_PROP_MUTE_VOL: -// printf("ao_jack_get_property(AO_PROP_MUTE_VOL): %u\n", value); - this->mute = value; - break; - } +static int ao_jack_get_property (ao_driver_t *this_gen, int property) +{ + jack_driver_t *this = (jack_driver_t *) this_gen; + + switch (property) { + case AO_PROP_PCM_VOL: + case AO_PROP_MIXER_VOL: + return this->mixer.volume; + break; + case AO_PROP_MUTE_VOL: + return this->mixer.mute; + break; + } + + return 0; +} - return ~value; +static int ao_jack_set_property (ao_driver_t *this_gen, int property, int value) +{ + jack_driver_t *this = (jack_driver_t *) this_gen; + + switch (property) { + case AO_PROP_PCM_VOL: + case AO_PROP_MIXER_VOL: + this->mixer.volume = value; + return value; + break; + case AO_PROP_MUTE_VOL: + this->mixer.mute = value; + return value; + break; + } + + return -1; } -static int ao_jack_ctrl(ao_driver_t *this_gen, int cmd, ...) { - jack_driver_t *this = (jack_driver_t *) this_gen; +static int ao_jack_ctrl (ao_driver_t *this_gen, int cmd, ...) +{ + jack_driver_t *this = (jack_driver_t *) this_gen; - switch (cmd) { + switch (cmd) { - case AO_CTRL_PLAY_PAUSE: - break; + case AO_CTRL_PLAY_PAUSE: + this->paused = 1; + break; - case AO_CTRL_PLAY_RESUME: - break; + case AO_CTRL_PLAY_RESUME: + this->paused = 0; + break; - case AO_CTRL_FLUSH_BUFFERS: -// fprintf(stderr, "ao_jack_ctrl(AO_CTRL_FLUSH_BUFFERS)\n"); - this->buf_write = this->buf_read = 0; - break; - } + case AO_CTRL_FLUSH_BUFFERS: + jack_reset (this); + break; + } - return 0; + return 0; } +static void jack_speaker_arrangement_cb (void *user_data, + xine_cfg_entry_t *entry); + static ao_driver_t *open_jack_plugin (audio_driver_class_t *class_gen, const void *data) { - jack_class_t *class = (jack_class_t *) class_gen; - jack_driver_t *this; - jack_client_t *client; - uint32_t rate; - const char **port_names; - int i; - - if ((client = jack_client_new("xine")) == 0) { - - char name[20]; - sprintf(name, "xine (%d)", (int)getpid()); - - if ((client = jack_client_new(name)) == 0) { - fprintf(stderr, "\nopen_jack_plugin: Error: Failed to connect to JACK server\n"); - fprintf(stderr, "open_jack_plugin: (did you start 'jackd' server?)\n"); - return 0; - } - } - - this = (jack_driver_t *) xine_xmalloc (sizeof (jack_driver_t)); - - this->client = client; - - jack_set_process_callback(client, jack_process, this); - jack_on_shutdown(client, jack_shutdown, this); - - rate = jack_get_sample_rate(client); - fprintf(stderr, "open_jack_plugin: JACK sample rate is %u\n", rate); - - // We support up to 2-channel output - - for (i = 0; i < 2; ++i) { - jack_port_t *port = jack_port_register - (client, (i ? "out_r" : "out_l"), - JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); - if (!port) { - fprintf(stderr, "ao_jack_open: failed to register port %u\n", i); - } - if (i) this->port_2 = port; - else this->port_1 = port; - } - - this->buf_read = this->buf_write = 0; - this->volume = 100; - this->mute = 0; - - if (jack_activate(client)) { - fprintf(stderr, "ao_jack_open: failed to activate JACK client\n"); - return 0; - } - - if ((port_names = jack_get_ports(client, NULL, NULL, - JackPortIsPhysical | JackPortIsInput)) != NULL) { - if (port_names[0]) { - jack_connect(client, jack_port_name(this->port_1), port_names[0]); - } - if (port_names[1] && this->port_2) { - jack_connect(client, jack_port_name(this->port_2), port_names[1]); - } - free(port_names); - } + jack_class_t *class = (jack_class_t *) class_gen; + config_values_t *config = class->config; + jack_driver_t *this; + + jack_client_t *client; + uint32_t rate; + char *jack_device; + const char **matching_ports = NULL; + const char **port_names; + + /* for usability reasons, keep this in sync with audio_oss_out.c */ + static char *speaker_arrangement[] = { + "Mono 1.0", "Stereo 2.0", "Headphones 2.0", "Stereo 2.1", + "Surround 3.0", "Surround 4.0", "Surround 4.1", "Surround 5.0", + "Surround 5.1", "Surround 6.0", + "Surround 6.1", "Surround 7.1", "Pass Through", NULL + }; +#define MONO 0 +#define STEREO 1 +#define HEADPHONES 2 +#define SURROUND21 3 +#define SURROUND3 4 +#define SURROUND4 5 +#define SURROUND41 6 +#define SURROUND5 7 +#define SURROUND51 8 +#define SURROUND6 9 +#define SURROUND61 10 +#define SURROUND71 11 +#define A52_PASSTHRU 12 + int speakers; + + /* Try to create a client called "xine[-NN]" */ + if ((client = jack_client_open ("xine", JackNullOption, NULL)) == 0) { + xprintf (class->xine, XINE_VERBOSITY_LOG, + "\nopen_jack_plugin: Error: Failed to connect to JACK server\n"); + return 0; + } + + this = calloc(1, sizeof (jack_driver_t)); + + rate = jack_get_sample_rate (client); + xprintf (class->xine, XINE_VERBOSITY_DEBUG, + "open_jack_plugin: JACK sample rate is %u\n", rate); + + /* devname_val is offset used to select auto, /dev/dsp, or /dev/sound/dsp */ + jack_device = config->register_string (config, + "audio.device.jack_device_name", + "", + _("JACK audio device name"), + _("Specifies the jack audio device name, " + "leave blank for the default physical output port."), + 10, NULL, NULL); + + this->capabilities = 0; + + + /* for usability reasons, keep this in sync with audio_alsa_out.c */ + speakers = + config->register_enum (config, "audio.output.speaker_arrangement", + STEREO, speaker_arrangement, + _("speaker arrangement"), + _("Select how your speakers are arranged, " + "this determines which speakers xine uses for sound output. " + "The individual values are:\n\n" + "Mono 1.0: You have only one speaker.\n" + "Stereo 2.0: You have two speakers for left and right channel.\n" + "Headphones 2.0: You use headphones.\n" + "Stereo 2.1: You have two speakers for left and right channel, and one " + "subwoofer for the low frequencies.\n" + "Surround 3.0: You have three speakers for left, right and rear channel.\n" + "Surround 4.0: You have four speakers for front left and right and rear " + "left and right channels.\n" + "Surround 4.1: You have four speakers for front left and right and rear " + "left and right channels, and one subwoofer for the low frequencies.\n" + "Surround 5.0: You have five speakers for front left, center and right and " + "rear left and right channels.\n" + "Surround 5.1: You have five speakers for front left, center and right and " + "rear left and right channels, and one subwoofer for the low frequencies.\n" + "Surround 6.0: You have six speakers for front left, center and right and " + "rear left, center and right channels.\n" + "Surround 6.1: You have six speakers for front left, center and right and " + "rear left, center and right channels, and one subwoofer for the low frequencies.\n" + "Surround 7.1: You have seven speakers for front left, center and right, " + "left and right and rear left and right channels, and one subwoofer for the " + "low frequencies.\n" + "Pass Through: Your sound system will receive undecoded digital sound from xine. " + "You need to connect a digital surround decoder capable of decoding the " + "formats you want to play to your sound card's digital output."), + 0, jack_speaker_arrangement_cb, this); + + int port_flags = JackPortIsInput; + int num_ports; + /* list matching ports */ + if (!jack_device) + port_flags |= JackPortIsPhysical; + /* Find all the ports matching either the desired device regexp or physical output ports */ + matching_ports = jack_get_ports (client, jack_device, NULL, port_flags); + /* Count 'em */ + for (num_ports = 0; matching_ports && matching_ports[num_ports]; + num_ports++) + /**/; + if (!num_ports) { + xprintf (this->xine, XINE_VERBOSITY_LOG, + "open_jack_plugin: no physical ports available\n"); + goto err_out; + } + + +/* TODO: We deliberately don't offer mono, let Xine upsample instead? */ +/* if (num_ports >= 1) { */ +/* this->capabilities |= AO_CAP_MODE_MONO; */ +/* xprintf(class->xine, XINE_VERBOSITY_DEBUG, "mono "); */ +/* } */ + + if (num_ports >= 2) { + this->capabilities |= AO_CAP_MODE_STEREO; + xprintf (class->xine, XINE_VERBOSITY_DEBUG, "stereo "); + } + + if (num_ports >= 4) { + if (speakers == SURROUND4) { + this->capabilities |= AO_CAP_MODE_4CHANNEL; + xprintf (class->xine, XINE_VERBOSITY_DEBUG, "4-channel "); + } else + xprintf (class->xine, XINE_VERBOSITY_DEBUG, + "(4-channel not enabled in xine config) "); + } + + if (num_ports >= 5) { + if (speakers == SURROUND5) { + this->capabilities |= AO_CAP_MODE_5CHANNEL; + xprintf (class->xine, XINE_VERBOSITY_DEBUG, "5-channel "); + } else + xprintf (class->xine, XINE_VERBOSITY_DEBUG, + "(5-channel not enabled in xine config) "); + } + + if (num_ports >= 6) { + if (speakers == SURROUND51) { + this->capabilities |= AO_CAP_MODE_5_1CHANNEL; + xprintf (class->xine, XINE_VERBOSITY_DEBUG, "5.1-channel "); + } else + xprintf (class->xine, XINE_VERBOSITY_DEBUG, + "(5.1-channel not enabled in xine config) "); + } + + this->buffer = (unsigned char *) malloc (BUFFSIZE); + jack_reset (this); + + this->capabilities |= AO_CAP_MIXER_VOL; + this->capabilities |= AO_CAP_MUTE_VOL; + /* TODO: Currently not respected by Xine, perhaps v1.2? */ + this->capabilities |= AO_CAP_FLOAT32; + + + this->mixer.mute = 0; + this->mixer.volume = 100; + + this->output_sample_rate = jack_get_sample_rate (client); + this->fragment_size = jack_get_buffer_size (client); + + /* Close our JACK client */ + jack_client_close (client); + + this->xine = class->xine; + + this->ao_driver.get_capabilities = ao_jack_get_capabilities; + this->ao_driver.get_property = ao_jack_get_property; + this->ao_driver.set_property = ao_jack_set_property; + this->ao_driver.open = ao_jack_open; + this->ao_driver.num_channels = ao_jack_num_channels; + this->ao_driver.bytes_per_frame = ao_jack_bytes_per_frame; + this->ao_driver.delay = ao_jack_delay; + this->ao_driver.write = ao_jack_write; + this->ao_driver.close = ao_jack_close; + this->ao_driver.exit = ao_jack_exit; + this->ao_driver.get_gap_tolerance = ao_jack_get_gap_tolerance; + this->ao_driver.control = ao_jack_ctrl; + + return &this->ao_driver; + +err_out: + free (matching_ports); + if (client) + jack_client_close (client); + return 0; +} - this->sample_rate = rate; - - this->xine = class->xine; - this->capabilities = AO_CAP_FLOAT32 | AO_CAP_MODE_MONO | - AO_CAP_MODE_STEREO | AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL; - - this->ao_driver.get_capabilities = ao_jack_get_capabilities; - this->ao_driver.get_property = ao_jack_get_property; - this->ao_driver.set_property = ao_jack_set_property; - this->ao_driver.open = ao_jack_open; - this->ao_driver.num_channels = ao_jack_num_channels; - this->ao_driver.bytes_per_frame = ao_jack_bytes_per_frame; - this->ao_driver.delay = ao_jack_delay; - this->ao_driver.write = ao_jack_write; - this->ao_driver.close = ao_jack_close; - this->ao_driver.exit = ao_jack_exit; - this->ao_driver.get_gap_tolerance = ao_jack_get_gap_tolerance; - this->ao_driver.control = ao_jack_ctrl; - - fprintf(stderr, "jack open_jack_plugin returning %p\n", (void *)(&this->ao_driver)); - return &this->ao_driver; +static void jack_speaker_arrangement_cb (void *user_data, + xine_cfg_entry_t *entry) +{ + jack_driver_t *this = (jack_driver_t *) user_data; + int32_t value = entry->num_value; + if (value == SURROUND4) { + this->capabilities |= AO_CAP_MODE_4CHANNEL; + } else { + this->capabilities &= ~AO_CAP_MODE_4CHANNEL; + } + if (value == SURROUND41) { + this->capabilities |= AO_CAP_MODE_4_1CHANNEL; + } else { + this->capabilities &= ~AO_CAP_MODE_4_1CHANNEL; + } + if (value == SURROUND5) { + this->capabilities |= AO_CAP_MODE_5CHANNEL; + } else { + this->capabilities &= ~AO_CAP_MODE_5CHANNEL; + } + if (value >= SURROUND51) { + this->capabilities |= AO_CAP_MODE_5_1CHANNEL; + } else { + this->capabilities &= ~AO_CAP_MODE_5_1CHANNEL; + } } /* * class functions */ -static char* get_identifier (audio_driver_class_t *this_gen) { - return "jack"; +static char *get_identifier (audio_driver_class_t *this_gen) +{ + return "jack"; } -static char* get_description (audio_driver_class_t *this_gen) { - return _("xine output plugin for JACK Audio Connection Kit"); +static char *get_description (audio_driver_class_t *this_gen) +{ + return _("xine output plugin for JACK Audio Connection Kit"); } -static void dispose_class (audio_driver_class_t *this_gen) { - - jack_class_t *this = (jack_class_t *) this_gen; - free (this); +static void dispose_class (audio_driver_class_t *this_gen) +{ + jack_class_t *this = (jack_class_t *) this_gen; + free (this); } -static void *init_class (xine_t *xine, void *data) { - - jack_class_t *this; - - this = (jack_class_t *) xine_xmalloc (sizeof (jack_class_t)); +static void *init_class (xine_t *xine, void *data) +{ + jack_class_t *this; - this->driver_class.open_plugin = open_jack_plugin; - this->driver_class.get_identifier = get_identifier; - this->driver_class.get_description = get_description; - this->driver_class.dispose = dispose_class; + this = calloc(1, sizeof (jack_class_t)); - this->config = xine->config; - this->xine = xine; + this->driver_class.open_plugin = open_jack_plugin; + this->driver_class.get_identifier = get_identifier; + this->driver_class.get_description = get_description; + this->driver_class.dispose = dispose_class; - fprintf(stderr, "jack init_class returning %p\n", (void *)this); + this->config = xine->config; + this->xine = xine; - return this; + return this; } -static ao_info_t ao_info_jack = { - 6 -}; +static ao_info_t ao_info_jack = { 6 }; /* * exported plugin catalog entry */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ - { PLUGIN_AUDIO_OUT, AO_OUT_JACK_IFACE_VERSION, "jack", XINE_VERSION_CODE /* XINE_VERSION_CODE */, &ao_info_jack, init_class }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_AUDIO_OUT, AO_OUT_JACK_IFACE_VERSION, "jack", XINE_VERSION_CODE, + &ao_info_jack, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; - diff --git a/src/audio_out/audio_none_out.c b/src/audio_out/audio_none_out.c index a815d645a..c3d351035 100644 --- a/src/audio_out/audio_none_out.c +++ b/src/audio_out/audio_none_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -40,7 +40,7 @@ #define AUDIO_NUM_FRAGMENTS 15 #define AUDIO_FRAGMENT_SIZE 8192 -#define GAP_TOLERANCE AO_MAX_GAP +#define GAP_TOLERANCE AO_MAX_GAP typedef struct none_driver_s { @@ -74,7 +74,7 @@ static int ao_none_open(ao_driver_t *this_gen, uint32_t bits, uint32_t rate, int { none_driver_t *this = (none_driver_t *) this_gen; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_none_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); this->mode = mode; @@ -115,13 +115,13 @@ static int ao_none_write(ao_driver_t *this_gen, int16_t *data, uint32_t num_frames) { none_driver_t *this = (none_driver_t *) this_gen; - + /* take some time to pretend we are doing something. * avoids burning cpu. */ if( (1000 * num_frames / this->sample_rate) > 10 ) xine_usec_sleep ((1000 * num_frames / this->sample_rate)*1000/2); - + return 1; } @@ -143,7 +143,7 @@ static uint32_t ao_none_get_capabilities (ao_driver_t *this_gen) { static void ao_none_exit(ao_driver_t *this_gen) { none_driver_t *this = (none_driver_t *) this_gen; - + ao_none_close(this_gen); free (this); @@ -177,7 +177,7 @@ static int ao_none_ctrl(ao_driver_t *this_gen, int cmd, ...) { return 0; } -static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) { none_class_t *class = (none_class_t *) class_gen; @@ -186,7 +186,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, lprintf ("open_plugin called\n"); - this = (none_driver_t *) xine_xmalloc (sizeof (none_driver_t)); + this = calloc(1, sizeof (none_driver_t)); if (!this) return NULL; @@ -236,7 +236,7 @@ static void *init_class (xine_t *xine, void *data) { lprintf ("init class\n"); - this = (none_class_t *) xine_xmalloc (sizeof (none_class_t)); + this = calloc(1, sizeof (none_class_t)); if (!this) return NULL; @@ -260,7 +260,7 @@ static const ao_info_t ao_info_none = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_NONE_IFACE_VERSION, "none", XINE_VERSION_CODE, &ao_info_none, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_oss_out.c b/src/audio_out/audio_oss_out.c index a6e0fe494..bd16a6dd3 100644 --- a/src/audio_out/audio_oss_out.c +++ b/src/audio_out/audio_oss_out.c @@ -1,25 +1,25 @@ -/* - * Copyright (C) 2000-2003 the xine project - * +/* + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * 20-8-2001 First implementation of Audio sync and Audio driver separation. * Copyright (C) 2001 James Courtier-Dutton James@superbug.demon.co.uk - * + * * General Programming Guidelines: - * New concept of an "audio_frame". * An audio_frame consists of all the samples required to fill every audio channel @@ -90,7 +90,7 @@ #endif #ifndef AFMT_AC3 -# define AFMT_AC3 0x00000400 +# define AFMT_AC3 0x00000400 #endif #define AO_OUT_OSS_IFACE_VERSION 8 @@ -127,7 +127,7 @@ typedef struct oss_driver_s { uint32_t bytes_per_frame; uint32_t bytes_in_buffer; /* number of bytes writen to audio hardware */ uint32_t last_getoptr; - + int audio_started; int sync_method; int latency; @@ -178,7 +178,7 @@ static int ao_oss_open(ao_driver_t *this_gen, close (this->audio_fd); } - + this->mode = mode; this->input_sample_rate = rate; this->bits_per_sample = bits; @@ -192,11 +192,11 @@ static int ao_oss_open(ao_driver_t *this_gen, this->audio_fd=open(this->audio_dev,O_WRONLY|O_NONBLOCK); if (this->audio_fd < 0) { - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: Opening audio device %s: %s\n"), this->audio_dev, strerror(errno)); return 0; } - + /* We wanted non blocking open but now put it back to normal */ fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL)&~O_NONBLOCK); @@ -213,8 +213,8 @@ static int ao_oss_open(ao_driver_t *this_gen, tmp = this->input_sample_rate; if (ioctl(this->audio_fd,SNDCTL_DSP_SPEED, &tmp) == -1) { - - xprintf(this->xine, XINE_VERBOSITY_LOG, + + xprintf(this->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: warning: sampling rate %d Hz not supported, trying 44100 Hz\n"), this->input_sample_rate); @@ -272,7 +272,7 @@ static int ao_oss_open(ao_driver_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "audio_oss_out: %d channels output\n", this->num_channels); this->bytes_per_frame=(this->bits_per_sample*this->num_channels)/8; - + /* * set format */ @@ -303,7 +303,7 @@ static int ao_oss_open(ao_driver_t *this_gen, else xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: The AFMT_S16_NE ioctl failed.\n"); return 0; - } + } } break; case AO_CAP_MODE_A52: @@ -317,7 +317,7 @@ static int ao_oss_open(ao_driver_t *this_gen, ioctl(this->audio_fd, SNDCTL_DSP_CHANNELS, &tmp); tmp = AFMT_AC3; if (ioctl(this->audio_fd, SNDCTL_DSP_SETFMT, &tmp) < 0 || tmp != AFMT_AC3) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: AC3 SNDCTL_DSP_SETFMT failed. %d. Using alternative.\n",tmp); tmp = AFMT_S16_LE; ioctl(this->audio_fd, SNDCTL_DSP_SETFMT, &tmp); @@ -344,7 +344,7 @@ static int ao_oss_open(ao_driver_t *this_gen, printf ("audio_oss_out: audio buffer fragment info : %x\n",tmp); - ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp); + ioctl(this->audio_fd,SNDCTL_DSP_SETFRAGMENT,&tmp); */ return this->output_sample_rate; @@ -395,9 +395,9 @@ static int ao_oss_delay(ao_driver_t *this_gen) { * this->output_sample_k_rate / 1000; frames += (tv.tv_sec - this->start_time.tv_sec) * this->output_sample_rate; - + frames -= this->latency * this->output_sample_k_rate; - + /* calc delay */ bytes_left = this->bytes_in_buffer - frames * this->bytes_per_frame; @@ -405,35 +405,37 @@ static int ao_oss_delay(ao_driver_t *this_gen) { if (bytes_left<=0) /* buffer ran dry */ bytes_left = 0; break; + case OSS_SYNC_GETODELAY: +#ifdef SNDCTL_DSP_GETODELAY + if (ioctl (this->audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) { + perror ("audio_oss_out: DSP_GETODELAY ioctl():"); + } + if (bytes_left<0) + bytes_left = 0; + + lprintf ("%d bytes left\n", bytes_left); + + break; +#endif case OSS_SYNC_GETOPTR: if (ioctl (this->audio_fd, SNDCTL_DSP_GETOPTR, &info)) { perror ("audio_oss_out: SNDCTL_DSP_GETOPTR failed:"); } - + lprintf ("%d bytes output\n", info.bytes); if (this->bytes_in_buffer < info.bytes) { this->bytes_in_buffer -= this->last_getoptr; /* GETOPTR wrapped */ - } - + } + bytes_left = this->bytes_in_buffer - info.bytes; /* calc delay */ - + if (bytes_left<=0) { /* buffer ran dry */ bytes_left = 0; this->bytes_in_buffer = info.bytes; } this->last_getoptr = info.bytes; break; - case OSS_SYNC_GETODELAY: - if (ioctl (this->audio_fd, SNDCTL_DSP_GETODELAY, &bytes_left)) { - perror ("audio_oss_out: DSP_GETODELAY ioctl():"); - } - if (bytes_left<0) - bytes_left = 0; - - lprintf ("%d bytes left\n", bytes_left); - - break; } return bytes_left / this->bytes_per_frame; @@ -474,7 +476,7 @@ static int ao_oss_write(ao_driver_t *this_gen, this->bytes_in_buffer += num_frames * this->bytes_per_frame; - n = write(this->audio_fd, frame_buffer, num_frames * this->bytes_per_frame); + n = write(this->audio_fd, frame_buffer, num_frames * this->bytes_per_frame); lprintf ("ao_oss_write done\n"); @@ -518,20 +520,20 @@ static int ao_oss_get_property (ao_driver_t *this_gen, int property) { case AO_PROP_PCM_VOL: case AO_PROP_MIXER_VOL: if(!this->mixer.mute) { - + if(this->mixer.fd != -1) { IOCTL_REQUEST_TYPE cmd = 0; int v; - + ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs); - + if(audio_devs & SOUND_MASK_PCM) cmd = SOUND_MIXER_READ_PCM; else if(audio_devs & SOUND_MASK_VOLUME) cmd = SOUND_MIXER_READ_VOLUME; else return -1; - + ioctl(this->mixer.fd, cmd, &v); this->mixer.volume = (((v & 0xFF00) >> 8) + (v & 0x00FF)) / 2; } else @@ -557,20 +559,20 @@ static int ao_oss_set_property (ao_driver_t *this_gen, int property, int value) case AO_PROP_PCM_VOL: case AO_PROP_MIXER_VOL: if(!this->mixer.mute) { - + if(this->mixer.fd != -1) { IOCTL_REQUEST_TYPE cmd = 0; int v; - + ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs); - + if(audio_devs & SOUND_MASK_PCM) cmd = SOUND_MIXER_WRITE_PCM; else if(audio_devs & SOUND_MASK_VOLUME) cmd = SOUND_MIXER_WRITE_VOLUME; else return -1; - + v = (value << 8) | value; ioctl(this->mixer.fd, cmd, &v); this->mixer.volume = value; @@ -586,26 +588,26 @@ static int ao_oss_set_property (ao_driver_t *this_gen, int property, int value) this->mixer.mute = (value) ? 1 : 0; if(this->mixer.mute) { - + if(this->mixer.fd != -1) { IOCTL_REQUEST_TYPE cmd = 0; int v = 0; - + ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs); - + if(audio_devs & SOUND_MASK_PCM) cmd = SOUND_MIXER_WRITE_PCM; else if(audio_devs & SOUND_MASK_VOLUME) cmd = SOUND_MIXER_WRITE_VOLUME; else return -1; - + ioctl(this->mixer.fd, cmd, &v); } else return -1; } else (void) ao_oss_set_property(&this->ao_driver, this->mixer.prop, this->mixer.volume); - + return value; break; } @@ -623,7 +625,7 @@ static int ao_oss_ctrl(ao_driver_t *this_gen, int cmd, ...) { if (this->sync_method != OSS_SYNC_SOFTSYNC) ioctl(this->audio_fd, SNDCTL_DSP_RESET, NULL); - + /* close/reopen if RESET causes problems */ if (this->sync_method == OSS_SYNC_GETOPTR) { ao_oss_close(this_gen); @@ -639,7 +641,7 @@ static int ao_oss_ctrl(ao_driver_t *this_gen, int cmd, ...) { lprintf ("AO_CTRL_FLUSH_BUFFERS\n"); if (this->sync_method != OSS_SYNC_SOFTSYNC) ioctl(this->audio_fd, SNDCTL_DSP_RESET, NULL); - + if (this->sync_method == OSS_SYNC_GETOPTR) { ao_oss_close(this_gen); ao_oss_open(this_gen, this->bits_per_sample, this->input_sample_rate, this->mode); @@ -685,14 +687,14 @@ static int probe_audio_devices(oss_driver_t *this) { strcpy(this->audio_dev, devname); /* Better, keep this one */ best_rate = rate; } - + close (audio_fd); } } } return best_rate; /* Will be zero if we did not find one */ -} - +} + static void oss_speaker_arrangement_cb (void *user_data, xine_cfg_entry_t *entry); @@ -726,8 +728,8 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da #define A52_PASSTHRU 12 int speakers; - - this = (oss_driver_t *) xine_xmalloc (sizeof (oss_driver_t)); + + this = calloc(1, sizeof (oss_driver_t)); if (!this) return NULL; @@ -760,7 +762,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: audio.device.oss_device_name = auto, probing devs\n")); if ( ! probe_audio_devices(this)) { /* Returns zero on fail */ - xprintf(class->xine, XINE_VERBOSITY_LOG, + xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: Auto probe for audio device failed\n")); free (this); return NULL; @@ -782,18 +784,18 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da audio_fd = open(this->audio_dev, O_WRONLY|O_NONBLOCK); if (audio_fd < 0) { - xprintf(class->xine, XINE_VERBOSITY_LOG, + xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: opening audio device %s failed:\n%s\n"), this->audio_dev, strerror(errno)); free (this); return NULL; - } + } /* * set up driver to reasonable values for capabilities tests */ - arg = AFMT_S16_NE; + arg = AFMT_S16_NE; status = ioctl(audio_fd, SNDCTL_DSP_SETFMT, &arg); arg = 44100; status = ioctl(audio_fd, SNDCTL_DSP_SPEED, &arg); @@ -803,7 +805,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da */ this->sync_method = config->register_enum (config, "audio.oss_sync_method", OSS_SYNC_AUTO_DETECT, - sync_methods, + sync_methods, _("a/v sync method to use by OSS"), _("xine can use different methods to keep audio and video " "synchronized. Which setting works best depends on the " @@ -840,10 +842,13 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da * check if SNDCTL_DSP_GETODELAY works. if so, using it is preferred. */ +#ifdef SNDCTL_DSP_GETODELAY if (ioctl(audio_fd, SNDCTL_DSP_GETODELAY, &info) != -1) { xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: using SNDCTL_DSP_GETODELAY\n"); this->sync_method = OSS_SYNC_GETODELAY; - } else if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) != -1) { + } else +#endif + if (ioctl(audio_fd, SNDCTL_DSP_GETOPTR, &info) != -1) { xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: using SNDCTL_DSP_GETOPTR\n"); this->sync_method = OSS_SYNC_GETOPTR; } else { @@ -857,9 +862,9 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da "audio_oss_out: ...will use system real-time clock for soft-sync instead\n" "audio_oss_out: ...there may be audio/video synchronization issues\n")); xine_monotonic_clock(&this->start_time, NULL); - + this->latency = config->register_range (config, "audio.oss_latency", 0, - -3000, 3000, + -3000, 3000, _("OSS audio output latency (adjust a/v sync)"), _("If you experience audio being not in sync " "with the video, you can enter a fixed offset " @@ -868,34 +873,30 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da "of a second."), 20, NULL, NULL); } - + if (this->sync_method == OSS_SYNC_PROBEBUFFER) { char *buf; int c; - - xprintf(class->xine, XINE_VERBOSITY_LOG, - _("audio_oss_out: Audio driver realtime sync disabled...\n" - "audio_oss_out: ...probing output buffer size: ")); + this->buffer_size = 0; - - if( (buf=malloc(1024)) != NULL ) { - memset(buf,0,1024); - + + if( (buf=calloc(1, 1024)) != NULL ) { do { c = write(audio_fd,buf,1024); if( c != -1 ) this->buffer_size += c; } while( c == 1024 ); - + free(buf); } close(audio_fd); xprintf(class->xine, XINE_VERBOSITY_LOG, - _("%d bytes\naudio_oss_out: ...there may be audio/video synchronization issues\n"), this->buffer_size); + _("audio_oss_out: Audio driver realtime sync disabled...\n" + "audio_oss_out: ...probing output buffer size: %d bytes\naudio_oss_out: ...there may be audio/video synchronization issues\n"), this->buffer_size); audio_fd=open(this->audio_dev, O_WRONLY|O_NONBLOCK); - if(audio_fd < 0) + if(audio_fd < 0) { xprintf(class->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: opening audio device %s failed:\n%s\n"), this->audio_dev, strerror(errno)); @@ -906,11 +907,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da } this->capabilities = 0; - + arg = AFMT_U8; if( ioctl(audio_fd, SNDCTL_DSP_SETFMT, &arg) != -1 && arg == AFMT_U8) this->capabilities |= AO_CAP_8BITS; - + /* switch back to 16bits, because some soundcards otherwise do not report all their capabilities */ arg = AFMT_S16_NE; if (ioctl(audio_fd, SNDCTL_DSP_SETFMT, &arg) == -1 || arg != AFMT_S16_NE) { @@ -954,48 +955,48 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da 0, oss_speaker_arrangement_cb, this); - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "audio_oss_out: supported modes are "); - num_channels = 1; - status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + char *logmsg = strdup (_("audio_oss_out: supported modes are")); + num_channels = 1; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); if ( (status != -1) && (num_channels==1) ) { this->capabilities |= AO_CAP_MODE_MONO; - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "mono "); + xine_strcat_realloc (&logmsg, _(" mono")); } - num_channels = 2; - status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + num_channels = 2; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); if ( (status != -1) && (num_channels==2) ) { this->capabilities |= AO_CAP_MODE_STEREO; - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "stereo "); + xine_strcat_realloc (&logmsg, _(" stereo")); } - num_channels = 4; - status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + num_channels = 4; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); if ( (status != -1) && (num_channels==4) ) { if ( speakers == SURROUND4 ) { this->capabilities |= AO_CAP_MODE_4CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "4-channel "); - } + xine_strcat_realloc (&logmsg, _(" 4-channel")); + } else - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(4-channel not enabled in xine config) " ); + xine_strcat_realloc (&logmsg, _(" (4-channel not enabled in xine config)")); } - num_channels = 5; - status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + num_channels = 5; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); if ( (status != -1) && (num_channels==5) ) { if ( speakers == SURROUND5 ) { this->capabilities |= AO_CAP_MODE_5CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "5-channel "); + xine_strcat_realloc (&logmsg, _(" 5-channel")); } else - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(5-channel not enabled in xine config) " ); + xine_strcat_realloc (&logmsg, _(" (5-channel not enabled in xine config)")); } - num_channels = 6; - status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); + num_channels = 6; + status = ioctl(audio_fd, SNDCTL_DSP_CHANNELS, &num_channels); if ( (status != -1) && (num_channels==6) ) { if ( speakers == SURROUND51 ) { this->capabilities |= AO_CAP_MODE_5_1CHANNEL; - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "5.1-channel "); - } + xine_strcat_realloc (&logmsg, _(" 5.1-channel")); + } else - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(5.1-channel not enabled in xine config) " ); + xine_strcat_realloc (&logmsg, _(" (5.1-channel not enabled in xine config)")); } ioctl(audio_fd,SNDCTL_DSP_GETFMTS,&caps); @@ -1005,11 +1006,14 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da if ( speakers == A52_PASSTHRU ) { this->capabilities |= AO_CAP_MODE_A52; this->capabilities |= AO_CAP_MODE_AC5; - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "a/52-pass-through "); - } - else - xprintf(class->xine, XINE_VERBOSITY_DEBUG, "(a/52-pass-through not enabled in xine config)"); - + xine_strcat_realloc (&logmsg, _(" a/52 pass-through")); + } + else + xine_strcat_realloc (&logmsg, _(" (a/52 pass-through not enabled in xine config)")); + + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "%s\n", logmsg); + free (logmsg); + /* * mixer initialisation. */ @@ -1018,7 +1022,7 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da int mixer_num; int audio_devs; char *parse; - + mixer_num = config->register_num(config, "audio.device.oss_mixer_number", -1, _("OSS audio mixer number, -1 for none"), _("The full mixer device name is created by taking the " @@ -1029,33 +1033,30 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da "The range of this value is -1 or 0-15. This setting is " "ignored, when the OSS audio device name is set to \"auto\"."), 10, NULL, NULL); - + /* get the mixer device name from the audio device name by replacing "dsp" with "mixer" */ strcpy(mixer_name, this->audio_dev); if ((parse = strstr(mixer_name, "dsp"))) { parse[0] = '\0'; parse += 3; - this->mixer.name = (char *)malloc(strlen(mixer_name) + sizeof("mixer") + 2); if (devname_val == 0) - sprintf(this->mixer.name, "%smixer%s", mixer_name, parse); + asprintf(&(this->mixer.name), "%smixer%s", mixer_name, parse); else { if (mixer_num == -1) - sprintf(this->mixer.name, "%smixer", mixer_name); + asprintf(&(this->mixer.name), "%smixer", mixer_name); else - sprintf(this->mixer.name, "%smixer%d", mixer_name, mixer_num); + asprintf(&(this->mixer.name), "%smixer%d", mixer_name, mixer_num); } } else { - this->mixer.name = (char *)malloc(1); - this->mixer.name[0] = '\0'; + _x_abort(); } - _x_assert(this->mixer.name[0] != '\0'); - + this->mixer.fd = open(this->mixer.name, O_RDONLY); if(this->mixer.fd != -1) { ioctl(this->mixer.fd, SOUND_MIXER_READ_DEVMASK, &audio_devs); - + if(audio_devs & SOUND_MASK_PCM) { this->capabilities |= AO_CAP_PCM_VOL; this->mixer.prop = AO_PROP_PCM_VOL; @@ -1064,9 +1065,9 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da this->capabilities |= AO_CAP_MIXER_VOL; this->mixer.prop = AO_PROP_MIXER_VOL; } - + /* - * This is obsolete in Linux kernel OSS + * This is obsolete in Linux kernel OSS * implementation, so this will certainly doesn't work. * So we just simulate the mute stuff */ @@ -1075,11 +1076,11 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da this->capabilities |= AO_CAP_MUTE_VOL; */ this->capabilities |= AO_CAP_MUTE_VOL; - - } else + + } else xprintf (class->xine, XINE_VERBOSITY_LOG, _("audio_oss_out: open() mixer %s failed: %s\n"), this->mixer.name, strerror(errno)); - + this->mixer.mute = 0; this->mixer.volume = ao_oss_get_property (&this->ao_driver, this->mixer.prop); @@ -1165,7 +1166,7 @@ static void *init_class (xine_t *xine, void *data) { oss_class_t *this; - this = (oss_class_t *) xine_xmalloc (sizeof (oss_class_t)); + this = calloc(1, sizeof (oss_class_t)); if (!this) return NULL; @@ -1189,7 +1190,7 @@ static const ao_info_t ao_info_oss = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_OUT_OSS_IFACE_VERSION, "oss", XINE_VERSION_CODE, &ao_info_oss, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c index 26d121bf6..d4d19ce1b 100644 --- a/src/audio_out/audio_pulse_out.c +++ b/src/audio_out/audio_pulse_out.c @@ -1,28 +1,28 @@ -/* - * Copyright (C) 2000-2007 the xine project - * +/* -*- Mode: C; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * ao plugin for pulseaudio (rename of polypaudio): + * ao plugin for PulseAudio: * http://0pointer.de/lennart/projects/pulsaudio/ * - * originally written for polypaudio simple api. Lennart then suggested - * using the async api for better control (such as volume), therefore, a lot - * of this code comes from Lennart's patch to mplayer. + * Diego Petteno, Lennart Poettering */ #ifdef HAVE_CONFIG_H @@ -48,15 +48,9 @@ #define GAP_TOLERANCE AO_MAX_GAP -/* CHECKME: should this be conditional on autotools? */ -extern const char *__progname; - typedef struct { audio_driver_class_t driver_class; xine_t *xine; - - struct pa_context *context; /*< Pulseaudio connection context */ - struct pa_threaded_mainloop *mainloop; /*< Main event loop object */ } pulse_class_t; typedef struct pulse_driver_s { @@ -67,11 +61,13 @@ typedef struct pulse_driver_s { char *host; /*< The host to connect to */ char *sink; /*< The sink to connect to */ - struct pa_stream *stream; /*< Pulseaudio playback stream object */ - pthread_mutex_t info_mutex; /**< Mutex for info callback signaling */ + pa_threaded_mainloop *mainloop; /*< Main event loop object */ + pa_context *context; /*< Pulseaudio connection context */ + pa_stream *stream; /*< Pulseaudio playback stream object */ pa_volume_t swvolume; + int muted; pa_cvolume cvolume; int capabilities; @@ -82,67 +78,117 @@ typedef struct pulse_driver_s { uint32_t bits_per_sample; uint32_t bytes_per_frame; - uint32_t frames_written; - } pulse_driver_t; /** - * @brief Callback function called when a stream operation succeed - * @param stream Stream which operation has succeeded - * @param success The success value for the operation (ignored) - * @param this_Gen pulse_driver_t pointer for the PulseAudio output - * instance. + * @brief Callback function called when the state of the context is changed + * @param c Context which changed status + * @param this_gen pulse_class_t pointer for the PulseAudio output class */ -static void __xine_pa_stream_success_callback(pa_stream *const stream, const int success, - void *const mutex_gen) +static void __xine_pa_context_state_callback(pa_context *c, void *this_gen) { - pthread_mutex_t *const completion_mutex = (pthread_mutex_t*)mutex_gen; + pulse_driver_t * this = (pulse_driver_t*) this_gen; + + switch (pa_context_get_state(c)) { - pthread_mutex_unlock(completion_mutex); + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: + pa_threaded_mainloop_signal(this->mainloop, 0); + break; + + case PA_CONTEXT_CONNECTING: + case PA_CONTEXT_UNCONNECTED: + case PA_CONTEXT_AUTHORIZING: + case PA_CONTEXT_SETTING_NAME: + break; + } } /** - * @brief Callback function called when the state of the context is changed - * @param ctx Context which operation has succeeded + * @brief Callback function called when the state of the stream is changed + * @param s Stream that changed status * @param this_gen pulse_driver_t pointer for the PulseAudio output * instance. */ -static void __xine_pa_context_status_callback(pa_context *const ctx, void *const this_gen) +static void __xine_pa_stream_state_callback(pa_stream *s, void *this_gen) { - pulse_driver_t *const this = (pulse_driver_t*)this_gen; - - switch (pa_context_get_state(ctx)) { - case PA_CONTEXT_READY: - case PA_CONTEXT_TERMINATED: - case PA_CONTEXT_FAILED: - pa_threaded_mainloop_signal(this->pa_class->mainloop, 0); - break; - - case PA_CONTEXT_CONNECTING: - case PA_CONTEXT_UNCONNECTED: - case PA_CONTEXT_AUTHORIZING: - case PA_CONTEXT_SETTING_NAME: - break; + pulse_driver_t * this = (pulse_driver_t*) this_gen; + + switch (pa_stream_get_state(s)) { + + case PA_STREAM_READY: + case PA_STREAM_TERMINATED: + case PA_STREAM_FAILED: + pa_threaded_mainloop_signal(this->mainloop, 0); + break; + + case PA_STREAM_UNCONNECTED: + case PA_STREAM_CREATING: + break; } } /** - * @brief Callback function called when a context operation succeed + * @brief Callback function called when PA asks for more audio data. + * @param s Stream on which data is requested + * @param nbytes the number of bytes PA requested + * @param this_gen pulse_driver_t pointer for the PulseAudio output + * instance. + */ +static void __xine_pa_stream_request_callback(pa_stream *s, size_t nbytes, void *this_gen) +{ + pulse_driver_t * this = (pulse_driver_t*) this_gen; + + pa_threaded_mainloop_signal(this->mainloop, 0); +} + +/** + * @brief Callback function called when PA notifies about something + * @param s Stream on which the notification happened + * @param this_gen pulse_driver_t pointer for the PulseAudio output + * instance. + */ +static void __xine_pa_stream_notify_callback(pa_stream *s, void *this_gen) +{ + pulse_driver_t * this = (pulse_driver_t*) this_gen; + + pa_threaded_mainloop_signal(this->mainloop, 0); +} + +/** + * @brief Callback function called when PA completed an operation * @param ctx Context which operation has succeeded - * @param success The success value for the operation (ignored) + * @param nbytes the number of bytes PA requested + * @param this_gen pulse_driver_t pointer for the PulseAudio output + * instance. + */ +static void __xine_pa_stream_success_callback(pa_stream *s, int success, void *this_gen) +{ + pulse_driver_t * this = (pulse_driver_t*) this_gen; + + if (!success) + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: stream operation failed: %s\n", pa_strerror(pa_context_errno(this->context))); + + pa_threaded_mainloop_signal(this->mainloop, 0); +} + +/** + * @brief Callback function called when PA completed an operation + * @param c Context on which operation has succeeded + * @param nbytes the number of bytes PA requested * @param this_gen pulse_driver_t pointer for the PulseAudio output * instance. */ -static void __xine_pa_context_success_callback(pa_context *const ctx, const int success, - void *const this_gen) +static void __xine_pa_context_success_callback(pa_context *c, int success, void *this_gen) { - pulse_driver_t *const this = (pulse_driver_t*)this_gen; + pulse_driver_t *this = (pulse_driver_t*) this_gen; - _x_assert(ctx); _x_assert(this); - _x_assert(ctx == this->pa_class->context); + if (!success) + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: context operation failed: %s\n", pa_strerror(pa_context_errno(this->context))); - pa_threaded_mainloop_signal(this->pa_class->mainloop, 0); + pa_threaded_mainloop_signal(this->mainloop, 0); } /** @@ -156,14 +202,14 @@ static void __xine_pa_context_success_callback(pa_context *const ctx, const int * This function saves the volume field of the passed structure to the * @c cvolume variable of the output instance. */ -static void __xine_pa_sink_info_callback(pa_context *const ctx, const pa_sink_input_info *const info, - const int is_last, void *const userdata) { +static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info *info, + int is_last, void *userdata) { pulse_driver_t *const this = (pulse_driver_t *) userdata; if (is_last < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to get sink input info: %s\n", - pa_strerror(pa_context_errno(this->pa_class->context))); + pa_strerror(pa_context_errno(this->context))); return; } @@ -171,36 +217,95 @@ static void __xine_pa_sink_info_callback(pa_context *const ctx, const pa_sink_in return; this->cvolume = info->volume; + this->swvolume = pa_cvolume_avg(&info->volume); +#if PA_PROTOCOL_VERSION >= 11 + /* PulseAudio 0.9.7 and newer */ + this->muted = info->mute; +#else + this->muted = pa_cvolume_is_muted (&this->cvolume); +#endif +} + +static int connect_context(pulse_driver_t *this) { + + if (this->context && (pa_context_get_state(this->context) == PA_CONTEXT_FAILED || + pa_context_get_state(this->context) == PA_CONTEXT_TERMINATED)) { + pa_context_unref(this->context); + this->context = NULL; + } + + if (!this->context) { + char fn[XINE_PATH_MAX], *p; + + if (pa_get_binary_name(fn, sizeof(fn))) + p = pa_path_get_filename(fn); + else + p = "Xine"; - pthread_mutex_unlock(&this->info_mutex); + this->context = pa_context_new(pa_threaded_mainloop_get_api(this->mainloop), p); + _x_assert(this->context); + + pa_context_set_state_callback(this->context, __xine_pa_context_state_callback, this); + } + + if (pa_context_get_state(this->context) == PA_CONTEXT_UNCONNECTED) { + + if (pa_context_connect(this->context, this->host, 0, NULL) < 0) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object %s\n", pa_strerror(pa_context_errno(this->context))); + return -1; + } + } + + for (;;) { + pa_context_state_t state = pa_context_get_state(this->context); + + if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object: %s\n", pa_strerror(pa_context_errno(this->context))); + return -1; + } + + if (state == PA_CONTEXT_READY) + break; + + pa_threaded_mainloop_wait(this->mainloop); + } + + return 0; } /* * open the audio device for writing to */ static int ao_pulse_open(ao_driver_t *this_gen, - uint32_t bits, uint32_t rate, int mode) + uint32_t bits, uint32_t rate, int mode) { pulse_driver_t *this = (pulse_driver_t *) this_gen; - struct pa_sample_spec ss; - struct pa_buffer_attr a; - pa_stream_state_t streamstate; + pa_sample_spec ss; + pa_channel_map cm; + int r; xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "audio_pulse_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); + "audio_pulse_out: ao_open bits=%d rate=%d, mode=%d\n", bits, rate, mode); if ( (mode & this->capabilities) == 0 ) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: unsupported mode %08x\n", mode); return 0; } + pa_threaded_mainloop_lock(this->mainloop); + if (this->stream) { - if ( mode == this->mode && rate == this->sample_rate && - bits == this->bits_per_sample ) + if (mode == this->mode && rate == this->sample_rate && + bits == this->bits_per_sample) { + + pa_threaded_mainloop_unlock(this->mainloop); return this->sample_rate; + } - this_gen->close(this_gen); + pa_stream_disconnect(this->stream); + pa_stream_unref(this->stream); + this->stream = NULL; } this->mode = mode; @@ -221,6 +326,8 @@ static int ao_pulse_open(ao_driver_t *this_gen, case 32: ss.format = PA_SAMPLE_FLOAT32NE; break; + default: + _x_assert(!"Should not be reached"); } if (!pa_sample_spec_valid(&ss)) { @@ -228,69 +335,86 @@ static int ao_pulse_open(ao_driver_t *this_gen, goto fail; } - if ( this->pa_class->context && pa_context_get_state(this->pa_class->context) > PA_CONTEXT_READY ) { - pa_context_unref(this->pa_class->context); - this->pa_class->context = NULL; - } - - if ( this->pa_class->context == NULL ) { - this->pa_class->context = pa_context_new(pa_threaded_mainloop_get_api(this->pa_class->mainloop), - __progname); - } - - pa_context_ref(this->pa_class->context); + cm.channels = ss.channels; - if ( pa_context_get_state(this->pa_class->context) == PA_CONTEXT_UNCONNECTED ) { - int ret; + switch (mode) { + case AO_CAP_MODE_MONO: + cm.map[0] = PA_CHANNEL_POSITION_MONO; + _x_assert(cm.channels == 1); + break; - pa_threaded_mainloop_lock(this->pa_class->mainloop); - ret = pa_context_connect(this->pa_class->context, this->host, 1, NULL); - if ( ret < 0 ) - goto fail; + case AO_CAP_MODE_STEREO: + cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + _x_assert(cm.channels == 2); + break; - pa_context_set_state_callback(this->pa_class->context, __xine_pa_context_status_callback, this); + case AO_CAP_MODE_4CHANNEL: + cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + cm.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + cm.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + _x_assert(cm.channels == 4); + break; - pa_threaded_mainloop_wait(this->pa_class->mainloop); - pa_threaded_mainloop_unlock(this->pa_class->mainloop); + case AO_CAP_MODE_4_1CHANNEL: + case AO_CAP_MODE_5CHANNEL: + case AO_CAP_MODE_5_1CHANNEL: + cm.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + cm.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + cm.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + cm.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + cm.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + cm.map[5] = PA_CHANNEL_POSITION_LFE; + cm.channels = 6; + break; + default: + _x_assert(!"Should not be reached"); } - if (pa_context_get_state(this->pa_class->context) != PA_CONTEXT_READY) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Failed to connect to server: %s\n", - pa_strerror(pa_context_errno(this->pa_class->context))); + if (!pa_channel_map_valid(&cm)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: Invalid channel map\n"); goto fail; } - this->stream = pa_stream_new(this->pa_class->context, "audio stream", &ss, NULL); + if (connect_context(this) < 0) + goto fail; + + _x_assert(!this->stream); + this->stream = pa_stream_new(this->context, "Audio Stream", &ss, &cm); _x_assert(this->stream); - a.maxlength = pa_bytes_per_second(&ss)*1; - a.tlength = a.maxlength*9/10; - a.prebuf = a.tlength/2; - a.minreq = a.tlength/10; + pa_stream_set_state_callback(this->stream, __xine_pa_stream_state_callback, this); + pa_stream_set_write_callback(this->stream, __xine_pa_stream_request_callback, this); + pa_stream_set_latency_update_callback(this->stream, __xine_pa_stream_notify_callback, this); - pa_stream_connect_playback(this->stream, this->sink, &a, - PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, + r = pa_stream_connect_playback(this->stream, this->sink, NULL, + PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL); - do { - xine_usec_sleep (100); + for (;;) { + pa_context_state_t cstate = pa_context_get_state(this->context); + pa_stream_state_t sstate = pa_stream_get_state(this->stream); - streamstate = pa_stream_get_state(this->stream); - } while (streamstate < PA_STREAM_READY); - - if (streamstate != PA_STREAM_READY) { - xprintf (this->xine, XINE_VERBOSITY_LOG, "audio_pulse_out: Failed to connect to server: %s\n", - pa_strerror(pa_context_errno(this->pa_class->context))); - goto fail; + if (cstate == PA_CONTEXT_FAILED || cstate == PA_CONTEXT_TERMINATED || + sstate == PA_STREAM_FAILED || sstate == PA_STREAM_TERMINATED) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to connect context object: %s\n", pa_strerror(pa_context_errno(this->context))); + goto fail; + } + + if (sstate == PA_STREAM_READY) + break; + + pa_threaded_mainloop_wait(this->mainloop); } - this->frames_written = 0; - this->ao_driver.set_property(this, AO_PROP_PCM_VOL, 100); + pa_threaded_mainloop_unlock(this->mainloop); return this->sample_rate; -fail: - pa_threaded_mainloop_unlock(this->pa_class->mainloop); + fail: + + pa_threaded_mainloop_unlock(this->mainloop); this_gen->close(this_gen); return 0; } @@ -318,217 +442,367 @@ static int ao_pulse_write(ao_driver_t *this_gen, int16_t *data, { pulse_driver_t *this = (pulse_driver_t *) this_gen; size_t size = num_frames * this->bytes_per_frame; - int ret = 0; - - if ( !this->stream || !this->pa_class->context) - return -1; + int ret = -1; + size_t done = 0; - switch( pa_stream_get_state(this->stream) ) { - case PA_STREAM_READY: - while (size > 0) { - size_t l; + pa_threaded_mainloop_lock(this->mainloop); - while (!(l = pa_stream_writable_size(this->stream))) { - xine_usec_sleep (10000); - } + while (size > 0) { + size_t l; - if (l > size) - l = size; - - pa_stream_write(this->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); - data = (int16_t *) ((uint8_t*) data + l); - size -= l; - } + for (;;) { + + if (!this->stream || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || + pa_stream_get_state(this->stream) != PA_STREAM_READY) + goto finish; - this->frames_written += num_frames; + if ((l = pa_stream_writable_size(this->stream)) == (size_t) -1) + goto finish; - if (pa_stream_get_state(this->stream) == PA_STREAM_READY) - ret = 1; + if (l > 0) + break; - break; + pa_threaded_mainloop_wait(this->mainloop); + } + + if (l > size) + l = size; + + pa_stream_write(this->stream, data, l, NULL, 0, PA_SEEK_RELATIVE); + data = (int16_t *) ((uint8_t*) data + l); + size -= l; + done += l; } + ret = done; + +finish: + + pa_threaded_mainloop_unlock(this->mainloop); + +/* fprintf(stderr, "write-out\n"); */ + return ret; -} +} static int ao_pulse_delay (ao_driver_t *this_gen) { pulse_driver_t *this = (pulse_driver_t *) this_gen; - pa_usec_t latency = 0; - unsigned int delay_frames; + int ret = 0; - if ( ! this->stream ) return this->frames_written; +/* fprintf(stderr, "delay-in\n"); */ - if (pa_stream_get_latency(this->stream, &latency, NULL) < 0) { - pa_context_unref(this->pa_class->context); - this->pa_class->context = NULL; + pa_threaded_mainloop_lock(this->mainloop); - pa_stream_disconnect(this->stream); - pa_stream_unref(this->stream); - this->stream = NULL; + for (;;) { + pa_usec_t latency = 0; - return 0; + if (!this->stream || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || + pa_stream_get_state(this->stream) != PA_STREAM_READY) + goto finish; + + if (pa_stream_get_latency(this->stream, &latency, NULL) >= 0) { + ret = (int) ((latency * this->sample_rate) / 1000000); + goto finish; + } + + if (pa_context_errno(this->context) != PA_ERR_NODATA) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: failed to query latency: %s\n", pa_strerror(pa_context_errno(this->context))); + goto finish; + } + + pa_threaded_mainloop_wait(this->mainloop); } - /* convert latency (us) to frame units. */ - delay_frames = (int)(latency * this->sample_rate / 1000000); +finish: + + pa_threaded_mainloop_unlock(this->mainloop); - if( delay_frames > this->frames_written ) - return this->frames_written; - else - return delay_frames; + return ret; } static void ao_pulse_close(ao_driver_t *this_gen) { pulse_driver_t *this = (pulse_driver_t *) this_gen; - - if (this->stream) { - if (pa_stream_get_state(this->stream) == PA_STREAM_READY) { - pthread_mutex_t completion_callback = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&completion_callback); - pa_stream_drain(this->stream, __xine_pa_stream_success_callback, &completion_callback); - pthread_mutex_lock(&completion_callback); - pthread_mutex_destroy(&completion_callback); - } + pa_threaded_mainloop_lock(this->mainloop); + if (this->stream) { pa_stream_disconnect(this->stream); pa_stream_unref(this->stream); this->stream = NULL; - - pa_context_unref(this->pa_class->context); } + + pa_threaded_mainloop_unlock(this->mainloop); } static uint32_t ao_pulse_get_capabilities (ao_driver_t *this_gen) { pulse_driver_t *this = (pulse_driver_t *) this_gen; + return this->capabilities; } -static void ao_pulse_exit(ao_driver_t *this_gen) -{ +static void ao_pulse_exit(ao_driver_t *this_gen) { pulse_driver_t *this = (pulse_driver_t *) this_gen; - free (this); + ao_pulse_close(this_gen); + + pa_threaded_mainloop_lock(this->mainloop); + + if (this->context) { + pa_context_disconnect(this->context); + pa_context_unref(this->context); + } + + pa_threaded_mainloop_unlock(this->mainloop); + + pa_threaded_mainloop_free(this->mainloop); + + free(this->host); + free(this->sink); + free(this); +} + +static int wait_for_operation(pulse_driver_t *this, pa_operation *o) { + + for (;;) { + + if (!this->stream || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || + pa_stream_get_state(this->stream) != PA_STREAM_READY) + return -1; + + if (pa_operation_get_state(o) != PA_OPERATION_RUNNING) + return 0; + + pa_threaded_mainloop_wait(this->mainloop); + } } static int ao_pulse_get_property (ao_driver_t *this_gen, int property) { pulse_driver_t *this = (pulse_driver_t *) this_gen; int result = 0; + pa_operation *o = NULL; - if ( ! this->stream || ! this->pa_class->context ) + pa_threaded_mainloop_lock(this->mainloop); + + if (!this->stream || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || + pa_stream_get_state(this->stream) != PA_STREAM_READY) { + pa_threaded_mainloop_unlock(this->mainloop); return 0; + } switch(property) { - case AO_PROP_PCM_VOL: - case AO_PROP_MIXER_VOL: - { - pthread_mutex_lock(&this->info_mutex); - pa_operation *o = pa_context_get_sink_input_info(this->pa_class->context, - pa_stream_get_index(this->stream), - __xine_pa_sink_info_callback, this); - if ( ! o ) return 0; - pthread_mutex_lock(&this->info_mutex); pthread_mutex_unlock(&this->info_mutex); - - result = (pa_sw_volume_to_linear(this->swvolume)*100); - } - break; - case AO_PROP_MUTE_VOL: - result = pa_cvolume_is_muted(&this->cvolume); - break; + case AO_PROP_MUTE_VOL: + case AO_PROP_PCM_VOL: + case AO_PROP_MIXER_VOL: + + o = pa_context_get_sink_input_info(this->context, pa_stream_get_index(this->stream), + __xine_pa_sink_info_callback, this); + + break; + } + + if (o) { + wait_for_operation(this, o); + pa_operation_unref(o); + } + + switch(property) { + + case AO_PROP_MUTE_VOL: + result = this->muted; + break; + + case AO_PROP_PCM_VOL: + case AO_PROP_MIXER_VOL: + result = (int) (pa_sw_volume_to_linear(this->swvolume)*100); + break; } - + + pa_threaded_mainloop_unlock(this->mainloop); + return result; } static int ao_pulse_set_property (ao_driver_t *this_gen, int property, int value) { pulse_driver_t *this = (pulse_driver_t *) this_gen; int result = ~value; + pa_operation *o = NULL; - if ( ! this->stream || ! this->pa_class->context ) - return result; + pa_threaded_mainloop_lock(this->mainloop); + + if (!this->stream || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || + pa_stream_get_state(this->stream) != PA_STREAM_READY) { + pa_threaded_mainloop_unlock(this->mainloop); + return 0; + } switch(property) { - case AO_PROP_PCM_VOL: - case AO_PROP_MIXER_VOL: - this->swvolume = pa_sw_volume_from_linear((double)value/100.0); - pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume); + case AO_PROP_PCM_VOL: + case AO_PROP_MIXER_VOL: + + this->swvolume = pa_sw_volume_from_linear((double)value/100.0); + pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume); - pa_context_set_sink_input_volume(this->pa_class->context, pa_stream_get_index(this->stream), - &this->cvolume, __xine_pa_context_success_callback, this); + o = pa_context_set_sink_input_volume(this->context, pa_stream_get_index(this->stream), + &this->cvolume, __xine_pa_context_success_callback, this); - result = value; - break; + result = value; + break; - case AO_PROP_MUTE_VOL: - if ( value ) - pa_cvolume_mute(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels); - else - pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume); + case AO_PROP_MUTE_VOL: - pa_context_set_sink_input_volume(this->pa_class->context, pa_stream_get_index(this->stream), - &this->cvolume, __xine_pa_context_success_callback, this); - - result = value; - break; + this->muted = value; + +#if PA_PROTOCOL_VERSION >= 11 + /* PulseAudio 0.9.7 and newer */ + o = pa_context_set_sink_input_mute(this->context, pa_stream_get_index(this->stream), + value, __xine_pa_context_success_callback, this); +#else + /* Get the current volume, so we can restore it properly. */ + o = pa_context_get_sink_input_info(this->context, pa_stream_get_index(this->stream), + __xine_pa_sink_info_callback, this); + + if (o) { + wait_for_operation(this, o); + pa_operation_unref(o); + } + + if ( value ) + pa_cvolume_mute(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels); + else + pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume); + + o = pa_context_set_sink_input_volume(this->context, pa_stream_get_index(this->stream), + &this->cvolume, __xine_pa_context_success_callback, this); +#endif + result = value; } - + + if (o) { + wait_for_operation(this, o); + pa_operation_unref(o); + } + + pa_threaded_mainloop_unlock(this->mainloop); + return result; } static int ao_pulse_ctrl(ao_driver_t *this_gen, int cmd, ...) { pulse_driver_t *this = (pulse_driver_t *) this_gen; + pa_operation *o = NULL; - if ( ! this->stream ) return 0; + pa_threaded_mainloop_lock(this->mainloop); + + if (!this->stream || + !this->context || + pa_context_get_state(this->context) != PA_CONTEXT_READY || + pa_stream_get_state(this->stream) != PA_STREAM_READY) { + pa_threaded_mainloop_unlock(this->mainloop); + return 0; + } switch (cmd) { - case AO_CTRL_FLUSH_BUFFERS: - _x_assert(this->stream && this->pa_class->context); + case AO_CTRL_FLUSH_BUFFERS: - if(pa_stream_get_state(this->stream) == PA_STREAM_READY) { - pthread_mutex_t completion_callback = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_lock(&completion_callback); - pa_stream_flush(this->stream, __xine_pa_stream_success_callback, &completion_callback); + o = pa_stream_flush(this->stream, __xine_pa_stream_success_callback, this); + break; - pthread_mutex_lock(&completion_callback); - pthread_mutex_destroy(&completion_callback); - } + case AO_CTRL_PLAY_RESUME: + case AO_CTRL_PLAY_PAUSE: - this->frames_written = 0; + o = pa_stream_cork(this->stream, cmd == AO_CTRL_PLAY_PAUSE, __xine_pa_stream_success_callback, this); + break; + } - break; + if (o) { + wait_for_operation(this, o); + pa_operation_unref(o); } + pa_threaded_mainloop_unlock(this->mainloop); + return 0; } static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) { pulse_class_t *class = (pulse_class_t *) class_gen; pulse_driver_t *this; - char *device; + const char* device; + int r; lprintf ("audio_pulse_out: open_plugin called\n"); - this = (pulse_driver_t *) xine_xmalloc (sizeof (pulse_driver_t)); + this = calloc(1, sizeof (pulse_driver_t)); if (!this) return NULL; + this->xine = class->xine; + this->host = NULL; + this->sink = NULL; + this->context = NULL; + this->mainloop = NULL; + + device = class->xine->config->register_string(class->xine->config, + "audio.pulseaudio_device", + "", + _("device used for pulseaudio"), + _("use 'server[:sink]' for setting the " + "pulseaudio sink device."), + 10, NULL, + NULL); + + if (device && *device) { + char *sep = strrchr(device, ':'); + if ( sep ) { + if (!(this->host = strndup(device, sep-device))) { + free(this); + return NULL; + } + + if (!(this->sink = strdup(sep+1))) { + free(this->host); + free(this); + return NULL; + } + } else { + + if (!(this->host = strdup(device))) { + free(this); + return NULL; + } + } + } + + this->mainloop = pa_threaded_mainloop_new(); + _x_assert(this->mainloop); + pa_threaded_mainloop_start(this->mainloop); /* * set capabilities */ - this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_MODE_4CHANNEL | - AO_CAP_MODE_4_1CHANNEL | AO_CAP_MODE_5CHANNEL | - AO_CAP_MODE_5_1CHANNEL | AO_CAP_MIXER_VOL | - AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS | - AO_CAP_16BITS | AO_CAP_FLOAT32; + this->capabilities = + AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_MODE_4CHANNEL | + AO_CAP_MODE_4_1CHANNEL | AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL | + AO_CAP_MIXER_VOL | AO_CAP_PCM_VOL | AO_CAP_MUTE_VOL | + AO_CAP_8BITS | AO_CAP_16BITS | AO_CAP_FLOAT32; this->sample_rate = 0; - this->host = NULL; - this->sink = NULL; - + this->ao_driver.get_capabilities = ao_pulse_get_capabilities; this->ao_driver.get_property = ao_pulse_get_property; this->ao_driver.set_property = ao_pulse_set_property; @@ -540,33 +814,22 @@ static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *da this->ao_driver.close = ao_pulse_close; this->ao_driver.exit = ao_pulse_exit; this->ao_driver.get_gap_tolerance = ao_pulse_get_gap_tolerance; - this->ao_driver.control = ao_pulse_ctrl; - - device = this->xine->config->register_string(this->xine->config, - "audio.pulseaudio_device", - "", - _("device used for pulseaudio"), - _("use 'server[:sink]' for setting the " - "pulseaudio sink device."), - 10, NULL, - NULL); - - if (device && *device) { - char *sep = strchr(device, ':'); - if ( sep ) { - this->host = strndup(device, sep-device); - this->sink = strdup(&sep[1]); - } else - this->host = strdup(device); - } - - pthread_mutex_init(&this->info_mutex, NULL); + this->ao_driver.control = ao_pulse_ctrl; xprintf (class->xine, XINE_VERBOSITY_DEBUG, "audio_pulse_out: host %s sink %s\n", this->host ? this->host : "(null)", this->sink ? this->sink : "(null)"); this->pa_class = class; + pa_threaded_mainloop_lock(this->mainloop); + r = connect_context(this); + pa_threaded_mainloop_unlock(this->mainloop); + + if (r < 0) { + ao_pulse_exit((ao_driver_t *) this); + return NULL; + } + return &this->ao_driver; } @@ -586,13 +849,7 @@ static void dispose_class (audio_driver_class_t *this_gen) { pulse_class_t *this = (pulse_class_t *) this_gen; - if ( this->context ) - pa_context_unref(this->context); - - pa_threaded_mainloop_stop(this->mainloop); - pa_threaded_mainloop_free(this->mainloop); - - free (this); + free(this); } static void *init_class (xine_t *xine, void *data) { @@ -601,29 +858,21 @@ static void *init_class (xine_t *xine, void *data) { lprintf ("audio_pulse_out: init class\n"); - this = (pulse_class_t *) xine_xmalloc (sizeof (pulse_class_t)); + this = calloc(1, sizeof (pulse_class_t)); if (!this) return NULL; + this->xine = xine; this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; this->driver_class.get_description = get_description; this->driver_class.dispose = dispose_class; - this->xine = xine; - - this->mainloop = pa_threaded_mainloop_new(); - _x_assert(this->mainloop); - - pa_threaded_mainloop_start(this->mainloop); - - this->context = NULL; - return this; } static const ao_info_t ao_info_pulse = { - 6 + 12 }; /* @@ -635,5 +884,3 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_AUDIO_OUT, 8, "pulseaudio", XINE_VERSION_CODE, &ao_info_pulse, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; - - diff --git a/src/audio_out/audio_sndio_out.c b/src/audio_out/audio_sndio_out.c new file mode 100644 index 000000000..1d789b5e8 --- /dev/null +++ b/src/audio_out/audio_sndio_out.c @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2008 Brad Smith <brad@comstyle.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* ao plugin for sndio by Brad Smith <brad@comstyle.com>. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <math.h> +#include <unistd.h> +#include <inttypes.h> +#include <pthread.h> + +#include <sndio.h> + +#include "xine_internal.h" +#include "xineutils.h" +#include "audio_out.h" +#include "bswap.h" + +#define GAP_TOLERANCE AO_MAX_GAP +#define PCT_TO_MIDI(p) (((p) * SIO_MAXVOL + 50) / 100) + +typedef struct { + audio_driver_class_t driver_class; + xine_t *xine; +} sndio_class_t; + +typedef struct sndio_driver_s { + ao_driver_t ao_driver; + xine_t *xine; + + struct sio_hdl *hdl; + long long realpos, playpos; + int capabilities; + + int num_channels; + u_int32_t bits_per_sample; + u_int32_t bytes_per_frame; + + struct { + int volume; + int mute; + } mixer; +} sndio_driver_t; + +/* + * Callback to notify of frames processed by the hw. It is + * called from the mail loop called from sio_write(). + */ +static void ao_sndio_onmove_cb(void *addr, int delta) +{ + sndio_driver_t *this = (sndio_driver_t *)addr; + + this->realpos += delta; +} + +/* + * Open the audio device for writing to. + */ +static int ao_sndio_open(ao_driver_t *this_gen, + uint32_t bits, uint32_t rate, int mode) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + struct sio_par par; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open bits=%d rate=%d, mode=%d\n", + bits, rate, mode); + + if (this->hdl != NULL) { + sio_close (this->hdl); + this->hdl = NULL; + } + + this->hdl = sio_open(NULL, SIO_PLAY, 0); + if (this->hdl == NULL) + goto bad; + + sio_initpar(&par); + + switch (mode) { + case AO_CAP_MODE_MONO: + par.pchan = 1; + break; + case AO_CAP_MODE_STEREO: + par.pchan = 2; + break; +#if 0 + case AO_CAP_MODE_4CHANNEL: + par.pchan = 4; + break; + case AO_CAP_MODE_4_1CHANNEL: + case AO_CAP_MODE_5CHANNEL: + case AO_CAP_MODE_5_1CHANNEL: + par.pchan = 6; + break; +#endif + default: + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open does not support the requested mode: 0x%X\n", + mode); + goto bad; + } + + switch (bits) { + case 8: + par.bits = 8; + par.sig = 0; + break; + case 16: + par.bits = 16; + par.sig = 1; + break; + default: + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open bits per sample not supported: %d\n", bits); + goto bad; + } + + par.rate = rate; + par.appbufsz = par.rate * 250 / 1000; /* 250ms buffer */ + + if (!sio_setpar(this->hdl, &par)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not set params\n"); + goto bad; + } + + if (!sio_getpar(this->hdl, &par)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not get params\n"); + goto bad; + } + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open %d channels output\n", + par.pchan); + + this->num_channels = par.pchan; + this->bytes_per_frame = par.bps * par.pchan; + this->playpos = 0; + this->realpos = 0; + sio_onmove(this->hdl, ao_sndio_onmove_cb, this); + + if (!sio_start(this->hdl)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not start\n"); + goto bad; + } + + return par.rate; + +bad: + if (this->hdl != NULL) + sio_close(this->hdl); + return 0; +} + +static int ao_sndio_num_channels(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->num_channels; +} + +static int ao_sndio_bytes_per_frame(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->bytes_per_frame; +} + +static int ao_sndio_get_gap_tolerance (ao_driver_t *this_gen) +{ + return GAP_TOLERANCE; +} + +static int ao_sndio_write(ao_driver_t *this_gen, int16_t *data, + uint32_t num_frames) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + size_t ret, size = num_frames * this->bytes_per_frame; + + ret = sio_write(this->hdl, data, size); + if (ret == 0) + return 0; + + this->playpos += num_frames; + + return 1; +} + +static int ao_sndio_delay (ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + int bufused; + + if (this->realpos < 0) + bufused = this->playpos; + else + bufused = this->playpos - this->realpos; + + return bufused; +} + +static void ao_sndio_close(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_close called\n"); + + if (!sio_stop(this->hdl)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_close could not stop\n"); + } + + sio_close(this->hdl); + this->hdl = NULL; +} + +static uint32_t ao_sndio_get_capabilities (ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->capabilities; +} + +static void ao_sndio_exit(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_exit called\n"); + + if (this->hdl != NULL) + sio_close(this->hdl); +} + +static int ao_sndio_get_property (ao_driver_t *this_gen, int property) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + switch (property) { + case AO_PROP_MIXER_VOL: + return this->mixer.volume; + break; + case AO_PROP_MUTE_VOL: + return this->mixer.mute; + break; + } + + return 0; +} + +static int ao_sndio_set_property (ao_driver_t *this_gen, int property, int value) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + int vol; + + if (this->hdl == NULL) + return 0; + + switch(property) { + case AO_PROP_MIXER_VOL: + this->mixer.volume = value; + if (!this->mixer.mute) + sio_setvol(this->hdl, PCT_TO_MIDI(this->mixer.volume)); + return this->mixer.volume; + break; + + case AO_PROP_MUTE_VOL: + this->mixer.mute = (value) ? 1 : 0; + vol = 0; + if (!this->mixer.mute) + vol = PCT_TO_MIDI(this->mixer.volume); + sio_setvol(this->hdl, vol); + return value; + break; + } + + return value; +} + +/* + * pause, resume, flush buffers + */ +static int ao_sndio_ctrl(ao_driver_t *this_gen, int cmd, ...) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + /* + * sndio pauses automatically if there are no more samples to play + * and resumes when there are samples again. So we leave this empty + * for the moment. + */ + + return 0; +} + +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) +{ + sndio_class_t *class = (sndio_class_t *) class_gen; + sndio_driver_t *this; + + lprintf ("audio_sndio_out: open_plugin called\n"); + + this = calloc(1, sizeof (sndio_driver_t)); + if (!this) + return NULL; + + this->xine = class->xine; + + /* + * Set capabilities + */ + this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | +#if 0 + AO_CAP_MODE_4CHANNEL | AO_CAP_MODE_4_1CHANNEL | + AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL | +#endif + AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS | + AO_CAP_16BITS; + + this->ao_driver.get_capabilities = ao_sndio_get_capabilities; + this->ao_driver.get_property = ao_sndio_get_property; + this->ao_driver.set_property = ao_sndio_set_property; + this->ao_driver.open = ao_sndio_open; + this->ao_driver.num_channels = ao_sndio_num_channels; + this->ao_driver.bytes_per_frame = ao_sndio_bytes_per_frame; + this->ao_driver.delay = ao_sndio_delay; + this->ao_driver.write = ao_sndio_write; + this->ao_driver.close = ao_sndio_close; + this->ao_driver.exit = ao_sndio_exit; + this->ao_driver.get_gap_tolerance = ao_sndio_get_gap_tolerance; + this->ao_driver.control = ao_sndio_ctrl; + + return &this->ao_driver; +} + +/* + * class functions + */ + +static char* get_identifier (audio_driver_class_t *this_gen) +{ + return "sndio"; +} + +static char* get_description (audio_driver_class_t *this_gen) +{ + return _("xine audio output plugin using sndio audio devices/drivers "); +} + +static void dispose_class (audio_driver_class_t *this_gen) +{ + sndio_class_t *this = (sndio_class_t *) this_gen; + + free(this); +} + +static void *init_class (xine_t *xine, void *data) +{ + sndio_class_t *this; + + lprintf ("audio_sndio_out: init class\n"); + + this = calloc(1, sizeof (sndio_class_t)); + if (!this) + return NULL; + + this->driver_class.open_plugin = open_plugin; + this->driver_class.get_identifier = get_identifier; + this->driver_class.get_description = get_description; + this->driver_class.dispose = dispose_class; + + this->xine = xine; + + return this; +} + +static const ao_info_t ao_info_sndio = { + 12 +}; + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_AUDIO_OUT, 8, "sndio", XINE_VERSION_CODE, &ao_info_sndio, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/audio_out/audio_sun_out.c b/src/audio_out/audio_sun_out.c index b23955b77..2a154c09d 100644 --- a/src/audio_out/audio_sun_out.c +++ b/src/audio_out/audio_sun_out.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2001-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -159,7 +159,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev) silence = calloc(1, len); if (silence == NULL) goto error; - + if ((fd = open(dev, O_WRONLY|O_NONBLOCK)) < 0) goto error; @@ -176,7 +176,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev) xprintf(xine, XINE_VERBOSITY_DEBUG, "rtsc: SETINFO failed\n"); goto error; } - + if (write(fd, silence, len) != len) { xprintf(xine, XINE_VERBOSITY_DEBUG, "rtsc: write failed\n"); goto error; @@ -195,7 +195,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev) delay.tv_sec = 0; delay.tv_nsec = 10000000; nanosleep(&delay, NULL); - + gettimeofday(&end, NULL); usec_delay = (end.tv_sec - start.tv_sec) * 1000000 + end.tv_usec - start.tv_usec; @@ -230,7 +230,7 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev) * sample counter increment from the soundcard driver of less than * 2000 samples, we assume that the driver provides a useable realtime * sample counter in the AUDIO_INFO play.samples field. Timing based - * on sample counts should be much more accurate than counting whole + * on sample counts should be much more accurate than counting whole * 16kbyte chunks. */ if (min_increment < 2000) @@ -238,10 +238,10 @@ static int realtime_samplecounter_available(xine_t *xine, char *dev) /* printf("audio_sun_out: minimum sample counter increment per 10msec interval: %d\n" - "\t%susing sample counter based timing code\n", + "\t%susing sample counter based timing code\n", min_increment, rtsc_ok == RTSC_ENABLED ? "" : "not "); */ - + error: if (silence != NULL) free(silence); @@ -263,7 +263,7 @@ error: } -/* +/* * match the requested sample rate |sample_rate| against the * sample rates supported by the audio device |dev|. Return * a supported sample rate, it that sample rate is close to @@ -294,7 +294,7 @@ find_close_samplerate_match(int dev, int sample_rate) if (sr->flags & MIXER_SR_LIMITS) { /* - * HW can playback any rate between + * HW can playback any rate between * sr->samp_rates[0] .. sr->samp_rates[1] */ free(sr); @@ -340,7 +340,7 @@ find_close_samplerate_match(int dev, int sample_rate) for (i = 0; audiocs_rates[i]; i++) { err = abs(audiocs_rates[i] - sample_rate); if (err == 0) { - /* + /* * exact supported sample rate match, no need to * retry something elise */ @@ -385,7 +385,7 @@ find_highest_samplerate(int dev) if (sr->flags & MIXER_SR_LIMITS) { /* - * HW can playback any rate between + * HW can playback any rate between * sr->samp_rates[0] .. sr->samp_rates[1] */ max_rate = sr->samp_rates[1]; @@ -412,7 +412,7 @@ find_highest_samplerate(int dev) * Implicit assumptions about audio format (bits/rate/mode): * * bits == 16: We always get 16-bit samples in native endian format, - * using signed linear encoding + * using signed linear encoding * * bits == 8: 8-bit samples use unsigned linear encoding, * other 8-bit formats (uLaw, aLaw, etc) are currently not supported @@ -440,7 +440,7 @@ static int ao_sun_open(ao_driver_t *this_gen, close (this->audio_fd); } - + this->mode = mode; this->input_sample_rate = rate; #ifdef __svr4__ @@ -453,11 +453,11 @@ static int ao_sun_open(ao_driver_t *this_gen, this->audio_fd = open(this->audio_dev, O_WRONLY|O_NONBLOCK); if(this->audio_fd < 0) { - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("audio_sun_out: opening audio device %s failed: %s\n"), this->audio_dev, strerror(errno)); return 0; } - + /* We wanted non blocking open but now put it back to normal */ fcntl(this->audio_fd, F_SETFL, fcntl(this->audio_fd, F_GETFL) & ~O_NONBLOCK); @@ -485,7 +485,7 @@ static int ao_sun_open(ao_driver_t *this_gen, if (pass & 1) { /* - * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is + * on some sun audio drivers, 8-bit unsigned LINEAR8 encoding is * not supported, but 8-bit signed encoding is. * * Try S8, and if it works, use our own U8->S8 conversion before @@ -511,7 +511,7 @@ static int ao_sun_open(ao_driver_t *this_gen, */ if (!(info.play.sample_rate = find_close_samplerate_match(this->audio_fd, - this->input_sample_rate))) + this->input_sample_rate))) continue; } @@ -567,7 +567,7 @@ static int ao_sun_open(ao_driver_t *this_gen, return this->output_sample_rate; } -static int ao_sun_num_channels(ao_driver_t *this_gen) +static int ao_sun_num_channels(ao_driver_t *this_gen) { sun_driver_t *this = (sun_driver_t *) this_gen; return this->num_channels; @@ -589,7 +589,7 @@ static int ao_sun_delay(ao_driver_t *this_gen) (this->frames_in_buffer == 0 || info.play.samples > 0)) { if (info.play.samples < this->last_samplecnt) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio_sun_out: broken sound driver, sample counter runs backwards, cur %u < prev %u\n", info.play.samples, this->last_samplecnt); } @@ -728,7 +728,7 @@ static int ao_sun_write(ao_driver_t *this_gen, int num_written; if (this->convert_u8_s8) { - /* + /* * Audio hardware does not support 8-bit unsigned format, * only 8-bit signed. Convert to 8-bit unsigned before sending * the data to the audio device. @@ -736,7 +736,7 @@ static int ao_sun_write(ao_driver_t *this_gen, uint8_t *p = (void *)frame_buffer; int i; - for (i = num_frames * this->bytes_per_frame; --i >= 0; p++) + for (i = num_frames * this->bytes_per_frame; --i >= 0; p++) *p ^= 0x80; } num_written = sun_audio_write(this, frame_buffer, num_frames * this->bytes_per_frame); @@ -747,7 +747,7 @@ static int ao_sun_write(ao_driver_t *this_gen, this->frames_in_buffer += num_written / this->bytes_per_frame; #endif - /* + /* * Avoid storing too much data in the sound driver's buffers. * * When we find more than 3 seconds of buffered audio data in the @@ -783,7 +783,7 @@ static uint32_t ao_sun_get_capabilities (ao_driver_t *this_gen) { static void ao_sun_exit(ao_driver_t *this_gen) { sun_driver_t *this = (sun_driver_t *) this_gen; - + if (this->audio_fd >= 0) close(this->audio_fd); @@ -869,7 +869,7 @@ static int ao_sun_ctrl(ao_driver_t *this_gen, int cmd, ...) { /* flush buffered STEAMS data first */ ioctl(this->audio_fd, I_FLUSH, FLUSHW); - /* + /* * the flush above discarded an unknown amount of data from the * audio device. To get the "*_delay" computation in sync again, * reset the audio device's sample counter to 0, after waiting @@ -909,7 +909,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v int status; audio_info_t info; - this = (sun_driver_t *) xine_xmalloc (sizeof (sun_driver_t)); + this = calloc(1, sizeof (sun_driver_t)); if (!this) return NULL; @@ -944,7 +944,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v this->audio_fd = open(this->audio_dev = devname, O_WRONLY|O_NONBLOCK); - if(this->audio_fd < 0) + if(this->audio_fd < 0) { xprintf(this->xine, XINE_VERBOSITY_LOG, _("audio_sun_out: opening audio device %s failed: %s\n"), devname, strerror(errno)); @@ -962,7 +962,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v info.play.precision = AUDIO_PRECISION_16; info.play.sample_rate = 44100; status = ioctl(this->audio_fd, AUDIO_SETINFO, &info); - + if (status < 0) { xprintf(this->xine, XINE_VERBOSITY_LOG, _("audio_sun_out: audio ioctl on device %s failed: %s\n"), devname, strerror(errno)); @@ -976,7 +976,7 @@ static ao_driver_t *ao_sun_open_plugin (audio_driver_class_t *class_gen, const v */ this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | AO_CAP_8BITS - | AO_CAP_16BITS | AO_CAP_PCM_VOL; + | AO_CAP_16BITS | AO_CAP_PCM_VOL; #ifdef __svr4__ this->capabilities |= AO_CAP_MUTE_VOL; #endif @@ -1032,7 +1032,7 @@ static void ao_sun_dispose_class (audio_driver_class_t *this_gen) { static void *ao_sun_init_class (xine_t *xine, void *data) { sun_class_t *this; - this = (sun_class_t *) xine_xmalloc (sizeof (sun_class_t)); + this = calloc(1, sizeof (sun_class_t)); if (!this) return NULL; @@ -1056,7 +1056,7 @@ static const ao_info_t ao_info_sun = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_OUT, AO_SUN_IFACE_VERSION, "sun", XINE_VERSION_CODE, &ao_info_sun, ao_sun_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/combined/Makefile.am b/src/combined/Makefile.am index 884fcf0cc..6a43fed47 100644 --- a/src/combined/Makefile.am +++ b/src/combined/Makefile.am @@ -1,5 +1,8 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common +SUBDIRS = ffmpeg + if HAVE_WAVPACK xineplug_wavpack = xineplug_wavpack.la endif diff --git a/src/combined/combined_wavpack.c b/src/combined/combined_wavpack.c index 893ee99be..5e4f47342 100644 --- a/src/combined/combined_wavpack.c +++ b/src/combined/combined_wavpack.c @@ -27,13 +27,13 @@ static const demuxer_info_t demux_info_wv = { 0 /* priority */ }; -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_WAVPACK, 0 }; static const decoder_info_t decoder_info_wv = { audio_types, /* supported types */ - 7 /* priority */ + 8 /* priority */ }; const plugin_info_t xine_plugin_info[] EXPORTED = { diff --git a/src/combined/combined_wavpack.h b/src/combined/combined_wavpack.h index 61a504a4f..3cfa78509 100644 --- a/src/combined/combined_wavpack.h +++ b/src/combined/combined_wavpack.h @@ -21,6 +21,7 @@ */ #include "os_types.h" +#include "attributes.h" typedef struct { uint32_t idcode; /* This should always be the string "wvpk" */ @@ -35,7 +36,7 @@ typedef struct { uint32_t samples_count; /* Count of samples in the current frame */ uint32_t flags; /* Misc flags */ uint32_t decoded_crc32; /* CRC32 of the decoded data */ -} __attribute__((packed)) wvheader_t; +} XINE_PACKED wvheader_t; #ifdef WORDS_BIGENDIAN static const uint32_t wvpk_signature = ('k' + ('p' << 8) + ('v' << 16) + ('w' << 24)); diff --git a/src/combined/decoder_flac.c b/src/combined/decoder_flac.c index 2230056cd..b774e0b90 100644 --- a/src/combined/decoder_flac.c +++ b/src/combined/decoder_flac.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -82,8 +82,8 @@ typedef struct flac_decoder_s { * FLAC callback functions */ -static FLAC__StreamDecoderReadStatus -flac_read_callback (const FLAC__StreamDecoder *decoder, +static FLAC__StreamDecoderReadStatus +flac_read_callback (const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data) @@ -131,50 +131,51 @@ flac_write_callback (const FLAC__StreamDecoder *decoder, lprintf("flac_write_callback\n"); while( samples_left ) { - + audio_buffer = this->stream->audio_out->get_buffer(this->stream->audio_out); if( audio_buffer->mem_size < samples_left * frame->header.channels * bytes_per_sample ) buf_samples = audio_buffer->mem_size / (frame->header.channels * bytes_per_sample); else buf_samples = samples_left; - - + + if( frame->header.bits_per_sample == 8 ) { data8 = (int8_t *)audio_buffer->mem; - + for( j=0; j < buf_samples; j++ ) for( i=0; i < frame->header.channels; i++ ) *data8++ = buffer[i][j]; - + } else { - + data16 = (int16_t *)audio_buffer->mem; - + for( j=0; j < buf_samples; j++ ) for( i=0; i < frame->header.channels; i++ ) *data16++ = buffer[i][j]; - } + } audio_buffer->num_frames = buf_samples; audio_buffer->vpts = this->pts; this->pts = 0; this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - + samples_left -= buf_samples; } return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; } +#ifdef LEGACY_FLAC static void flac_metadata_callback (const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) { /* flac_decoder_t *this = (flac_decoder_t *)client_data; */ - + lprintf("Metadata callback called!\n"); - + #ifdef LOG if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO) { printf("libflac: min_blocksize = %d\n", metadata->data.stream_info.min_blocksize); @@ -188,6 +189,7 @@ flac_metadata_callback (const FLAC__StreamDecoder *decoder, return; } +#endif static void flac_error_callback (const FLAC__StreamDecoder *decoder, @@ -207,7 +209,7 @@ flac_error_callback (const FLAC__StreamDecoder *decoder, else printf("libflac: unknown error.\n"); #endif - + return; } @@ -216,34 +218,34 @@ flac_error_callback (const FLAC__StreamDecoder *decoder, * FLAC plugin decoder */ -static void +static void flac_reset (audio_decoder_t *this_gen) { flac_decoder_t *this = (flac_decoder_t *) this_gen; this->buf_pos = 0; - - if( FLAC__stream_decoder_get_state(this->flac_decoder) != - FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ) + + if( FLAC__stream_decoder_get_state(this->flac_decoder) != + FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ) FLAC__stream_decoder_flush (this->flac_decoder); } -static void -flac_discontinuity (audio_decoder_t *this_gen) +static void +flac_discontinuity (audio_decoder_t *this_gen) { flac_decoder_t *this = (flac_decoder_t *) this_gen; this->pts = 0; - + lprintf("Discontinuity!\n"); } -static void +static void flac_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { flac_decoder_t *this = (flac_decoder_t *) this_gen; int ret = 1; - + /* We are getting the stream header, open up the audio * device, and collect information about the stream */ @@ -286,15 +288,15 @@ flac_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) xine_fast_memcpy (&this->buf[this->buf_pos], buf->content, buf->size); this->buf_pos += buf->size; - + if (buf->pts) this->pts = buf->pts; /* We have enough to decode a frame */ while( ret && this->buf_pos > this->min_size ) { - + FLAC__StreamDecoderState state = FLAC__stream_decoder_get_state(this->flac_decoder); - + if( state == FLAC__STREAM_DECODER_SEARCH_FOR_METADATA ) { lprintf("process_until_end_of_metadata\n"); ret = FLAC__stream_decoder_process_until_end_of_metadata (this->flac_decoder); @@ -310,24 +312,24 @@ flac_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) } } else return; - + } static void flac_dispose (audio_decoder_t *this_gen) { - flac_decoder_t *this = (flac_decoder_t *) this_gen; + flac_decoder_t *this = (flac_decoder_t *) this_gen; FLAC__stream_decoder_finish (this->flac_decoder); FLAC__stream_decoder_delete (this->flac_decoder); - if (this->output_open) + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); if (this->buf) free(this->buf); - + free (this_gen); } @@ -335,7 +337,7 @@ static audio_decoder_t * open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { flac_decoder_t *this ; - this = (flac_decoder_t *) xine_xmalloc (sizeof (flac_decoder_t)); + this = calloc(1, sizeof (flac_decoder_t)); this->audio_decoder.decode_data = flac_decode_data; this->audio_decoder.reset = flac_reset; @@ -406,8 +408,8 @@ static void dispose_class (audio_decoder_class_t *this) { static void * init_plugin (xine_t *xine, void *data) { flac_class_t *this; - - this = (flac_class_t *) xine_xmalloc (sizeof (flac_class_t)); + + this = calloc(1, sizeof (flac_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -418,17 +420,17 @@ init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_FLAC, 0 }; static const decoder_info_t dec_info_audio = { audio_types, /* supported types */ - 5 /* priority */ + 8 /* priority */ }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "flac", XINE_VERSION_CODE, NULL, demux_flac_init_class }, { PLUGIN_AUDIO_DECODER, 15, "flacdec", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/combined/decoder_wavpack.c b/src/combined/decoder_wavpack.c index f8a301c9f..7b00ec8f3 100644 --- a/src/combined/decoder_wavpack.c +++ b/src/combined/decoder_wavpack.c @@ -138,7 +138,7 @@ static void wavpack_reset (audio_decoder_t *const this_gen) this->buf_pos = 0; } -static void wavpack_discontinuity (audio_decoder_t *const this_gen) +static void wavpack_discontinuity (audio_decoder_t *const this_gen) { /* wavpack_decoder_t *this = (wavpack_decoder_t *) this_gen; */ @@ -148,7 +148,7 @@ static void wavpack_discontinuity (audio_decoder_t *const this_gen) static void wavpack_decode_data (audio_decoder_t *const this_gen, buf_element_t *const buf) { wavpack_decoder_t *const this = (wavpack_decoder_t *) this_gen; - + /* We are getting the stream header, open up the audio * device, and collect information about the stream */ @@ -192,7 +192,7 @@ static void wavpack_decode_data (audio_decoder_t *const this_gen, buf_element_t xine_fast_memcpy (&this->buf[this->buf_pos], buf->content, buf->size); this->buf_pos += buf->size; - + if ( buf->decoder_flags & BUF_FLAG_FRAME_END ) { static WavpackStreamReader wavpack_buffer_reader = { .read_bytes = xine_buffer_read_bytes, @@ -214,7 +214,7 @@ static void wavpack_decode_data (audio_decoder_t *const this_gen, buf_element_t this->buf_pos = 0; if ( le2me_32(header->samples_count) == 0 ) return; - + ctx = WavpackOpenFileInputEx(&wavpack_buffer_reader, this, NULL, error, OPEN_STREAMING, 0); if ( ! ctx ) { lprintf("unable to open the stream: %s\n", error); @@ -248,14 +248,14 @@ static void wavpack_decode_data (audio_decoder_t *const this_gen, buf_element_t } lprintf("Decoded %d samples\n", buf_samples); - + samples_left -= decoded_count; audio_buffer->num_frames = decoded_count; audio_buffer->vpts = 0; /* TODO: Fix the pts calculation */ // audio_buffer->vpts = (buf->pts * (samples_total-samples_left)) / samples_total; lprintf("Audio buffer with pts %"PRId64"\n", audio_buffer->vpts); - + switch(this->bits_per_sample) { case 8: { int8_t *data8 = (int8_t*)audio_buffer->mem; @@ -280,18 +280,18 @@ static void wavpack_decode_data (audio_decoder_t *const this_gen, buf_element_t } static void wavpack_dispose (audio_decoder_t *this_gen) { - wavpack_decoder_t *this = (wavpack_decoder_t *) this_gen; + wavpack_decoder_t *this = (wavpack_decoder_t *) this_gen; if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); free(this->buf); - + free (this_gen); } static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { - wavpack_decoder_t * const this = (wavpack_decoder_t *) xine_xmalloc (sizeof (wavpack_decoder_t)); + wavpack_decoder_t * const this = calloc(1, sizeof (wavpack_decoder_t)); this->audio_decoder.decode_data = wavpack_decode_data; this->audio_decoder.reset = wavpack_reset; @@ -323,8 +323,8 @@ static void dispose_class (audio_decoder_class_t *this) { void *decoder_wavpack_init_plugin (xine_t *xine, void *data) { wavpack_class_t *this; - - this = (wavpack_class_t *) xine_xmalloc (sizeof (wavpack_class_t)); + + this = calloc(1, sizeof (wavpack_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; diff --git a/src/combined/demux_flac.c b/src/combined/demux_flac.c index 85f98e876..9c5f7de32 100644 --- a/src/combined/demux_flac.c +++ b/src/combined/demux_flac.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -66,7 +66,7 @@ typedef struct demux_flac_s { demux_plugin_t demux_plugin; xine_stream_t *stream; - + fifo_buffer_t *audio_fifo; fifo_buffer_t *video_fifo; @@ -112,15 +112,15 @@ flac_read_callback (const FLAC__SeekableStreamDecoder *decoder, void *client_data) { demux_flac_t *this = (demux_flac_t *)client_data; - input_plugin_t *input = this->input; + input_plugin_t *input = this->input; off_t offset = *bytes; lprintf("flac_read_callback\n"); - + /* This should only be called when flac is reading the metadata * of the flac stream. */ - + offset = input->read (input, buffer, offset); lprintf("Read %lld / %u bytes into buffer\n", offset, *bytes); @@ -130,7 +130,7 @@ flac_read_callback (const FLAC__SeekableStreamDecoder *decoder, { *bytes = offset; lprintf("Marking EOF\n"); - + this->status = DEMUX_FINISHED; #ifdef LEGACY_FLAC return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_ERROR; @@ -142,7 +142,7 @@ flac_read_callback (const FLAC__SeekableStreamDecoder *decoder, { *bytes = offset; lprintf("Read was perfect\n"); - + #ifdef LEGACY_FLAC return FLAC__SEEKABLE_STREAM_DECODER_READ_STATUS_OK; #else @@ -233,7 +233,7 @@ flac_length_callback (const FLAC__SeekableStreamDecoder *decoder, #endif } -static FLAC__bool +static FLAC__bool flac_eof_callback (const FLAC__SeekableStreamDecoder *decoder, void *client_data) { @@ -255,28 +255,28 @@ flac_eof_callback (const FLAC__SeekableStreamDecoder *decoder, } } -static FLAC__StreamDecoderWriteStatus -flac_write_callback (const FLAC__SeekableStreamDecoder *decoder, +static FLAC__StreamDecoderWriteStatus +flac_write_callback (const FLAC__SeekableStreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], - void *client_data) + void *client_data) { /* This should never be called, all we use flac for in this demuxer * is seeking. We do the decoding in the decoder */ - + lprintf("Error: Write callback was called!\n"); return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; } -static void -flac_metadata_callback (const FLAC__SeekableStreamDecoder *decoder, - const FLAC__StreamMetadata *metadata, +static void +flac_metadata_callback (const FLAC__SeekableStreamDecoder *decoder, + const FLAC__StreamMetadata *metadata, void *client_data) { demux_flac_t *this = (demux_flac_t *)client_data; - + lprintf("IN: Metadata callback\n"); /* This should be called when we first look at a flac stream, @@ -295,8 +295,8 @@ flac_metadata_callback (const FLAC__SeekableStreamDecoder *decoder, return; } -static void -flac_error_callback (const FLAC__SeekableStreamDecoder *decoder, +static void +flac_error_callback (const FLAC__SeekableStreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) { @@ -308,24 +308,24 @@ flac_error_callback (const FLAC__SeekableStreamDecoder *decoder, xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_flac: flac_error_callback\n"); if (status == FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_flac: Decoder lost synchronization.\n"); else if (status == FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER) xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_flac: Decoder encounted a corrupted frame header.\n"); else if (status == FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_flac: Frame's data did not match the CRC in the footer.\n"); else xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_flac: unknown error.\n"); - + this->status = DEMUX_FINISHED; - + return; } /* FLAC Demuxer plugin */ -static int +static int demux_flac_send_chunk (demux_plugin_t *this_gen) { demux_flac_t *this = (demux_flac_t *) this_gen; buf_element_t *buf = NULL; @@ -335,7 +335,7 @@ demux_flac_send_chunk (demux_plugin_t *this_gen) { remaining_sample_bytes = 2048; - current_file_pos = this->input->get_current_pos (this->input) + current_file_pos = this->input->get_current_pos (this->input) - this->data_start; if( (this->data_size - this->data_start) > 0 ) file_size = (this->data_size - this->data_start); @@ -400,7 +400,7 @@ demux_flac_send_chunk (demux_plugin_t *this_gen) { return this->status; } -static void +static void demux_flac_send_headers (demux_plugin_t *this_gen) { demux_flac_t *this = (demux_flac_t *) this_gen; @@ -434,7 +434,7 @@ demux_flac_send_headers (demux_plugin_t *this_gen) { } } -static void +static void demux_flac_dispose (demux_plugin_t *this_gen) { demux_flac_t *this = (demux_flac_t *) this_gen; @@ -451,7 +451,7 @@ demux_flac_dispose (demux_plugin_t *this_gen) { return; } -static int +static int demux_flac_get_status (demux_plugin_t *this_gen) { demux_flac_t *this = (demux_flac_t *) this_gen; @@ -461,7 +461,7 @@ demux_flac_get_status (demux_plugin_t *this_gen) { } -static int +static int demux_flac_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing) { demux_flac_t *this = (demux_flac_t *) this_gen; @@ -479,15 +479,15 @@ demux_flac_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time, int } start_pos = (uint64_t)(distance * (this->data_size - this->data_start)); } - + if (start_pos || !start_time) { - + start_pos += this->data_start; this->input->seek (this->input, start_pos, SEEK_SET); lprintf ("Seek to position: %lld\n", start_pos); - + } else { - + double distance = (double)start_time; uint64_t target_sample; FLAC__bool s = false; @@ -518,9 +518,9 @@ demux_flac_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time, int return this->status; } -static int +static int demux_flac_get_stream_length (demux_plugin_t *this_gen) { - demux_flac_t *this = (demux_flac_t *) this_gen; + demux_flac_t *this = (demux_flac_t *) this_gen; lprintf("demux_flac_get_stream_length\n"); @@ -530,14 +530,14 @@ demux_flac_get_stream_length (demux_plugin_t *this_gen) { return 0; } -static uint32_t +static uint32_t demux_flac_get_capabilities (demux_plugin_t *this_gen) { lprintf("demux_flac_get_capabilities\n"); return DEMUX_CAP_NOCAP; } -static int +static int demux_flac_get_optional_data (demux_plugin_t *this_gen, void *data, int dtype) { lprintf("demux_flac_get_optional_data\n"); @@ -545,8 +545,8 @@ demux_flac_get_optional_data (demux_plugin_t *this_gen, void *data, int dtype) { } static demux_plugin_t * -open_plugin (demux_class_t *class_gen, - xine_stream_t *stream, +open_plugin (demux_class_t *class_gen, + xine_stream_t *stream, input_plugin_t *input) { demux_flac_t *this; @@ -558,22 +558,22 @@ open_plugin (demux_class_t *class_gen, uint8_t buf[MAX_PREVIEW_SIZE]; int len; - /* + /* * try to get a preview of the data */ len = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW); if (len == INPUT_OPTIONAL_UNSUPPORTED) { - + if (input->get_capabilities (input) & INPUT_CAP_SEEKABLE) { - + input->seek (input, 0, SEEK_SET); if ( (len=input->read (input, buf, 1024)) <= 0) return NULL; input->seek (input, 0, SEEK_SET); - + } else return NULL; - } + } /* FIXME: Skip id3v2 tag */ /* Look for fLaC tag at the beginning of file */ @@ -583,10 +583,10 @@ open_plugin (demux_class_t *class_gen, } break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; - + const char *ending, *mrl; + mrl = input->get_mrl (input); - + ending = strrchr (mrl, '.'); if (!ending || (strlen (ending) < 5)) @@ -607,7 +607,7 @@ open_plugin (demux_class_t *class_gen, * if we reach this point, the input has been accepted. */ - this = xine_xmalloc (sizeof (demux_flac_t)); + this = calloc(1, sizeof (demux_flac_t)); this->stream = stream; this->input = input; @@ -622,7 +622,7 @@ open_plugin (demux_class_t *class_gen, this->demux_plugin.demux_class = class_gen; this->seek_flag = 0; - + /* Get a new FLAC decoder and hook up callbacks */ #ifdef LEGACY_FLAC @@ -715,27 +715,28 @@ open_plugin (demux_class_t *class_gen, /* FLAC Demuxer class */ -static char * +static const char * get_description (demux_class_t *this_gen) { return "FLAC demux plugin"; } - -static char * + +static const char * get_identifier (demux_class_t *this_gen) { return "FLAC"; } -static char * +static const char * get_extensions (demux_class_t *this_gen) { return "flac"; } -static char * +static const char * get_mimetypes (demux_class_t *this_gen) { - return "application/x-flac: flac: FLAC Audio;"; + return "audio/x-flac: flac: FLAC Audio;" + "audio/flac: flac: FLAC Audio;"; } -static void +static void class_dispose (demux_class_t *this_gen) { demux_flac_class_t *this = (demux_flac_class_t *) this_gen; @@ -748,10 +749,10 @@ void * demux_flac_init_class (xine_t *xine, void *data) { demux_flac_class_t *this; - + lprintf("demux_flac_init_class\n"); - this = xine_xmalloc (sizeof (demux_flac_class_t)); + this = calloc(1, sizeof (demux_flac_class_t)); this->config = xine->config; this->xine = xine; diff --git a/src/combined/demux_flac.h b/src/combined/demux_flac.h index a48c73260..d9e09e34a 100644 --- a/src/combined/demux_flac.h +++ b/src/combined/demux_flac.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/combined/demux_wavpack.c b/src/combined/demux_wavpack.c index e8081bca9..94a23acdc 100644 --- a/src/combined/demux_wavpack.c +++ b/src/combined/demux_wavpack.c @@ -39,7 +39,7 @@ typedef struct { demux_plugin_t demux_plugin; - + xine_stream_t *stream; fifo_buffer_t *audio_fifo; input_plugin_t *input; @@ -188,7 +188,7 @@ static int demux_wv_send_chunk(demux_plugin_t *const this_gen) { this->status = DEMUX_FINISHED; return this->status; } - + lprintf("current sample: %u\n", this->current_sample); do { @@ -229,7 +229,7 @@ static int demux_wv_send_chunk(demux_plugin_t *const this_gen) { input_time_guess *= buf->extra_info->input_normpos; input_time_guess /= 65535; buf->extra_info->input_time = input_time_guess; - + if ( ! header_sent ) offset = sizeof(wvheader_t); @@ -247,7 +247,7 @@ static int demux_wv_send_chunk(demux_plugin_t *const this_gen) { if ( bytes_to_read <= 0 && (le2me_32(header.flags) & FINAL_BLOCK) == FINAL_BLOCK) buf->decoder_flags |= BUF_FLAG_FRAME_END; - + this->audio_fifo->put(this->audio_fifo, buf); } } while ( (le2me_32(header.flags) & FINAL_BLOCK) != FINAL_BLOCK ); @@ -271,7 +271,7 @@ static void demux_wv_send_headers(demux_plugin_t *const this_gen) { /* Send header to decoder */ if (this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - + buf->type = BUF_AUDIO_WAVPACK; buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; buf->decoder_info[0] = this->input->get_length(this->input); @@ -332,7 +332,7 @@ static int demux_wv_get_optional_data(demux_plugin_t *const this_gen, static demux_plugin_t *open_plugin (demux_class_t *const class_gen, xine_stream_t *const stream, input_plugin_t *const input) { - demux_wv_t *const this = xine_xmalloc (sizeof (demux_wv_t)); + demux_wv_t *const this = calloc(1, sizeof (demux_wv_t)); this->stream = stream; this->input = input; @@ -362,12 +362,12 @@ static demux_plugin_t *open_plugin (demux_class_t *const class_gen, case METHOD_BY_CONTENT: case METHOD_EXPLICIT: - + if (!open_wv_file(this)) { free (this); return NULL; } - + break; default: @@ -387,11 +387,11 @@ static const char *get_identifier (demux_class_t *const this_gen) { } static const char *get_extensions (demux_class_t *const this_gen) { - return "wv"; + return "wv wvp"; } static const char *get_mimetypes (demux_class_t *const this_gen) { - return NULL; + return "audio/x-wavpack: wv,wvp: WavPack audio;"; } static void class_dispose (demux_class_t *const this_gen) { @@ -401,7 +401,7 @@ static void class_dispose (demux_class_t *const this_gen) { } void *demux_wv_init_plugin (xine_t *const xine, void *const data) { - demux_wv_class_t *const this = xine_xmalloc (sizeof (demux_wv_class_t)); + demux_wv_class_t *const this = calloc(1, sizeof (demux_wv_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/combined/ffmpeg/Makefile.am b/src/combined/ffmpeg/Makefile.am new file mode 100644 index 000000000..24cab7577 --- /dev/null +++ b/src/combined/ffmpeg/Makefile.am @@ -0,0 +1,81 @@ +include $(top_builddir)/misc/Makefile.plugins +include $(top_srcdir)/misc/Makefile.common + +DEFAULT_INCLUDES = -I. + +if HAVE_FFMPEG +ff_cppflags = $(FFMPEG_CFLAGS) $(FFMPEG_POSTPROC_CFLAGS) +link_ffmpeg = $(FFMPEG_LIBS) $(FFMPEG_UTIL_LIBS) $(FFMPEG_POSTPROC_LIBS) +else +ff_cppflags = -I$(top_builddir)/src/libffmpeg -I$(top_srcdir)/src/libffmpeg/libavcodec -I$(top_srcdir)/src/libffmpeg/libavutil +link_ffmpeg = \ + $(top_builddir)/src/libffmpeg/libavcodec/libavcodec.la \ + $(top_builddir)/src/libffmpeg/libavutil/libavutil.la \ + $(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la +endif + +ff_generated = \ + avcodec_video.list avcodec_audio.list \ + ff_video_list.h ff_audio_list.h + +BUILT_SOURCES = $(ff_generated) + +# ffmpeg_config.h is generated by configure +DISTCLEANFILES = ffmpeg_config.h $(ff_generated) + +# this must always be included, even if the current machine has no DXR3... +EXTRA_DIST = ffmpeg_encoder.c \ + xine_video.list xine_audio.list mkcodeclist.pl + +xineplug_LTLIBRARIES = xineplug_decode_ff.la xineplug_decode_dvaudio.la + +if HAVE_DXR3 +AM_CPPFLAGS = -I$(top_srcdir)/src/dxr3 $(X_CFLAGS) $(ff_cppflags) \ + $(ZLIB_CPPFLAGS) +xineplug_decode_ff_la_SOURCES = ffmpeg_decoder.c ff_audio_decoder.c ff_video_decoder.c \ + ffmpeg_encoder.c ff_mpeg_parser.c ffmpeg_decoder.h \ + ff_mpeg_parser.h +else +AM_CPPFLAGS = $(ff_cppflags) $(ZLIB_CPPFLAGS) +xineplug_decode_ff_la_SOURCES = ffmpeg_decoder.c ff_audio_decoder.c ff_video_decoder.c \ + ff_mpeg_parser.c ffmpeg_decoder.h ff_mpeg_parser.h +endif + +xineplug_decode_ff_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) +xineplug_decode_ff_la_LDFLAGS = $(xineplug_ldflags) $(IMPURE_TEXT_LDFLAGS) +xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm $(ZLIB_LIBS) \ + $(link_ffmpeg) $(PTHREAD_LIBS) $(LTLIBINTL) + +xineplug_decode_dvaudio_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) +xineplug_decode_dvaudio_la_LDFLAGS = $(xineplug_ldflags) +xineplug_decode_dvaudio_la_SOURCES = ff_dvaudio_decoder.c +xineplug_decode_dvaudio_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) + +$(top_srcdir)/src/libffmpeg/libavcodec/libavcodec.la: + make -C $(top_srcdir)/src/libffmpeg + +# Generation of ffmpeg->xine codec mapping lists (see xine_*.list). + +AV_CPP = $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) + +# Extract some CODEC_ID_* from avcodec.h. Requires some sed mangling. +avcodec_audio.list: AV_CODECS:=/CODEC_ID_PCM_S16LE/,/CODEC_ID_DVD_SUBTITLE/ +avcodec_video.list: AV_CODECS:=/CODEC_ID_MPEG1VIDEO/,/CODEC_ID_PCM_S16LE/ + +avcodec_audio.list avcodec_video.list: + echo '#include "$(srcdir)/ffmpeg_decoder.h"' | $(AV_CPP) - |\ + sed -e $(AV_CODECS)'! d; s/^[ \t]*//; s/[=,].*//; /^$$/ d' >$@ + +# Generate the mappings. These are #included where needed. +ff_%_list.h: $(srcdir)/mkcodeclist.pl avcodec_%.list $(srcdir)/xine_%.list + $(PERL) $^ $@ + +ff_audio_decoder.c: ff_audio_list.h +ff_video_decoder.c: ff_video_list.h + +# 'make report' prints tokens corresponding to any unhandled codecs. +report: avcodec_audio.list avcodec_video.list + @$(top_srcdir)/src/combined/ffmpeg/mkcodeclist.pl avcodec_audio.list xine_audio.list - audio + @$(top_srcdir)/src/combined/ffmpeg/mkcodeclist.pl avcodec_video.list xine_video.list - video + +.PHONY: report diff --git a/src/libffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c index 5f197bed5..bd3ada69d 100644 --- a/src/libffmpeg/ff_audio_decoder.c +++ b/src/combined/ffmpeg/ff_audio_decoder.c @@ -1,28 +1,28 @@ /* - * Copyright (C) 2001-2005 the xine project - * + * Copyright (C) 2001-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * xine audio decoder plugin using ffmpeg */ - + #ifdef HAVE_CONFIG_H #include "config.h" -#include "ffmpeg_config.h" +#include "../../libffmpeg/ffmpeg_config.h" #endif #include <stdlib.h> @@ -66,55 +66,20 @@ typedef struct ff_audio_decoder_s { AVCodecContext *context; AVCodec *codec; - + char *decode_buffer; int decoder_ok; } ff_audio_decoder_t; -static const ff_codec_t ff_audio_lookup[] = { - {BUF_AUDIO_WMAV1, CODEC_ID_WMAV1, "MS Windows Media Audio 1 (ffmpeg)"}, - {BUF_AUDIO_WMAV2, CODEC_ID_WMAV2, "MS Windows Media Audio 2 (ffmpeg)"}, - {BUF_AUDIO_14_4, CODEC_ID_RA_144, "Real 14.4 (ffmpeg)"}, - {BUF_AUDIO_28_8, CODEC_ID_RA_288, "Real 28.8 (ffmpeg)"}, - {BUF_AUDIO_MPEG, CODEC_ID_MP3, "MP3 (ffmpeg)"}, - {BUF_AUDIO_MSADPCM, CODEC_ID_ADPCM_MS, "MS ADPCM (ffmpeg)"}, - {BUF_AUDIO_QTIMAADPCM, CODEC_ID_ADPCM_IMA_QT, "QT IMA ADPCM (ffmpeg)"}, - {BUF_AUDIO_MSIMAADPCM, CODEC_ID_ADPCM_IMA_WAV, "MS IMA ADPCM (ffmpeg)"}, - {BUF_AUDIO_DK3ADPCM, CODEC_ID_ADPCM_IMA_DK3, "Duck DK3 ADPCM (ffmpeg)"}, - {BUF_AUDIO_DK4ADPCM, CODEC_ID_ADPCM_IMA_DK4, "Duck DK4 ADPCM (ffmpeg)"}, - {BUF_AUDIO_VQA_IMA, CODEC_ID_ADPCM_IMA_WS, "Westwood Studios IMA (ffmpeg)"}, - {BUF_AUDIO_SMJPEG_IMA, CODEC_ID_ADPCM_IMA_SMJPEG, "SMJPEG IMA (ffmpeg)"}, - {BUF_AUDIO_XA_ADPCM, CODEC_ID_ADPCM_XA, "CD-ROM/XA ADPCM (ffmpeg)"}, - {BUF_AUDIO_4X_ADPCM, CODEC_ID_ADPCM_4XM, "4X ADPCM (ffmpeg)"}, - {BUF_AUDIO_EA_ADPCM, CODEC_ID_ADPCM_EA, "Electronic Arts ADPCM (ffmpeg)"}, - {BUF_AUDIO_MULAW, CODEC_ID_PCM_MULAW, "mu-law logarithmic PCM (ffmpeg)"}, - {BUF_AUDIO_ALAW, CODEC_ID_PCM_ALAW, "A-law logarithmic PCM (ffmpeg)"}, - {BUF_AUDIO_ROQ, CODEC_ID_ROQ_DPCM, "RoQ DPCM (ffmpeg)"}, - {BUF_AUDIO_INTERPLAY, CODEC_ID_INTERPLAY_DPCM, "Interplay DPCM (ffmpeg)"}, - {BUF_AUDIO_MAC3, CODEC_ID_MACE3, "MACE 3:1 (ffmpeg)"}, - {BUF_AUDIO_MAC6, CODEC_ID_MACE6, "MACE 6:1 (ffmpeg)"}, - {BUF_AUDIO_XAN_DPCM, CODEC_ID_XAN_DPCM, "Origin Xan DPCM (ffmpeg)"}, - {BUF_AUDIO_VMD, CODEC_ID_VMDAUDIO, "Sierra VMD Audio (ffmpeg)"}, - {BUF_AUDIO_FLAC, CODEC_ID_FLAC, "FLAC (ffmpeg)"}, - {BUF_AUDIO_SHORTEN, CODEC_ID_SHORTEN, "Shorten (ffmpeg)"}, - {BUF_AUDIO_ALAC, CODEC_ID_ALAC, "ALAC (ffmpeg)"}, - {BUF_AUDIO_QDESIGN2, CODEC_ID_QDM2, "QDesign (ffmpeg)"}, - {BUF_AUDIO_COOK, CODEC_ID_COOK, "RealAudio Cooker (ffmpeg)"}, - {BUF_AUDIO_TRUESPEECH, CODEC_ID_TRUESPEECH, "TrueSpeech (ffmpeg)"}, - {BUF_AUDIO_TTA, CODEC_ID_TTA, "True Audio Lossless (ffmpeg)"}, - {BUF_AUDIO_SMACKER, CODEC_ID_SMACKAUDIO, "Smacker (ffmpeg)"}, - {BUF_AUDIO_FLVADPCM, CODEC_ID_ADPCM_SWF, "Flash ADPCM (ffmpeg)"}, - {BUF_AUDIO_WAVPACK, CODEC_ID_WAVPACK, "WavPack (ffmpeg)"}, -}; - +#include "ff_audio_list.h" static void ff_audio_ensure_buffer_size(ff_audio_decoder_t *this, int size) { if (size > this->bufsize) { this->bufsize = size + size / 2; xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("ffmpeg_audio_dec: increasing buffer to %d to avoid overflow.\n"), + _("ffmpeg_audio_dec: increasing buffer to %d to avoid overflow.\n"), this->bufsize); this->buf = realloc( this->buf, this->bufsize ); } @@ -137,15 +102,15 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) ff_audio_ensure_buffer_size(this, this->size + buf->size); memcpy(this->buf + this->size, buf->content, buf->size); this->size += buf->size; - + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { size_t i; unsigned int codec_type; xine_waveformatex *audio_header; - + codec_type = buf->type & 0xFFFF0000; this->codec = NULL; - + for(i = 0; i < sizeof(ff_audio_lookup)/sizeof(ff_codec_t); i++) if(ff_audio_lookup[i].type == codec_type) { pthread_mutex_lock (&ffmpeg_lock); @@ -155,93 +120,138 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) ff_audio_lookup[i].name); break; } - + if (!this->codec) { - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_audio_dec: couldn't find ffmpeg decoder for buf type 0x%X\n"), codec_type); _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); return; } - + this->context = avcodec_alloc_context(); - + if(buf->decoder_flags & BUF_FLAG_STDHEADER) { this->audio_sample_rate = buf->decoder_info[1]; this->audio_channels = buf->decoder_info[3]; - + if(this->size) { audio_header = (xine_waveformatex *)this->buf; - + this->context->block_align = audio_header->nBlockAlign; this->context->bit_rate = audio_header->nAvgBytesPerSec * 8; - + if(audio_header->cbSize > 0) { - this->context->extradata = xine_xmalloc(audio_header->cbSize); + this->context->extradata = malloc(audio_header->cbSize); this->context->extradata_size = audio_header->cbSize; - memcpy( this->context->extradata, + memcpy( this->context->extradata, (uint8_t *)audio_header + sizeof(xine_waveformatex), - audio_header->cbSize ); + audio_header->cbSize ); } } } else { short *ptr; - + switch(codec_type) { case BUF_AUDIO_14_4: this->audio_sample_rate = 8000; this->audio_channels = 1; - + this->context->block_align = 240; break; case BUF_AUDIO_28_8: this->audio_sample_rate = _X_BE_16(&this->buf[0x30]); this->audio_channels = this->buf[0x37]; /* this->audio_bits = buf->content[0x35] */ - - this->context->block_align = _X_BE_16(&this->buf[0x2A]); - + + this->context->block_align = _X_BE_32(&this->buf[0x18]); + this->context->extradata_size = 5*sizeof(short); - this->context->extradata = xine_xmalloc(this->context->extradata_size); - + this->context->extradata = malloc(this->context->extradata_size); + ptr = (short *) this->context->extradata; - + ptr[0] = _X_BE_16(&this->buf[0x2C]); /* subpacket size */ ptr[1] = _X_BE_16(&this->buf[0x28]); /* subpacket height */ ptr[2] = _X_BE_16(&this->buf[0x16]); /* subpacket flavour */ ptr[3] = _X_BE_32(&this->buf[0x18]); /* coded frame size */ ptr[4] = 0; /* codec's data length */ + + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_audio_dec: 28_8 audio channels %d bits %d sample rate %d block align %d\n", + this->audio_channels, this->audio_bits, this->audio_sample_rate, + this->context->block_align); break; + case BUF_AUDIO_COOK: + { + int version; + int data_len; + int extradata; + + version = _X_BE_16 (this->buf+4); + if (version == 4) { + this->audio_sample_rate = _X_BE_16 (this->buf+48); + this->audio_bits = _X_BE_16 (this->buf+52); + this->audio_channels = _X_BE_16 (this->buf+54); + data_len = _X_BE_32 (this->buf+67); + extradata = 71; + } else { + this->audio_sample_rate = _X_BE_16 (this->buf+54); + this->audio_bits = _X_BE_16 (this->buf+58); + this->audio_channels = _X_BE_16 (this->buf+60); + data_len = _X_BE_32 (this->buf+74); + extradata = 78; + } + this->context->block_align = _X_BE_16 (this->buf+44); + + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_audio_dec: cook audio channels %d bits %d sample rate %d block align %d\n", + this->audio_channels, this->audio_bits, this->audio_sample_rate, + this->context->block_align); + + if (extradata + data_len > this->size) + break; /* abort early - extradata length is bad */ + if (extradata > INT_MAX - data_len) + break;/*integer overflow*/ + + this->context->extradata_size = data_len; + this->context->extradata = malloc(this->context->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + xine_fast_memcpy (this->context->extradata, this->buf + extradata, + this->context->extradata_size); + break; + } default: xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "ffmpeg_audio_dec: unknown header with buf type 0x%X\n", codec_type); break; } } - - /* Current ffmpeg audio decoders always use 16 bits/sample + + /* Current ffmpeg audio decoders always use 16 bits/sample * buf->decoder_info[2] can't be used as it doesn't refer to the output * bits/sample for some codecs (e.g. MS ADPCM) */ - this->audio_bits = 16; - + this->audio_bits = 16; + this->context->bits_per_sample = this->audio_bits; this->context->sample_rate = this->audio_sample_rate; this->context->channels = this->audio_channels; this->context->codec_id = this->codec->id; + this->context->codec_type = this->codec->type; this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC); - + this->size = 0; - - this->decode_buffer = xine_xmalloc(AVCODEC_MAX_AUDIO_FRAME_SIZE); - + + this->decode_buffer = calloc(1, AVCODEC_MAX_AUDIO_FRAME_SIZE); + return; } } else if ((buf->decoder_flags & BUF_FLAG_SPECIAL) && (buf->decoder_info[1] == BUF_SPECIAL_STSD_ATOM)) { this->context->extradata_size = buf->decoder_info[2]; - this->context->extradata = xine_xmalloc(buf->decoder_info[2] + - FF_INPUT_BUFFER_PADDING_SIZE); + this->context->extradata = malloc(buf->decoder_info[2] + + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(this->context->extradata, buf->decoder_info_ptr[2], buf->decoder_info[2]); @@ -258,16 +268,35 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) pthread_mutex_lock (&ffmpeg_lock); if (avcodec_open (this->context, this->codec) < 0) { pthread_mutex_unlock (&ffmpeg_lock); - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_audio_dec: couldn't open decoder\n")); _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); return; } - pthread_mutex_unlock (&ffmpeg_lock); + pthread_mutex_unlock (&ffmpeg_lock); this->decoder_ok = 1; } + if( buf->decoder_flags & BUF_FLAG_PREVIEW ) + return; + + ff_audio_ensure_buffer_size(this, this->size + buf->size); + xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); + this->size += buf->size; + if (!this->output_open) { + if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) { + avcodec_decode_audio2 (this->context, + (int16_t *)this->decode_buffer, + &decode_buffer_size, + &this->buf[0], + this->size); + this->audio_bits = this->context->bits_per_sample; + this->audio_sample_rate = this->context->sample_rate; + this->audio_channels = this->context->channels; + if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) + return; + } this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, this->audio_bits, this->audio_sample_rate, _x_ao_channels2mode(this->audio_channels)); @@ -277,26 +306,19 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) if (!this->output_open) return; - if( buf->decoder_flags & BUF_FLAG_PREVIEW ) - return; - - ff_audio_ensure_buffer_size(this, this->size + buf->size); - xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); - this->size += buf->size; - if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* time to decode a frame */ offset = 0; while (this->size>0) { decode_buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; - bytes_consumed = avcodec_decode_audio2 (this->context, + bytes_consumed = avcodec_decode_audio2 (this->context, (int16_t *)this->decode_buffer, - &decode_buffer_size, + &decode_buffer_size, &this->buf[offset], this->size); if (bytes_consumed<0) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: error decompressing audio frame\n"); this->size=0; return; @@ -309,10 +331,17 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* dispatch the decoded audio */ out = 0; while (out < decode_buffer_size) { - audio_buffer = + int stream_status = xine_get_status(this->stream); + + if (stream_status == XINE_STATUS_QUIT || stream_status == XINE_STATUS_STOP) { + this->size = 0; + return; + } + + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_audio_dec: Help! Allocated audio buffer with nothing in it!\n"); return; } @@ -324,7 +353,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* fill up this buffer */ xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out], - bytes_to_send); + bytes_to_send); /* byte count / 2 (bytes / sample) / channels */ audio_buffer->num_frames = bytes_to_send / 2 / this->audio_channels; @@ -348,14 +377,15 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) static void ff_audio_reset (audio_decoder_t *this_gen) { ff_audio_decoder_t *this = (ff_audio_decoder_t *) this_gen; - + this->size = 0; /* try to reset the wma decoder */ if( this->context && this->decoder_ok ) { pthread_mutex_lock (&ffmpeg_lock); avcodec_close (this->context); - avcodec_open (this->context, this->codec); + if (avcodec_open (this->context, this->codec) < 0) + this->decoder_ok = 0; pthread_mutex_unlock (&ffmpeg_lock); } } @@ -366,7 +396,7 @@ static void ff_audio_discontinuity (audio_decoder_t *this_gen) { static void ff_audio_dispose (audio_decoder_t *this_gen) { ff_audio_decoder_t *this = (ff_audio_decoder_t *) this_gen; - + if( this->context && this->decoder_ok ) { pthread_mutex_lock (&ffmpeg_lock); avcodec_close (this->context); @@ -384,7 +414,7 @@ static void ff_audio_dispose (audio_decoder_t *this_gen) { free(this->context->extradata); if(this->context) - free(this->context); + av_free(this->context); free (this_gen); } @@ -393,7 +423,7 @@ static audio_decoder_t *ff_audio_open_plugin (audio_decoder_class_t *class_gen, ff_audio_decoder_t *this ; - this = (ff_audio_decoder_t *) xine_xmalloc (sizeof (ff_audio_decoder_t)); + this = calloc(1, sizeof (ff_audio_decoder_t)); this->audio_decoder.decode_data = ff_audio_decode_data; this->audio_decoder.reset = ff_audio_reset; @@ -407,7 +437,7 @@ static audio_decoder_t *ff_audio_open_plugin (audio_decoder_class_t *class_gen, this->size = 0; this->bufsize = 0; this->decoder_ok = 0; - + ff_audio_ensure_buffer_size(this, AUDIOBUFSIZE); return &this->audio_decoder; @@ -429,7 +459,7 @@ void *init_audio_plugin (xine_t *xine, void *data) { ff_audio_class_t *this ; - this = (ff_audio_class_t *) xine_xmalloc (sizeof (ff_audio_class_t)); + this = calloc(1, sizeof (ff_audio_class_t)); this->decoder_class.open_plugin = ff_audio_open_plugin; this->decoder_class.get_identifier = ff_audio_get_identifier; @@ -441,111 +471,7 @@ void *init_audio_plugin (xine_t *xine, void *data) { return this; } -static uint32_t supported_audio_types[] = { - #ifdef CONFIG_WMAV1_DECODER - BUF_AUDIO_WMAV1, - #endif - #ifdef CONFIG_WMAV2_DECODER - BUF_AUDIO_WMAV2, - #endif - #ifdef CONFIG_RA_144_DECODER - BUF_AUDIO_14_4, - #endif - #ifdef CONFIG_RA_288_DECODER - BUF_AUDIO_28_8, - #endif - #ifdef CONFIG_MP3_DECODER - BUF_AUDIO_MPEG, - #endif - #ifdef CONFIG_ADPCM_MS_DECODER - BUF_AUDIO_MSADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_QT_DECODER - BUF_AUDIO_QTIMAADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_WAV_DECODER - BUF_AUDIO_MSIMAADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_DK3_DECODER - BUF_AUDIO_DK3ADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_DK4_DECODER - BUF_AUDIO_DK4ADPCM, - #endif - #ifdef CONFIG_ADPCM_IMA_WS_DECODER - BUF_AUDIO_VQA_IMA, - #endif - #ifdef CONFIG_ADPCM_IMA_SMJPEG_DECODER - BUF_AUDIO_SMJPEG_IMA, - #endif - #ifdef CONFIG_ADPCM_XA_DECODER - BUF_AUDIO_XA_ADPCM, - #endif - #ifdef CONFIG_ADPCM_4XM_DECODER - BUF_AUDIO_4X_ADPCM, - #endif - #ifdef CONFIG_ADPCM_EA_DECODER - BUF_AUDIO_EA_ADPCM, - #endif - #ifdef CONFIG_PCM_MULAW_DECODER - BUF_AUDIO_MULAW, - #endif - #ifdef CONFIG_PCM_ALAW_DECODER - BUF_AUDIO_ALAW, - #endif - #ifdef CONFIG_ROQ_DPCM_DECODER - BUF_AUDIO_ROQ, - #endif - #ifdef CONFIG_INTERPLAY_DPCM_DECODER - BUF_AUDIO_INTERPLAY, - #endif - #ifdef CONFIG_MACE3_DECODER - BUF_AUDIO_MAC3, - #endif - #ifdef CONFIG_MACE6_DECODER - BUF_AUDIO_MAC6, - #endif - #ifdef CONFIG_XAN_DPCM_DECODER - BUF_AUDIO_XAN_DPCM, - #endif - #ifdef CONFIG_VMDAUDIO_DECODER - BUF_AUDIO_VMD, - #endif - #ifdef CONFIG_FLAC_DECODER - BUF_AUDIO_FLAC, - #endif - #ifdef CONFIG_SHORTEN_DECODER - BUF_AUDIO_SHORTEN, - #endif - #ifdef CONFIG_ALAC_DECODER - BUF_AUDIO_ALAC, - #endif - #ifdef CONFIG_QDM2_DECODER - BUF_AUDIO_QDESIGN2, - #endif - #ifdef CONFIG_COOK_DECODER - BUF_AUDIO_COOK, - #endif - #ifdef CONFIG_TRUESPEECH_DECODER - BUF_AUDIO_TRUESPEECH, - #endif - #ifdef CONFIG_TTA_DECODER - BUF_AUDIO_TTA, - #endif - #ifdef CONFIG_SMACKAUDIO_DECODER - BUF_AUDIO_SMACKER, - #endif - #ifdef CONFIG_ADPCM_SWF_DECODER - BUF_AUDIO_FLVADPCM, - #endif - #ifdef CONFIG_WAVPACK_DECODER - BUF_AUDIO_WAVPACK, - #endif - - 0 -}; - decoder_info_t dec_info_ffmpeg_audio = { supported_audio_types, /* supported types */ - 6 /* priority */ + 7 /* priority */ }; diff --git a/src/libffmpeg/ff_dvaudio_decoder.c b/src/combined/ffmpeg/ff_dvaudio_decoder.c index 0796b3862..4d78162df 100644 --- a/src/libffmpeg/ff_dvaudio_decoder.c +++ b/src/combined/ffmpeg/ff_dvaudio_decoder.c @@ -1,25 +1,25 @@ /* * Copyright (C) 2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * dv audio decoder based on patch by Dan Dennedy <dan@dennedy.org> */ - + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -52,14 +52,16 @@ # undef uint64_t #endif -#ifdef HAVE_FFMPEG +#ifdef HAVE_FFMPEG_AVUTIL_H # include <avcodec.h> -# include "libavcodec/dvdata.h" +#elif defined HAVE_FFMPEG +# include <libavcodec/avcodec.h> #else -# include "libavcodec/avcodec.h" -# include "libavcodec/dvdata.h" +# include "../../libffmpeg/libavcodec/avcodec.h" #endif +#include "../../libffmpeg/libavcodec/dvdata.h" + #ifdef _MSC_VER # undef malloc # undef free @@ -244,29 +246,29 @@ static void dvaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) int out; audio_buffer_t *audio_buffer; int bytes_to_send; - + if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; - + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { - this->buf = xine_xmalloc(AUDIOBUFSIZE); + this->buf = calloc(1, AUDIOBUFSIZE); this->bufsize = AUDIOBUFSIZE; this->size = 0; - this->decode_buffer = xine_xmalloc(MAXFRAMESIZE); - + this->decode_buffer = calloc(1, MAXFRAMESIZE); + this->audio_sample_rate = buf->decoder_info[1]; this->audio_bits = buf->decoder_info[2]; this->audio_channels = buf->decoder_info[3]; - + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "DV Audio"); - + this->decoder_ok = 1; - + return; } - + if (this->decoder_ok && !(buf->decoder_flags & (BUF_FLAG_HEADER|BUF_FLAG_SPECIAL))) { - + if (!this->output_open) { this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, this->audio_bits, this->audio_sample_rate, @@ -276,11 +278,11 @@ static void dvaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* if the audio still isn't open, bail */ if (!this->output_open) return; - + if( this->size + buf->size > this->bufsize ) { this->bufsize = this->size + 2 * buf->size; xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("dvaudio: increasing buffer to %d to avoid overflow.\n"), + _("dvaudio: increasing buffer to %d to avoid overflow.\n"), this->bufsize); this->buf = realloc( this->buf, this->bufsize ); } @@ -298,14 +300,14 @@ static void dvaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) bytes_consumed = dv_frame_profile(&this->buf[offset])->frame_size; else bytes_consumed = decode_buffer_size; - + /* dispatch the decoded audio */ out = 0; while (out < decode_buffer_size) { - audio_buffer = + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "dvaudio: Help! Allocated audio buffer with nothing in it!\n"); return; } @@ -341,7 +343,7 @@ static void dvaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) static void dvaudio_reset (audio_decoder_t *this_gen) { dvaudio_decoder_t *this = (dvaudio_decoder_t *) this_gen; - + this->size = 0; } @@ -351,7 +353,7 @@ static void dvaudio_discontinuity (audio_decoder_t *this_gen) { static void dvaudio_dispose (audio_decoder_t *this_gen) { dvaudio_decoder_t *this = (dvaudio_decoder_t *) this_gen; - + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = 0; @@ -366,7 +368,7 @@ static audio_decoder_t *dvaudio_open_plugin (audio_decoder_class_t *class_gen, x dvaudio_decoder_t *this ; - this = (dvaudio_decoder_t *) xine_xmalloc (sizeof (dvaudio_decoder_t)); + this = calloc(1, sizeof (dvaudio_decoder_t)); this->audio_decoder.decode_data = dvaudio_decode_data; this->audio_decoder.reset = dvaudio_reset; @@ -379,7 +381,7 @@ static audio_decoder_t *dvaudio_open_plugin (audio_decoder_class_t *class_gen, x this->buf = NULL; this->size = 0; this->decoder_ok = 0; - + return &this->audio_decoder; } @@ -399,7 +401,7 @@ static void *init_dvaudio_plugin (xine_t *xine, void *data) { dvaudio_class_t *this ; - this = (dvaudio_class_t *) xine_xmalloc (sizeof (dvaudio_class_t)); + this = calloc(1, sizeof (dvaudio_class_t)); this->decoder_class.open_plugin = dvaudio_open_plugin; this->decoder_class.get_identifier = dvaudio_get_identifier; @@ -409,7 +411,7 @@ static void *init_dvaudio_plugin (xine_t *xine, void *data) { return this; } -static uint32_t supported_audio_types[] = { +static uint32_t supported_audio_types[] = { BUF_AUDIO_DV, 0 }; @@ -418,13 +420,13 @@ static const decoder_info_t dec_info_dvaudio = { supported_audio_types, /* supported types */ 5 /* priority */ }; - + /* * exported plugin catalog entry */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 15, "dvaudio", XINE_VERSION_CODE, &dec_info_dvaudio, init_dvaudio_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libffmpeg/ff_mpeg_parser.c b/src/combined/ffmpeg/ff_mpeg_parser.c index 70901d93b..54f7d6c94 100644 --- a/src/libffmpeg/ff_mpeg_parser.c +++ b/src/combined/ffmpeg/ff_mpeg_parser.c @@ -50,14 +50,14 @@ static const int frame_rate_tab[][2] = { void mpeg_parser_init (mpeg_parser_t *parser) { - parser->chunk_buffer = xine_xmalloc(BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + parser->chunk_buffer = malloc(BUFFER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); mpeg_parser_reset(parser); } void mpeg_parser_dispose (mpeg_parser_t *parser) { if ( parser == NULL ) return; - + free(parser->chunk_buffer); } @@ -124,7 +124,7 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le { int is_frame_done; int next_code = parser->code; - + /* wait for sequence_header_code */ if (parser->is_sequence_needed) { if (code != 0xb3) { @@ -133,7 +133,7 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le return 0; } } - + is_frame_done = parser->in_slice && ((!next_code) || (next_code == 0xb7)); if (is_frame_done) @@ -141,7 +141,7 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le switch (code) { case 0x00: /* picture_start_code */ - + parse_header_picture (parser, buffer); parser->in_slice = 1; @@ -150,11 +150,11 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le case B_TYPE: lprintf ("B-Frame\n"); break; - + case P_TYPE: lprintf ("P-Frame\n"); break; - + case I_TYPE: lprintf ("I-Frame\n"); break; @@ -169,11 +169,11 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le { int value; uint16_t width, height; - + if (parser->is_sequence_needed) { parser->is_sequence_needed = 0; } - + if ((buffer[6] & 0x20) != 0x20) { lprintf("Invalid sequence: missing marker_bit\n"); parser->has_sequence = 0; @@ -185,7 +185,7 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le buffer[2]; width = ((value >> 12) + 15) & ~15; height = ((value & 0xfff) + 15) & ~15; - + if ((width > 1920) || (height > 1152)) { lprintf("Invalid sequence: width=%d, height=%d\n", width, height); parser->has_sequence = 0; @@ -196,7 +196,7 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le parser->height = height; parser->rate_code = buffer[3] & 15; parser->aspect_ratio_info = buffer[3] >> 4; - + if (parser->rate_code < (sizeof(frame_rate_tab)/sizeof(*frame_rate_tab))) { parser->frame_duration = 90000; parser->frame_duration *= frame_rate_tab[parser->rate_code][1]; @@ -211,7 +211,7 @@ static int parse_chunk (mpeg_parser_t *parser, int code, uint8_t *buffer, int le parser->is_mpeg1 = 1; } break; - + case 0xb5: /* extension_start_code */ switch (buffer[0] & 0xf0) { case 0x10: /* sequence extension */ @@ -282,7 +282,7 @@ uint8_t *mpeg_parser_decode_data (mpeg_parser_t *parser, ret = 0; *flush = 0; - + while (current != end) { if (parser->chunk_ptr == parser->chunk_buffer) { /* write the beginning of the chunk */ @@ -294,9 +294,9 @@ uint8_t *mpeg_parser_decode_data (mpeg_parser_t *parser, parser->chunk_start = parser->chunk_ptr; parser->has_sequence = 0; } - + code = parser->code; - + current = copy_chunk (parser, current, end); if (current == NULL) return NULL; @@ -309,10 +309,10 @@ uint8_t *mpeg_parser_decode_data (mpeg_parser_t *parser, } parser->buffer_size = parser->chunk_ptr - parser->chunk_buffer - 4; parser->chunk_ptr = parser->chunk_buffer; - + if (parser->code == 0xb7) /* sequence end, maybe a still menu */ *flush = 1; - + return current; } } diff --git a/src/libffmpeg/ff_mpeg_parser.h b/src/combined/ffmpeg/ff_mpeg_parser.h index ea43a6ce4..5797933df 100644 --- a/src/libffmpeg/ff_mpeg_parser.h +++ b/src/combined/ffmpeg/ff_mpeg_parser.h @@ -49,7 +49,7 @@ typedef struct mpeg_parser_s { uint8_t in_slice:1; uint8_t rate_code:4; - + int aspect_ratio_info; /* public properties */ diff --git a/src/libffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index dc1176e78..727508847 100644 --- a/src/libffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -1,28 +1,28 @@ /* - * Copyright (C) 2001-2007 the xine project - * + * Copyright (C) 2001-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * xine video decoder plugin using ffmpeg */ - + #ifdef HAVE_CONFIG_H #include "config.h" -#include "ffmpeg_config.h" +#include "../../libffmpeg/ffmpeg_config.h" #endif #include <stdlib.h> @@ -45,10 +45,10 @@ #include "ffmpeg_decoder.h" #include "ff_mpeg_parser.h" -#ifdef HAVE_FFMPEG +#ifdef HAVE_FFMPEG_AVUTIL_H # include <postprocess.h> #else -# include "libavcodec/libpostproc/postprocess.h" +# include <libpostproc/postprocess.h> #endif #define VIDEOBUFSIZE (128*1024) @@ -58,6 +58,12 @@ #define ENABLE_DIRECT_RENDERING +/* reordered_opaque appeared in libavcodec 51.68.0 */ +#define AVCODEC_HAS_REORDERED_OPAQUE +#if LIBAVCODEC_VERSION_INT < 0x334400 +# undef AVCODEC_HAS_REORDERED_OPAQUE +#endif + typedef struct ff_video_decoder_s ff_video_decoder_t; typedef struct ff_video_class_s { @@ -67,7 +73,7 @@ typedef struct ff_video_class_s { int thread_count; int8_t skip_loop_filter_enum; int8_t choose_speed_over_accuracy; - + xine_t *xine; } ff_video_class_t; @@ -78,7 +84,14 @@ struct ff_video_decoder_s { xine_stream_t *stream; int64_t pts; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + uint64_t pts_tag_mask; + uint64_t pts_tag; + int pts_tag_counter; + int pts_tag_stable_counter; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ int video_step; + int reported_video_step; uint8_t decoder_ok:1; uint8_t decoder_init_mode:1; @@ -94,13 +107,13 @@ struct ff_video_decoder_s { int bufsize; int size; int skipframes; - + int slice_offset_size; AVFrame *av_frame; AVCodecContext *context; AVCodec *codec; - + int pp_quality; int pp_flags; pp_context_t *pp_context; @@ -113,7 +126,7 @@ struct ff_video_decoder_s { int aspect_ratio_prio; int frame_flags; int crop_right, crop_bottom; - + int output_format; xine_list_t *dr1_frames; @@ -121,6 +134,10 @@ struct ff_video_decoder_s { yuv_planes_t yuv; AVPaletteControl palette_control; + +#ifdef LOG + enum PixelFormat debug_fmt; +#endif }; @@ -137,7 +154,7 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ vo_frame_t *img; int width = context->width; int height = context->height; - + if (!this->bih.biWidth || !this->bih.biHeight) { this->bih.biWidth = width; this->bih.biHeight = height; @@ -149,12 +166,12 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ set_stream_info(this); } } - + avcodec_align_dimensions(context, &width, &height); - if( this->context->pix_fmt != PIX_FMT_YUV420P ) { + if( this->context->pix_fmt != PIX_FMT_YUV420P && this->context->pix_fmt != PIX_FMT_YUVJ420P ) { if (!this->is_direct_rendering_disabled) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: unsupported frame format, DR1 disabled.\n")); this->is_direct_rendering_disabled = 1; } @@ -165,14 +182,14 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ av_frame->data[2]= NULL; return avcodec_default_get_buffer(context, av_frame); } - + if((width != this->bih.biWidth) || (height != this->bih.biHeight)) { if(this->stream->video_out->get_capabilities(this->stream->video_out) & VO_CAP_CROP) { this->crop_right = width - this->bih.biWidth; this->crop_bottom = height - this->bih.biHeight; } else { if (!this->is_direct_rendering_disabled) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: unsupported frame dimensions, DR1 disabled.\n")); this->is_direct_rendering_disabled = 1; } @@ -187,7 +204,7 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ img = this->stream->video_out->get_frame (this->stream->video_out, width, height, - this->aspect_ratio, + this->aspect_ratio, this->output_format, VO_BOTH_FIELDS|this->frame_flags); @@ -208,6 +225,11 @@ static int get_buffer(AVCodecContext *context, AVFrame *av_frame){ av_frame->type= FF_BUFFER_TYPE_USER; +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* take over pts for this frame to have it reordered */ + av_frame->reordered_opaque = context->reordered_opaque; +#endif + xine_list_push_back(this->dr1_frames, av_frame); return 0; @@ -224,7 +246,7 @@ static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){ } xine_list_iterator_t it; - + it = xine_list_find(this->dr1_frames, av_frame); assert(it); if( it != NULL ) @@ -240,83 +262,7 @@ static void release_buffer(struct AVCodecContext *context, AVFrame *av_frame){ } #endif -static const ff_codec_t ff_video_lookup[] = { - {BUF_VIDEO_MSMPEG4_V1, CODEC_ID_MSMPEG4V1, "Microsoft MPEG-4 v1 (ffmpeg)"}, - {BUF_VIDEO_MSMPEG4_V2, CODEC_ID_MSMPEG4V2, "Microsoft MPEG-4 v2 (ffmpeg)"}, - {BUF_VIDEO_MSMPEG4_V3, CODEC_ID_MSMPEG4V3, "Microsoft MPEG-4 v3 (ffmpeg)"}, - {BUF_VIDEO_WMV7, CODEC_ID_WMV1, "MS Windows Media Video 7 (ffmpeg)"}, - {BUF_VIDEO_WMV8, CODEC_ID_WMV2, "MS Windows Media Video 8 (ffmpeg)"}, - {BUF_VIDEO_WMV9, CODEC_ID_WMV3, "MS Windows Media Video 9 (ffmpeg)"}, - {BUF_VIDEO_VC1, CODEC_ID_VC1, "MS Windows Media Video VC-1 (ffmpeg)"}, - {BUF_VIDEO_MPEG4, CODEC_ID_MPEG4, "ISO MPEG-4 (ffmpeg)"}, - {BUF_VIDEO_XVID, CODEC_ID_MPEG4, "ISO MPEG-4 (XviD, ffmpeg)"}, - {BUF_VIDEO_DIVX5, CODEC_ID_MPEG4, "ISO MPEG-4 (DivX5, ffmpeg)"}, - {BUF_VIDEO_3IVX, CODEC_ID_MPEG4, "ISO MPEG-4 (3ivx, ffmpeg)"}, - {BUF_VIDEO_JPEG, CODEC_ID_MJPEG, "Motion JPEG (ffmpeg)"}, - {BUF_VIDEO_MJPEG, CODEC_ID_MJPEG, "Motion JPEG (ffmpeg)"}, - {BUF_VIDEO_MJPEG_B, CODEC_ID_MJPEGB, "Motion JPEG B (ffmpeg)"}, - {BUF_VIDEO_I263, CODEC_ID_H263I, "ITU H.263 (ffmpeg)"}, - {BUF_VIDEO_H263, CODEC_ID_H263, "H.263 (ffmpeg)"}, - {BUF_VIDEO_RV10, CODEC_ID_RV10, "Real Video 1.0 (ffmpeg)"}, - {BUF_VIDEO_RV20, CODEC_ID_RV20, "Real Video 2.0 (ffmpeg)"}, - {BUF_VIDEO_IV31, CODEC_ID_INDEO3, "Indeo Video 3.1 (ffmpeg)"}, - {BUF_VIDEO_IV32, CODEC_ID_INDEO3, "Indeo Video 3.2 (ffmpeg)"}, - {BUF_VIDEO_SORENSON_V1, CODEC_ID_SVQ1, "Sorenson Video 1 (ffmpeg)"}, - {BUF_VIDEO_SORENSON_V3, CODEC_ID_SVQ3, "Sorenson Video 3 (ffmpeg)"}, - {BUF_VIDEO_DV, CODEC_ID_DVVIDEO, "DV (ffmpeg)"}, - {BUF_VIDEO_HUFFYUV, CODEC_ID_HUFFYUV, "HuffYUV (ffmpeg)"}, - {BUF_VIDEO_VP31, CODEC_ID_VP3, "On2 VP3.1 (ffmpeg)"}, - {BUF_VIDEO_VP5, CODEC_ID_VP5, "On2 VP5 (ffmpeg)"}, - {BUF_VIDEO_VP6, CODEC_ID_VP6, "On2 VP6 (ffmpeg)"}, - {BUF_VIDEO_VP6F, CODEC_ID_VP6F, "On2 VP6 (ffmpeg)"}, - {BUF_VIDEO_4XM, CODEC_ID_4XM, "4X Video (ffmpeg)"}, - {BUF_VIDEO_CINEPAK, CODEC_ID_CINEPAK, "Cinepak (ffmpeg)"}, - {BUF_VIDEO_MSVC, CODEC_ID_MSVIDEO1, "Microsoft Video 1 (ffmpeg)"}, - {BUF_VIDEO_MSRLE, CODEC_ID_MSRLE, "Microsoft RLE (ffmpeg)"}, - {BUF_VIDEO_RPZA, CODEC_ID_RPZA, "Apple Quicktime Video/RPZA (ffmpeg)"}, - {BUF_VIDEO_CYUV, CODEC_ID_CYUV, "Creative YUV (ffmpeg)"}, - {BUF_VIDEO_ROQ, CODEC_ID_ROQ, "Id Software RoQ (ffmpeg)"}, - {BUF_VIDEO_IDCIN, CODEC_ID_IDCIN, "Id Software CIN (ffmpeg)"}, - {BUF_VIDEO_WC3, CODEC_ID_XAN_WC3, "Xan (ffmpeg)"}, - {BUF_VIDEO_VQA, CODEC_ID_WS_VQA, "Westwood Studios VQA (ffmpeg)"}, - {BUF_VIDEO_INTERPLAY, CODEC_ID_INTERPLAY_VIDEO, "Interplay MVE (ffmpeg)"}, - {BUF_VIDEO_FLI, CODEC_ID_FLIC, "FLIC Video (ffmpeg)"}, - {BUF_VIDEO_8BPS, CODEC_ID_8BPS, "Planar RGB (ffmpeg)"}, - {BUF_VIDEO_SMC, CODEC_ID_SMC, "Apple Quicktime Graphics/SMC (ffmpeg)"}, - {BUF_VIDEO_DUCKTM1, CODEC_ID_TRUEMOTION1,"Duck TrueMotion v1 (ffmpeg)"}, - {BUF_VIDEO_DUCKTM2, CODEC_ID_TRUEMOTION2,"Duck TrueMotion v2 (ffmpeg)"}, - {BUF_VIDEO_VMD, CODEC_ID_VMDVIDEO, "Sierra VMD Video (ffmpeg)"}, - {BUF_VIDEO_ZLIB, CODEC_ID_ZLIB, "ZLIB Video (ffmpeg)"}, - {BUF_VIDEO_MSZH, CODEC_ID_MSZH, "MSZH Video (ffmpeg)"}, - {BUF_VIDEO_ASV1, CODEC_ID_ASV1, "ASV v1 Video (ffmpeg)"}, - {BUF_VIDEO_ASV2, CODEC_ID_ASV2, "ASV v2 Video (ffmpeg)"}, - {BUF_VIDEO_ATIVCR1, CODEC_ID_VCR1, "ATI VCR-1 (ffmpeg)"}, - {BUF_VIDEO_FLV1, CODEC_ID_FLV1, "Flash Video (ffmpeg)"}, - {BUF_VIDEO_QTRLE, CODEC_ID_QTRLE, "Apple Quicktime Animation/RLE (ffmpeg)"}, - {BUF_VIDEO_H264, CODEC_ID_H264, "H.264/AVC (ffmpeg)"}, - {BUF_VIDEO_H261, CODEC_ID_H261, "H.261 (ffmpeg)"}, - {BUF_VIDEO_AASC, CODEC_ID_AASC, "Autodesk Video (ffmpeg)"}, - {BUF_VIDEO_LOCO, CODEC_ID_LOCO, "LOCO (ffmpeg)"}, - {BUF_VIDEO_QDRW, CODEC_ID_QDRAW, "QuickDraw (ffmpeg)"}, - {BUF_VIDEO_QPEG, CODEC_ID_QPEG, "Q-Team QPEG (ffmpeg)"}, - {BUF_VIDEO_TSCC, CODEC_ID_TSCC, "TechSmith Video (ffmpeg)"}, - {BUF_VIDEO_ULTI, CODEC_ID_ULTI, "IBM UltiMotion (ffmpeg)"}, - {BUF_VIDEO_WNV1, CODEC_ID_WNV1, "Winnow Video (ffmpeg)"}, - {BUF_VIDEO_XL, CODEC_ID_VIXL, "Miro/Pinnacle VideoXL (ffmpeg)"}, - {BUF_VIDEO_RT21, CODEC_ID_INDEO2, "Indeo/RealTime 2 (ffmpeg)"}, - {BUF_VIDEO_FPS1, CODEC_ID_FRAPS, "Fraps (ffmpeg)"}, - {BUF_VIDEO_MPEG, CODEC_ID_MPEG1VIDEO, "MPEG 1/2 (ffmpeg)"}, - {BUF_VIDEO_CSCD, CODEC_ID_CSCD, "CamStudio (ffmpeg)"}, - {BUF_VIDEO_AVS, CODEC_ID_AVS, "AVS (ffmpeg)"}, - {BUF_VIDEO_ALGMM, CODEC_ID_MMVIDEO, "American Laser Games MM (ffmpeg)"}, - {BUF_VIDEO_ZMBV, CODEC_ID_ZMBV, "Zip Motion Blocks Video (ffmpeg)"}, - {BUF_VIDEO_SMACKER, CODEC_ID_SMACKVIDEO, "Smacker (ffmpeg)"}, - {BUF_VIDEO_NUV, CODEC_ID_NUV, "NuppelVideo (ffmpeg)"}, - {BUF_VIDEO_KMVC, CODEC_ID_KMVC, "Karl Morton's Video Codec (ffmpeg)"}, - {BUF_VIDEO_FLASHSV, CODEC_ID_FLASHSV, "Flash Screen Video (ffmpeg)"}, - {BUF_VIDEO_CAVS, CODEC_ID_CAVS, "Chinese AVS (ffmpeg)"}, - {BUF_VIDEO_THEORA_RAW, CODEC_ID_THEORA, "Theora (ffmpeg)"}, -}; +#include "ff_video_list.h" static const char *const skip_loop_filter_enum_names[] = { "default", /* AVDISCARD_DEFAULT */ @@ -354,7 +300,7 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) } if (!this->codec) { - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: couldn't find ffmpeg decoder for buf type 0x%X\n"), codec_type); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0); @@ -363,30 +309,30 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) lprintf("lavc decoder found\n"); - /* force (width % 8 == 0), otherwise there will be - * display problems with Xv. - */ + /* force (width % 8 == 0), otherwise there will be + * display problems with Xv. + */ this->bih.biWidth = (this->bih.biWidth + 1) & (~1); this->context->width = this->bih.biWidth; this->context->height = this->bih.biHeight; - this->context->stream_codec_tag = this->context->codec_tag = + this->context->stream_codec_tag = this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_FOURCC); /* Some codecs (eg rv10) copy flags in init so it's necessary to set * this flag here in case we are going to use direct rendering */ - if(this->codec->capabilities & CODEC_CAP_DR1) { + if(this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264) { this->context->flags |= CODEC_FLAG_EMU_EDGE; } - + if (this->class->choose_speed_over_accuracy) this->context->flags2 |= CODEC_FLAG2_FAST; pthread_mutex_lock(&ffmpeg_lock); if (avcodec_open (this->context, this->codec) < 0) { pthread_mutex_unlock(&ffmpeg_lock); - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: couldn't open decoder\n")); free(this->context); this->context = NULL; @@ -394,6 +340,22 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) return; } + if (this->codec->id == CODEC_ID_VC1 && + (!this->bih.biWidth || !this->bih.biHeight)) { + /* VC1 codec must be re-opened with correct width and height. */ + avcodec_close(this->context); + + if (avcodec_open (this->context, this->codec) < 0) { + pthread_mutex_unlock(&ffmpeg_lock); + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + _("ffmpeg_video_dec: couldn't open decoder (pass 2)\n")); + free(this->context); + this->context = NULL; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0); + return; + } + } + if (this->class->thread_count > 1) { avcodec_thread_init(this->context, this->class->thread_count); this->context->thread_count = this->class->thread_count; @@ -422,14 +384,14 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) (this->stream->video_out->open) (this->stream->video_out, this->stream); this->skipframes = 0; - + /* enable direct rendering by default */ this->output_format = XINE_IMGFMT_YV12; #ifdef ENABLE_DIRECT_RENDERING if( this->codec->capabilities & CODEC_CAP_DR1 && this->codec->id != CODEC_ID_H264 ) { this->context->get_buffer = get_buffer; this->context->release_buffer = release_buffer; - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("ffmpeg_video_dec: direct rendering enabled\n")); } #endif @@ -460,25 +422,25 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type) static void choose_speed_over_accuracy_cb(void *user_data, xine_cfg_entry_t *entry) { ff_video_class_t *class = (ff_video_class_t *) user_data; - + class->choose_speed_over_accuracy = entry->num_value; } static void skip_loop_filter_enum_cb(void *user_data, xine_cfg_entry_t *entry) { ff_video_class_t *class = (ff_video_class_t *) user_data; - + class->skip_loop_filter_enum = entry->num_value; } static void thread_count_cb(void *user_data, xine_cfg_entry_t *entry) { ff_video_class_t *class = (ff_video_class_t *) user_data; - + class->thread_count = entry->num_value; } static void pp_quality_cb(void *user_data, xine_cfg_entry_t *entry) { ff_video_class_t *class = (ff_video_class_t *) user_data; - + class->pp_quality = entry->num_value; } @@ -491,15 +453,15 @@ static void pp_change_quality (ff_video_decoder_t *this) { this->pp_flags); if(this->pp_mode) pp_free_mode(this->pp_mode); - - this->pp_mode = pp_get_mode_by_name_and_quality("hb:a,vb:a,dr:a", + + this->pp_mode = pp_get_mode_by_name_and_quality("hb:a,vb:a,dr:a", this->pp_quality); } else { if(this->pp_mode) { pp_free_mode(this->pp_mode); this->pp_mode = NULL; } - + if(this->pp_context) { pp_free_context(this->pp_context); this->pp_context = NULL; @@ -524,22 +486,22 @@ static void init_postprocess (ff_video_decoder_t *this) { this->pp_available = 0; break; } - + /* Detect what cpu accel we have */ cpu_caps = xine_mm_accel(); this->pp_flags = PP_FORMAT_420; - + if(cpu_caps & MM_ACCEL_X86_MMX) this->pp_flags |= PP_CPU_CAPS_MMX; - + if(cpu_caps & MM_ACCEL_X86_MMXEXT) this->pp_flags |= PP_CPU_CAPS_MMX2; - - if(cpu_caps & MM_ACCEL_X86_3DNOW) + + if(cpu_caps & MM_ACCEL_X86_3DNOW) this->pp_flags |= PP_CPU_CAPS_3DNOW; - + /* Set level */ - pp_change_quality(this); + pp_change_quality(this); } static int ff_handle_mpeg_sequence(ff_video_decoder_t *this, mpeg_parser_t *parser) { @@ -548,13 +510,13 @@ static int ff_handle_mpeg_sequence(ff_video_decoder_t *this, mpeg_parser_t *pars * init codec */ if (this->decoder_init_mode) { - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "mpeg-1 (ffmpeg)"); init_video_codec (this, BUF_VIDEO_MPEG); this->decoder_init_mode = 0; } - + /* frame format change */ if ((parser->width != this->bih.biWidth) || (parser->height != this->bih.biHeight) || @@ -580,7 +542,7 @@ static int ff_handle_mpeg_sequence(ff_video_decoder_t *this, mpeg_parser_t *pars xine_event_send(this->stream, &event); } this->video_step = this->mpeg_parser->frame_duration; - + return 1; } @@ -588,6 +550,11 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { int y; uint8_t *dy, *du, *dv, *sy, *su, *sv; +#ifdef LOG + if (this->debug_fmt != this->context->pix_fmt) + printf ("frame format == %08x\n", this->debug_fmt = this->context->pix_fmt); +#endif + dy = img->base[0]; du = img->base[1]; dv = img->base[2]; @@ -595,6 +562,10 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { su = this->av_frame->data[1]; sv = this->av_frame->data[2]; + /* Some segfaults & heap corruption have been observed with img->height, + * so we use this->bih.biHeight instead (which is the displayed height) + */ + if (this->context->pix_fmt == PIX_FMT_YUV410P) { yuv9_to_yv12( @@ -615,7 +586,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - img->height); + this->bih.biHeight); } else if (this->context->pix_fmt == PIX_FMT_YUV411P) { @@ -637,19 +608,19 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { img->pitches[2], /* width x height */ img->width, - img->height); + this->bih.biHeight); + + } else if (this->context->pix_fmt == PIX_FMT_RGB32) { - } else if (this->context->pix_fmt == PIX_FMT_RGBA32) { - int x, plane_ptr = 0; uint32_t *argb_pixels; uint32_t argb; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { argb_pixels = (uint32_t *)sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; - + /* this is endian-safe as the ARGB pixels are stored in * machine order */ argb = *argb_pixels++; @@ -664,20 +635,20 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } sy += this->av_frame->linesize[0]; } - + yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]); - + } else if (this->context->pix_fmt == PIX_FMT_RGB565) { int x, plane_ptr = 0; uint8_t *src; uint16_t pixel16; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; - + /* a 16-bit RGB565 pixel is supposed to be stored in native-endian * byte order; the following should be endian-safe */ pixel16 = *((uint16_t *)src); @@ -693,20 +664,20 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } sy += this->av_frame->linesize[0]; } - + yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]); - + } else if (this->context->pix_fmt == PIX_FMT_RGB555) { - + int x, plane_ptr = 0; uint8_t *src; uint16_t pixel16; - - for(y = 0; y < img->height; y++) { + + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; - + /* a 16-bit RGB555 pixel is supposed to be stored in native-endian * byte order; the following should be endian-safe */ pixel16 = *((uint16_t *)src); @@ -722,19 +693,19 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } sy += this->av_frame->linesize[0]; } - + yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]); - + } else if (this->context->pix_fmt == PIX_FMT_BGR24) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; - + b = *src++; g = *src++; r = *src++; @@ -746,19 +717,19 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } sy += this->av_frame->linesize[0]; } - + yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]); - + } else if (this->context->pix_fmt == PIX_FMT_RGB24) { int x, plane_ptr = 0; uint8_t *src; - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { uint8_t r, g, b; - + r = *src++; g = *src++; b = *src++; @@ -770,11 +741,11 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } sy += this->av_frame->linesize[0]; } - + yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]); - + } else if (this->context->pix_fmt == PIX_FMT_PAL8) { - + int x, plane_ptr = 0; uint8_t *src; uint8_t pixel; @@ -797,7 +768,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { v_palette[x] = COMPUTE_V(r, g, b); } - for(y = 0; y < img->height; y++) { + for(y = 0; y < this->bih.biHeight; y++) { src = sy; for(x = 0; x < img->width; x++) { pixel = *src++; @@ -809,34 +780,34 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } sy += this->av_frame->linesize[0]; } - + yuv444_to_yuy2(&this->yuv, img->base[0], img->pitches[0]); - + } else { - - for (y=0; y<img->height; y++) { + + for (y = 0; y < this->bih.biHeight; y++) { xine_fast_memcpy (dy, sy, img->width); - + dy += img->pitches[0]; - + sy += this->av_frame->linesize[0]; } - for (y=0; y<(img->height/2); y++) { - + for (y = 0; y < this->bih.biHeight / 2; y++) { + if (this->context->pix_fmt != PIX_FMT_YUV444P) { - + xine_fast_memcpy (du, su, img->width/2); xine_fast_memcpy (dv, sv, img->width/2); - + } else { - + int x; uint8_t *src; uint8_t *dst; - + /* subsample */ - + src = su; dst = du; for (x=0; x<(img->width/2); x++) { *dst = *src; @@ -851,7 +822,7 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { } } - + du += img->pitches[1]; dv += img->pitches[2]; @@ -869,8 +840,8 @@ static void ff_convert_frame(ff_video_decoder_t *this, vo_frame_t *img) { static void ff_check_bufsize (ff_video_decoder_t *this, int size) { if (size > this->bufsize) { this->bufsize = size + size / 2; - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("ffmpeg_video_dec: increasing buffer to %d to avoid overflow.\n"), + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("ffmpeg_video_dec: increasing buffer to %d to avoid overflow.\n"), this->bufsize); this->buf = realloc(this->buf, this->bufsize + FF_INPUT_BUFFER_PADDING_SIZE ); } @@ -885,7 +856,7 @@ static void ff_handle_preview_buffer (ff_video_decoder_t *this, buf_element_t *b if (codec_type == BUF_VIDEO_MPEG) { this->is_mpeg12 = 1; if ( this->mpeg_parser == NULL ) { - this->mpeg_parser = xine_xmalloc(sizeof(mpeg_parser_t)); + this->mpeg_parser = calloc(1, sizeof(mpeg_parser_t)); mpeg_parser_init(this->mpeg_parser); this->decoder_init_mode = 0; } @@ -916,33 +887,53 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu if (buf->decoder_flags & BUF_FLAG_STDHEADER) { lprintf("standard header\n"); - + /* init package containing bih */ memcpy ( &this->bih, this->buf, sizeof(xine_bmiheader) ); if (this->bih.biSize > sizeof(xine_bmiheader)) { this->context->extradata_size = this->bih.biSize - sizeof(xine_bmiheader); - this->context->extradata = malloc(this->context->extradata_size + + this->context->extradata = malloc(this->context->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(this->context->extradata, this->buf + sizeof(xine_bmiheader), this->context->extradata_size); } - + this->context->bits_per_sample = this->bih.biBitCount; - + } else { - + switch (codec_type) { case BUF_VIDEO_RV10: case BUF_VIDEO_RV20: this->bih.biWidth = _X_BE_16(&this->buf[12]); this->bih.biHeight = _X_BE_16(&this->buf[14]); - + this->context->sub_id = _X_BE_32(&this->buf[30]); - this->context->slice_offset = xine_xmalloc(sizeof(int)*SLICE_OFFSET_SIZE); + this->context->slice_offset = calloc(SLICE_OFFSET_SIZE, sizeof(int)); this->slice_offset_size = SLICE_OFFSET_SIZE; + this->context->extradata_size = this->size - 26; + if (this->context->extradata_size < 8) { + this->context->extradata_size= 8; + this->context->extradata = malloc(this->context->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + ((uint32_t *)this->context->extradata)[0] = 0; + if (codec_type == BUF_VIDEO_RV10) + ((uint32_t *)this->context->extradata)[1] = 0x10000000; + else + ((uint32_t *)this->context->extradata)[1] = 0x10003001; + } else { + this->context->extradata = malloc(this->context->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(this->context->extradata, this->buf + 26, + this->context->extradata_size); + } + + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_video_dec: buf size %d\n", this->size); + lprintf("w=%d, h=%d\n", this->bih.biWidth, this->bih.biHeight); break; @@ -959,7 +950,7 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu } static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *buf) { - /* take care of all the various types of special buffers + /* take care of all the various types of special buffers * note that order is important here */ lprintf("special buffer\n"); @@ -968,34 +959,34 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b lprintf("BUF_SPECIAL_STSD_ATOM\n"); this->context->extradata_size = buf->decoder_info[2]; - this->context->extradata = xine_xmalloc(buf->decoder_info[2] + - FF_INPUT_BUFFER_PADDING_SIZE); + this->context->extradata = malloc(buf->decoder_info[2] + + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(this->context->extradata, buf->decoder_info_ptr[2], buf->decoder_info[2]); } else if (buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG && !this->context->extradata_size) { - + lprintf("BUF_SPECIAL_DECODER_CONFIG\n"); this->context->extradata_size = buf->decoder_info[2]; - this->context->extradata = xine_xmalloc(buf->decoder_info[2] + - FF_INPUT_BUFFER_PADDING_SIZE); + this->context->extradata = malloc(buf->decoder_info[2] + + FF_INPUT_BUFFER_PADDING_SIZE); memcpy(this->context->extradata, buf->decoder_info_ptr[2], buf->decoder_info[2]); - + } else if (buf->decoder_info[1] == BUF_SPECIAL_PALETTE) { unsigned int i; palette_entry_t *demuxer_palette; AVPaletteControl *decoder_palette; - + lprintf("BUF_SPECIAL_PALETTE\n"); this->context->palctrl = &this->palette_control; decoder_palette = (AVPaletteControl *)this->context->palctrl; demuxer_palette = (palette_entry_t *)buf->decoder_info_ptr[2]; for (i = 0; i < buf->decoder_info[2]; i++) { - decoder_palette->palette[i] = + decoder_palette->palette[i] = (demuxer_palette[i].r << 16) | (demuxer_palette[i].g << 8) | (demuxer_palette[i].b << 0); @@ -1004,20 +995,20 @@ static void ff_handle_special_buffer (ff_video_decoder_t *this, buf_element_t *b } else if (buf->decoder_info[1] == BUF_SPECIAL_RV_CHUNK_TABLE) { int i; - + lprintf("BUF_SPECIAL_RV_CHUNK_TABLE\n"); this->context->slice_count = buf->decoder_info[2]+1; lprintf("slice_count=%d\n", this->context->slice_count); - + if(this->context->slice_count > this->slice_offset_size) { this->context->slice_offset = realloc(this->context->slice_offset, sizeof(int)*this->context->slice_count); this->slice_offset_size = this->context->slice_count; } - + for(i = 0; i < this->context->slice_count; i++) { - this->context->slice_offset[i] = + this->context->slice_offset[i] = ((uint32_t *) buf->decoder_info_ptr[2])[(2*i)+1]; lprintf("slice_offset[%d]=%d\n", i, this->context->slice_offset[i]); } @@ -1060,7 +1051,7 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu if (!this->decoder_ok) return; - + if (flush) { lprintf("flush lavc buffers\n"); /* hack: ffmpeg outputs the last frame if size=0 */ @@ -1078,11 +1069,11 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu len, got_picture); len = current - buf->content - offset; lprintf("avcodec_decode_video: consumed_size=%d\n", len); - + flush = next_flush; if ((len < 0) || (len > buf->size)) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_video_dec: error decompressing frame\n"); size = 0; /* draw a bad frame and exit */ } else { @@ -1097,7 +1088,7 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu img = this->stream->video_out->get_frame (this->stream->video_out, this->bih.biWidth, this->bih.biHeight, - this->aspect_ratio, + this->aspect_ratio, this->output_format, VO_BOTH_FIELDS|this->frame_flags); free_img = 1; @@ -1117,7 +1108,7 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu img->crop_right = this->crop_right; img->crop_bottom = this->crop_bottom; - + this->skipframes = img->draw(img, this->stream); if(free_img) @@ -1130,7 +1121,7 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu img = this->stream->video_out->get_frame (this->stream->video_out, this->bih.biWidth, this->bih.biHeight, - this->aspect_ratio, + this->aspect_ratio, this->output_format, VO_BOTH_FIELDS|this->frame_flags); img->pts = 0; @@ -1143,6 +1134,97 @@ static void ff_handle_mpeg12_buffer (ff_video_decoder_t *this, buf_element_t *bu } } +#ifdef AVCODEC_HAS_REORDERED_OPAQUE +static uint64_t ff_tag_pts(ff_video_decoder_t *this, uint64_t pts) +{ + return pts | this->pts_tag; +} + +static uint64_t ff_untag_pts(ff_video_decoder_t *this, uint64_t pts) +{ + if (this->pts_tag_mask == 0) + return pts; /* pts tagging inactive */ + + if (this->pts_tag != 0 && (pts & this->pts_tag_mask) != this->pts_tag) + return 0; /* reset pts if outdated while waiting for first pass (see below) */ + + return pts & ~this->pts_tag_mask; +} + +static void ff_check_pts_tagging(ff_video_decoder_t *this, uint64_t pts) +{ + if (this->pts_tag_mask == 0) + return; /* pts tagging inactive */ + if ((pts & this->pts_tag_mask) != this->pts_tag) { + this->pts_tag_stable_counter = 0; + return; /* pts still outdated */ + } + + /* the tag should be stable for 100 frames */ + this->pts_tag_stable_counter++; + + if (this->pts_tag != 0) { + if (this->pts_tag_stable_counter >= 100) { + /* first pass: reset pts_tag */ + this->pts_tag = 0; + this->pts_tag_stable_counter = 0; + } + } else if (pts == 0) + return; /* cannot detect second pass */ + else { + if (this->pts_tag_stable_counter >= 100) { + /* second pass: reset pts_tag_mask and pts_tag_counter */ + this->pts_tag_mask = 0; + this->pts_tag_counter = 0; + this->pts_tag_stable_counter = 0; + } + } +} +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ + +static int ff_vc1_find_header(ff_video_decoder_t *this, buf_element_t *buf) +{ + uint8_t *p = buf->content; + + if (!p[0] && !p[1] && p[2] == 1 && p[3] == 0x0f) { + int i; + + this->context->extradata = calloc(1, buf->size); + this->context->extradata_size = 0; + + for (i = 0; i < buf->size && i < 128; i++) { + if (!p[i] && !p[i+1] && p[i+2]) { + lprintf("00 00 01 %02x at %d\n", p[i+3], i); + if (p[i+3] != 0x0e && p[i+3] != 0x0f) + break; + } + this->context->extradata[i] = p[i]; + this->context->extradata_size++; + } + + lprintf("ff_video_decoder: found VC1 sequence header\n"); + return 1; + } + + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "ffmpeg_video_dec: VC1 extradata missing !\n"); + return 0; +} + +static int ff_check_extradata(ff_video_decoder_t *this, unsigned int codec_type, buf_element_t *buf) +{ + if (this->context && this->context->extradata) + return 1; + + switch (codec_type) { + case BUF_VIDEO_VC1: + return ff_vc1_find_header(this, buf); + default:; + } + + return 1; +} + static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { uint8_t *chunk_buf = this->buf; AVRational avr00 = {0, 1}; @@ -1153,6 +1235,9 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { if (this->decoder_init_mode) { int codec_type = buf->type & 0xFFFF0000; + if (!ff_check_extradata(this, codec_type, buf)) + return; + /* init ffmpeg decoder */ init_video_codec(this, codec_type); init_postprocess(this); @@ -1167,10 +1252,20 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->size = 0; } +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + if (this->size == 0) { + /* take over pts when we are about to buffer a frame */ + this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); + if (this->context) /* shouldn't be NULL */ + this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->pts = 0; + } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ + /* data accumulation */ if (buf->size > 0) { if ((this->size == 0) && - ((buf->size + FF_INPUT_BUFFER_PADDING_SIZE) < buf->max_size) && + ((buf->size + FF_INPUT_BUFFER_PADDING_SIZE) < buf->max_size) && (buf->decoder_flags & BUF_FLAG_FRAME_END)) { /* buf contains a complete frame */ /* no memcpy needed */ @@ -1183,7 +1278,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { chunk_buf = this->buf; /* ff_check_bufsize might realloc this->buf */ xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); - + this->size += buf->size; lprintf("accumulate data into this->buf\n"); } @@ -1206,7 +1301,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { memset(&chunk_buf[this->size], 0, FF_INPUT_BUFFER_PADDING_SIZE); while (this->size > 0) { - + /* DV frames can be completely skipped */ if( codec_type == BUF_VIDEO_DV && this->skipframes ) { this->size = 0; @@ -1219,9 +1314,15 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { len = avcodec_decode_video (this->context, this->av_frame, &got_picture, &chunk_buf[offset], this->size); + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* reset consumed pts value */ + this->context->reordered_opaque = ff_tag_pts(this, 0); +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ + lprintf("consumed size: %d, got_picture: %d\n", len, got_picture); if ((len <= 0) || (len > this->size)) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ffmpeg_video_dec: error decompressing frame\n"); this->size = 0; @@ -1234,12 +1335,27 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_check_bufsize(this, this->size); memmove (this->buf, &chunk_buf[offset], this->size); chunk_buf = this->buf; + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* take over pts for next access unit */ + this->av_frame->reordered_opaque = ff_tag_pts(this, this->pts); + this->context->reordered_opaque = ff_tag_pts(this, this->pts); + this->pts = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } } } /* use externally provided video_step or fall back to stream's time_base otherwise */ - video_step_to_use = (this->video_step || !this->context->time_base.den) ? this->video_step : (int)(90000ll * this->context->time_base.num / this->context->time_base.den); + video_step_to_use = (this->video_step || !this->context->time_base.den) + ? this->video_step + : (int)(90000ll +#if LIBAVCODEC_VERSION_INT >= 0x341400 + * this->context->ticks_per_frame +#elif LIBAVCODEC_VERSION_INT >= 0x340000 +# warning Building without avcodec ticks_per_frame support; you should upgrade your libavcodec and recompile +#endif + * this->context->time_base.num / this->context->time_base.den); /* aspect ratio provided by ffmpeg, override previous setting */ if ((this->aspect_ratio_prio < 2) && @@ -1250,7 +1366,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { this->bih.biHeight = this->context->height; } - this->aspect_ratio = av_q2d(this->context->sample_aspect_ratio) * + this->aspect_ratio = av_q2d(this->context->sample_aspect_ratio) * (double)this->bih.biWidth / (double)this->bih.biHeight; this->aspect_ratio_prio = 2; lprintf("ffmpeg aspect ratio: %f\n", this->aspect_ratio); @@ -1265,7 +1381,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { /* initialize the colorspace converter */ if (!this->cs_convert_init) { - if ((this->context->pix_fmt == PIX_FMT_RGBA32) || + if ((this->context->pix_fmt == PIX_FMT_RGB32) || (this->context->pix_fmt == PIX_FMT_RGB565) || (this->context->pix_fmt == PIX_FMT_RGB555) || (this->context->pix_fmt == PIX_FMT_BGR24) || @@ -1289,7 +1405,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { img = this->stream->video_out->get_frame (this->stream->video_out, (this->bih.biWidth + 15) & ~15, (this->bih.biHeight + 15) & ~15, - this->aspect_ratio, + this->aspect_ratio, this->output_format, VO_BOTH_FIELDS|this->frame_flags); free_img = 1; @@ -1310,17 +1426,17 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { img = this->stream->video_out->get_frame (this->stream->video_out, (img->width + 15) & ~15, (img->height + 15) & ~15, - this->aspect_ratio, + this->aspect_ratio, this->output_format, VO_BOTH_FIELDS|this->frame_flags); free_img = 1; } - pp_postprocess(this->av_frame->data, this->av_frame->linesize, - img->base, img->pitches, + pp_postprocess(this->av_frame->data, this->av_frame->linesize, + img->base, img->pitches, img->width, img->height, this->av_frame->qscale_table, this->av_frame->qstride, - this->pp_mode, this->pp_context, + this->pp_mode, this->pp_context, this->av_frame->pict_type); } else if (!this->av_frame->opaque) { @@ -1328,15 +1444,24 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { ff_convert_frame(this, img); } +#ifndef AVCODEC_HAS_REORDERED_OPAQUE img->pts = this->pts; this->pts = 0; +#else /* AVCODEC_HAS_REORDERED_OPAQUE */ + img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); + ff_check_pts_tagging(this, this->av_frame->reordered_opaque); /* only check for valid frames */ + this->av_frame->reordered_opaque = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ /* workaround for weird 120fps streams */ if( video_step_to_use == 750 ) { /* fallback to the VIDEO_PTS_MODE */ video_step_to_use = 0; } - + + if (video_step_to_use && video_step_to_use != this->reported_video_step) + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, (this->reported_video_step = video_step_to_use)); + if (this->av_frame->repeat_pict) img->duration = video_step_to_use * 3 / 2; else @@ -1351,7 +1476,7 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { img->top_field_first = this->av_frame->top_field_first; this->skipframes = img->draw(img, this->stream); - + if(free_img) img->free(img); } @@ -1365,12 +1490,17 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { img = this->stream->video_out->get_frame (this->stream->video_out, (this->bih.biWidth <= 0) ? 16 : ((this->bih.biWidth + 15) & ~15), (this->bih.biHeight <= 0) ? 16 : ((this->bih.biHeight + 15) & ~15), - this->aspect_ratio, + this->aspect_ratio, this->output_format, VO_BOTH_FIELDS|this->frame_flags); /* set PTS to allow early syncing */ +#ifndef AVCODEC_HAS_REORDERED_OPAQUE img->pts = this->pts; this->pts = 0; +#else /* AVCODEC_HAS_REORDERED_OPAQUE */ + img->pts = ff_untag_pts(this, this->av_frame->reordered_opaque); + this->av_frame->reordered_opaque = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ img->duration = video_step_to_use; @@ -1390,16 +1520,16 @@ static void ff_handle_buffer (ff_video_decoder_t *this, buf_element_t *buf) { static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { ff_video_decoder_t *this = (ff_video_decoder_t *) this_gen; - lprintf ("processing packet type = %08x, len = %d, decoder_flags=%08x\n", + lprintf ("processing packet type = %08x, len = %d, decoder_flags=%08x\n", buf->type, buf->size, buf->decoder_flags); if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, (this->reported_video_step = this->video_step)); } if (buf->decoder_flags & BUF_FLAG_PREVIEW) { - + ff_handle_preview_buffer(this, buf); } else { @@ -1407,7 +1537,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_flags & BUF_FLAG_SPECIAL) { ff_handle_special_buffer(this, buf); - + } if (buf->decoder_flags & BUF_FLAG_HEADER) { @@ -1421,7 +1551,7 @@ static void ff_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { lprintf("aspect ratio: %f\n", this->aspect_ratio); set_stream_info(this); } - } + } } else { @@ -1452,31 +1582,73 @@ static void ff_reset (video_decoder_t *this_gen) { if(this->context && this->decoder_ok) avcodec_flush_buffers(this->context); - + if (this->is_mpeg12) mpeg_parser_reset(this->mpeg_parser); + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + this->pts_tag_mask = 0; + this->pts_tag = 0; + this->pts_tag_counter = 0; + this->pts_tag_stable_counter = 0; +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } static void ff_discontinuity (video_decoder_t *this_gen) { ff_video_decoder_t *this = (ff_video_decoder_t *) this_gen; - + lprintf ("ff_discontinuity\n"); this->pts = 0; + +#ifdef AVCODEC_HAS_REORDERED_OPAQUE + /* + * there is currently no way to reset all the pts which are stored in the decoder. + * therefore, we add a unique tag (generated from pts_tag_counter) to pts (see + * ff_tag_pts()) and wait for it to appear on returned frames. + * until then, any retrieved pts value will be reset to 0 (see ff_untag_pts()). + * when we see the tag returned, pts_tag will be reset to 0. from now on, any + * untagged pts value is valid already. + * when tag 0 appears too, there are no tags left in the decoder so pts_tag_mask + * and pts_tag_counter will be reset to 0 too (see ff_check_pts_tagging()). + */ + this->pts_tag_counter++; + this->pts_tag_mask = 0; + this->pts_tag = 0; + this->pts_tag_stable_counter = 0; + { + /* pts values typically don't use the uppermost bits. therefore we put the tag there */ + int counter_mask = 1; + int counter = 2 * this->pts_tag_counter + 1; /* always set the uppermost bit in tag_mask */ + uint64_t tag_mask = 0x8000000000000000ull; + while (this->pts_tag_counter >= counter_mask) + { + /* + * mirror the counter into the uppermost bits. this allows us to enlarge mask as + * necessary and while previous taggings can still be detected to be outdated. + */ + if (counter & counter_mask) + this->pts_tag |= tag_mask; + this->pts_tag_mask |= tag_mask; + tag_mask >>= 1; + counter_mask <<= 1; + } + } +#endif /* AVCODEC_HAS_REORDERED_OPAQUE */ } static void ff_dispose (video_decoder_t *this_gen) { ff_video_decoder_t *this = (ff_video_decoder_t *) this_gen; lprintf ("ff_dispose\n"); - + if (this->decoder_ok) { xine_list_iterator_t it; AVFrame *av_frame; - + pthread_mutex_lock(&ffmpeg_lock); avcodec_close (this->context); pthread_mutex_unlock(&ffmpeg_lock); - + /* frame garbage collector here - workaround for buggy ffmpeg codecs that * don't release their DR1 frames */ while( (it = xine_list_front(this->dr1_frames)) != NULL ) @@ -1484,7 +1656,7 @@ static void ff_dispose (video_decoder_t *this_gen) { av_frame = (AVFrame *)xine_list_get_value(this->dr1_frames, it); release_buffer(this->context, av_frame); } - + this->stream->video_out->close(this->stream->video_out, this->stream); this->decoder_ok = 0; } @@ -1497,27 +1669,27 @@ static void ff_dispose (video_decoder_t *this_gen) { if(this->yuv_init) free_yuv_planes(&this->yuv); - + if( this->context ) - free( this->context ); + av_free( this->context ); if( this->av_frame ) - free( this->av_frame ); - + av_free( this->av_frame ); + if (this->buf) free(this->buf); this->buf = NULL; - + if(this->pp_context) pp_free_context(this->pp_context); - + if(this->pp_mode) pp_free_mode(this->pp_mode); mpeg_parser_dispose(this->mpeg_parser); - + xine_list_delete(this->dr1_frames); - + free (this_gen); } @@ -1527,7 +1699,7 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen, lprintf ("open_plugin\n"); - this = (ff_video_decoder_t *) xine_xmalloc (sizeof (ff_video_decoder_t)); + this = calloc(1, sizeof (ff_video_decoder_t)); this->video_decoder.decode_data = ff_decode_data; this->video_decoder.flush = ff_flush; @@ -1543,10 +1715,10 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen, this->context = avcodec_alloc_context(); this->context->opaque = this; this->context->palctrl = NULL; - + this->decoder_ok = 0; this->decoder_init_mode = 1; - this->buf = xine_xmalloc(VIDEOBUFSIZE + FF_INPUT_BUFFER_PADDING_SIZE); + this->buf = calloc(1, VIDEOBUFSIZE + FF_INPUT_BUFFER_PADDING_SIZE); this->bufsize = VIDEOBUFSIZE; this->is_mpeg12 = 0; @@ -1555,11 +1727,15 @@ static video_decoder_t *ff_video_open_plugin (video_decoder_class_t *class_gen, this->pp_quality = 0; this->pp_context = NULL; this->pp_mode = NULL; - + this->mpeg_parser = NULL; - + this->dr1_frames = xine_list_new(); +#ifdef LOG + this->debug_fmt = -1; +#endif + return &this->video_decoder; } @@ -1579,8 +1755,8 @@ void *init_video_plugin (xine_t *xine, void *data) { ff_video_class_t *this; config_values_t *config; - - this = (ff_video_class_t *) xine_xmalloc (sizeof (ff_video_class_t)); + + this = calloc(1, sizeof (ff_video_class_t)); this->decoder_class.open_plugin = ff_video_open_plugin; this->decoder_class.get_identifier = ff_video_get_identifier; @@ -1589,12 +1765,12 @@ void *init_video_plugin (xine_t *xine, void *data) { this->xine = xine; pthread_once( &once_control, init_once_routine ); - + /* Configuration for post processing quality - default to mid (3) for the * moment */ config = xine->config; - - this->pp_quality = xine->config->register_range(config, "video.processing.ffmpeg_pp_quality", 3, + + this->pp_quality = xine->config->register_range(config, "video.processing.ffmpeg_pp_quality", 3, 0, PP_QUALITY_MAX, _("MPEG-4 postprocessing quality"), _("You can adjust the amount of post processing applied to MPEG-4 video.\n" @@ -1603,8 +1779,8 @@ void *init_video_plugin (xine_t *xine, void *data) { "too heavy post processing can actually make the image worse by blurring it " "too much."), 10, pp_quality_cb, this); - - this->thread_count = xine->config->register_num(config, "video.processing.ffmpeg_thread_count", 1, + + this->thread_count = xine->config->register_num(config, "video.processing.ffmpeg_thread_count", 1, _("FFmpeg video decoding thread count"), _("You can adjust the number of video decoding threads which FFmpeg may use.\n" "Higher values should speed up decoding but it depends on the codec used " @@ -1613,7 +1789,7 @@ void *init_video_plugin (xine_t *xine, void *data) { "A change of this setting will take effect with playing the next stream."), 10, thread_count_cb, this); - this->skip_loop_filter_enum = xine->config->register_enum(config, "video.processing.ffmpeg_skip_loop_filter", 0, + this->skip_loop_filter_enum = xine->config->register_enum(config, "video.processing.ffmpeg_skip_loop_filter", 0, (char **)skip_loop_filter_enum_names, _("Skip loop filter"), _("You can control for which frames the loop filter shall be skipped after " @@ -1624,7 +1800,7 @@ void *init_video_plugin (xine_t *xine, void *data) { "A change of this setting will take effect with playing the next stream."), 10, skip_loop_filter_enum_cb, this); - this->choose_speed_over_accuracy = xine->config->register_bool(config, "video.processing.ffmpeg_choose_speed_over_accuracy", 0, + this->choose_speed_over_accuracy = xine->config->register_bool(config, "video.processing.ffmpeg_choose_speed_over_accuracy", 0, _("Choose speed over specification compliance"), _("You may want to allow speed cheats which violate codec specification.\n" "Cheating may speed up decoding but can also lead to decoding artefacts.\n" @@ -1634,239 +1810,14 @@ void *init_video_plugin (xine_t *xine, void *data) { return this; } -static uint32_t supported_video_types[] = { - #ifdef CONFIG_MSMPEG4V1_DECODER - BUF_VIDEO_MSMPEG4_V1, - #endif - #ifdef CONFIG_MSMPEG4V2_DECODER - BUF_VIDEO_MSMPEG4_V2, - #endif - #ifdef CONFIG_MSMPEG4V3_DECODER - BUF_VIDEO_MSMPEG4_V3, - #endif - #ifdef CONFIG_WMV1_DECODER - BUF_VIDEO_WMV7, - #endif - #ifdef CONFIG_WMV2_DECODER - BUF_VIDEO_WMV8, - #endif - #ifdef CONFIG_WMV3_DECODER - BUF_VIDEO_WMV9, - #endif - #ifdef CONFIG_VC1_DECODER - BUF_VIDEO_VC1, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_MPEG4, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_XVID, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_DIVX5, - #endif - #ifdef CONFIG_MPEG4_DECODER - BUF_VIDEO_3IVX, - #endif - #ifdef CONFIG_MJPEG_DECODER - BUF_VIDEO_JPEG, - #endif - #ifdef CONFIG_MJPEG_DECODER - BUF_VIDEO_MJPEG, - #endif - #ifdef CONFIG_MJPEGB_DECODER - BUF_VIDEO_MJPEG_B, - #endif - #ifdef CONFIG_H263I_DECODER - BUF_VIDEO_I263, - #endif - #ifdef CONFIG_H263_DECODER - BUF_VIDEO_H263, - #endif - #ifdef CONFIG_RV10_DECODER - BUF_VIDEO_RV10, - #endif - #ifdef CONFIG_RV20_DECODER - BUF_VIDEO_RV20, - #endif - #ifdef CONFIG_INDEO3_DECODER - BUF_VIDEO_IV31, - #endif - #ifdef CONFIG_INDEO3_DECODER - BUF_VIDEO_IV32, - #endif - #ifdef CONFIG_SVQ1_DECODER - BUF_VIDEO_SORENSON_V1, - #endif - #ifdef CONFIG_SVQ3_DECODER - BUF_VIDEO_SORENSON_V3, - #endif - #ifdef CONFIG_DVVIDEO_DECODER - BUF_VIDEO_DV, - #endif - #ifdef CONFIG_HUFFYUV_DECODER - BUF_VIDEO_HUFFYUV, - #endif - #ifdef CONFIG_VP3_DECODER - BUF_VIDEO_VP31, - #endif - #ifdef CONFIG_VP5_DECODER - BUF_VIDEO_VP5, - #endif - #ifdef CONFIG_VP6_DECODER - BUF_VIDEO_VP6, - BUF_VIDEO_VP6F, - #endif - #ifdef CONFIG_4XM_DECODER - BUF_VIDEO_4XM, - #endif - #ifdef CONFIG_CINEPAK_DECODER - BUF_VIDEO_CINEPAK, - #endif - #ifdef CONFIG_MSVIDEO1_DECODER - BUF_VIDEO_MSVC, - #endif - #ifdef CONFIG_MSRLE_DECODER - BUF_VIDEO_MSRLE, - #endif - #ifdef CONFIG_RPZA_DECODER - BUF_VIDEO_RPZA, - #endif - #ifdef CONFIG_CYUV_DECODER - BUF_VIDEO_CYUV, - #endif - #ifdef CONFIG_ROQ_DECODER - BUF_VIDEO_ROQ, - #endif - #ifdef CONFIG_IDCIN_DECODER - BUF_VIDEO_IDCIN, - #endif - #ifdef CONFIG_XAN_WC3_DECODER - BUF_VIDEO_WC3, - #endif - #ifdef CONFIG_WS_VQA_DECODER - BUF_VIDEO_VQA, - #endif - #ifdef CONFIG_INTERPLAY_VIDEO_DECODER - BUF_VIDEO_INTERPLAY, - #endif - #ifdef CONFIG_FLIC_DECODER - BUF_VIDEO_FLI, - #endif - #ifdef CONFIG_8BPS_DECODER - BUF_VIDEO_8BPS, - #endif - #ifdef CONFIG_SMC_DECODER - BUF_VIDEO_SMC, - #endif - #ifdef CONFIG_TRUEMOTION1_DECODER - BUF_VIDEO_DUCKTM1, - #endif - #ifdef CONFIG_TRUEMOTION2_DECODER - BUF_VIDEO_DUCKTM2, - #endif - #ifdef CONFIG_VMDVIDEO_DECODER - BUF_VIDEO_VMD, - #endif - #ifdef CONFIG_ZLIB_DECODER - BUF_VIDEO_ZLIB, - #endif - #ifdef CONFIG_MSZH_DECODER - BUF_VIDEO_MSZH, - #endif - #ifdef CONFIG_ASV1_DECODER - BUF_VIDEO_ASV1, - #endif - #ifdef CONFIG_ASV2_DECODER - BUF_VIDEO_ASV2, - #endif - #ifdef CONFIG_VCR1_DECODER - BUF_VIDEO_ATIVCR1, - #endif - #ifdef CONFIG_FLV_DECODER - BUF_VIDEO_FLV1, - #endif - #ifdef CONFIG_QTRLE_DECODER - BUF_VIDEO_QTRLE, - #endif - #ifdef CONFIG_H264_DECODER - BUF_VIDEO_H264, - #endif - #ifdef CONFIG_H261_DECODER - BUF_VIDEO_H261, - #endif - #ifdef CONFIG_AASC_DECODER - BUF_VIDEO_AASC, - #endif - #ifdef CONFIG_LOCO_DECODER - BUF_VIDEO_LOCO, - #endif - #ifdef CONFIG_QDRAW_DECODER - BUF_VIDEO_QDRW, - #endif - #ifdef CONFIG_QPEG_DECODER - BUF_VIDEO_QPEG, - #endif - #ifdef CONFIG_TSCC_DECODER - BUF_VIDEO_TSCC, - #endif - #ifdef CONFIG_ULTI_DECODER - BUF_VIDEO_ULTI, - #endif - #ifdef CONFIG_WNV1_DECODER - BUF_VIDEO_WNV1, - #endif - #ifdef CONFIG_VIXL_DECODER - BUF_VIDEO_XL, - #endif - #ifdef CONFIG_INDEO2_DECODER - BUF_VIDEO_RT21, - #endif - #ifdef CONFIG_FRAPS_DECODER - BUF_VIDEO_FPS1, - #endif - #ifdef CONFIG_MPEG1VIDEO_DECODER - BUF_VIDEO_MPEG, - #endif - #ifdef CONFIG_CSCD_DECODER - BUF_VIDEO_CSCD, - #endif - #ifdef CONFIG_AVS_DECODER - BUF_VIDEO_AVS, - #endif - #ifdef CONFIG_MMVIDEO_DECODER - BUF_VIDEO_ALGMM, - #endif - #ifdef CONFIG_ZMBV_DECODER - BUF_VIDEO_ZMBV, - #endif - #ifdef CONFIG_SMACKVIDEO_DECODER - BUF_VIDEO_SMACKER, - #endif - #ifdef CONFIG_NUV_DECODER - BUF_VIDEO_NUV, - #endif - #ifdef CONFIG_KMVC_DECODER - BUF_VIDEO_KMVC, - #endif - #ifdef CONFIG_FLASHSV_DECODER - BUF_VIDEO_FLASHSV, - #endif - #ifdef CONFIG_CAVS_DECODER - BUF_VIDEO_CAVS, - #endif - BUF_VIDEO_THEORA_RAW, - 0 -}; - -static uint32_t wmv8_video_types[] = { +static uint32_t wmv8_video_types[] = { BUF_VIDEO_WMV8, - 0 + 0 }; -static uint32_t wmv9_video_types[] = { +static uint32_t wmv9_video_types[] = { BUF_VIDEO_WMV9, - 0 + 0 }; decoder_info_t dec_info_ffmpeg_video = { diff --git a/src/libffmpeg/ffmpeg_decoder.c b/src/combined/ffmpeg/ffmpeg_decoder.c index d0175184f..6d0bfa432 100644 --- a/src/libffmpeg/ffmpeg_decoder.c +++ b/src/combined/ffmpeg/ffmpeg_decoder.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2001-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -22,7 +22,7 @@ #ifdef HAVE_CONFIG_H #include "config.h" -#include "ffmpeg_config.h" +#include "../../libffmpeg/ffmpeg_config.h" #endif #include "xine_internal.h" @@ -317,7 +317,7 @@ void init_once_routine(void) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER | PLUGIN_MUST_PRELOAD, 18, "ffmpegvideo", XINE_VERSION_CODE, &dec_info_ffmpeg_video, init_video_plugin }, { PLUGIN_VIDEO_DECODER, 18, "ffmpeg-wmv8", XINE_VERSION_CODE, &dec_info_ffmpeg_wmv8, init_video_plugin }, { PLUGIN_VIDEO_DECODER, 18, "ffmpeg-wmv9", XINE_VERSION_CODE, &dec_info_ffmpeg_wmv9, init_video_plugin }, diff --git a/src/libffmpeg/ffmpeg_decoder.h b/src/combined/ffmpeg/ffmpeg_decoder.h index 14788cf29..0aeb71271 100644 --- a/src/libffmpeg/ffmpeg_decoder.h +++ b/src/combined/ffmpeg/ffmpeg_decoder.h @@ -1,23 +1,23 @@ /* * Copyright (C) 2001-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + #ifndef HAVE_XINE_DECODER_H #define HAVE_XINE_DECODER_H @@ -25,10 +25,16 @@ #include "config.h" #endif -#ifdef HAVE_FFMPEG +#ifdef HAVE_FFMPEG_AVUTIL_H # include <avcodec.h> +#elif defined HAVE_FFMPEG +# include <libavcodec/avcodec.h> #else -# include "libavcodec/avcodec.h" +# include "../../libffmpeg/libavcodec/avcodec.h" +#endif + +#if LIBAVCODEC_VERSION_MAJOR > 51 +#define bits_per_sample bits_per_coded_sample #endif typedef struct ff_codec_s { diff --git a/src/libffmpeg/ffmpeg_encoder.c b/src/combined/ffmpeg/ffmpeg_encoder.c index c8a450b0d..d41023675 100644 --- a/src/libffmpeg/ffmpeg_encoder.c +++ b/src/combined/ffmpeg/ffmpeg_encoder.c @@ -1,23 +1,23 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + /* mpeg encoders for the dxr3 video out plugin. */ #ifdef HAVE_CONFIG_H @@ -38,13 +38,15 @@ #include "video_out_dxr3.h" -#ifdef HAVE_FFMPEG +#ifdef HAVE_FFMPEG_AVUTIL_H # include <avcodec.h> +#elif defined HAVE_FFMPEG +# include <libavcodec/avcodec.h> #else -# include "libavcodec/avcodec.h" +# include "../../libffmpeg/libavcodec/avcodec.h" #endif -/* buffer size for encoded mpeg1 stream; will hold one intra frame +/* buffer size for encoded mpeg1 stream; will hold one intra frame * at 640x480 typical sizes are <50 kB. 512 kB should be plenty */ #define DEFAULT_BUFFER_SIZE 512*1024 @@ -74,9 +76,9 @@ int dxr3_encoder_init(dxr3_driver_t *drv) lavc_data_t* this; avcodec_init(); - avcodec_register_all(); + avcodec_register_all(); lprintf("lavc init , version %x\n", avcodec_version()); - this = xine_xmalloc(sizeof(lavc_data_t)); + this = calloc(1, sizeof(lavc_data_t)); if (!this) return 0; this->encoder_data.type = ENC_LAVC; @@ -85,7 +87,7 @@ int dxr3_encoder_init(dxr3_driver_t *drv) this->encoder_data.on_display_frame = lavc_on_display_frame; this->encoder_data.on_unneeded = lavc_on_unneeded; this->context = 0; - + drv->enc = &this->encoder_data; return 1; } @@ -98,7 +100,7 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) lavc_data_t *this = (lavc_data_t *)drv->enc; AVCodec *codec; unsigned char use_quantizer; - + if (this->context) { avcodec_close(this->context); free(this->context); @@ -106,27 +108,27 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) this->context = NULL; this->picture = NULL; } - + /* if YUY2 and dimensions changed, we need to re-allocate the * internal YV12 buffer */ if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { int image_size = frame->vo_frame.pitches[0] * frame->oheight; - this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, + this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, (void *)&this->buf); - this->out[1] = this->out[0] + image_size; - this->out[2] = this->out[1] + image_size/4; + this->out[1] = this->out[0] + image_size; + this->out[2] = this->out[1] + image_size/4; /* fill with black (yuv 16,128,128) */ memset(this->out[0], 16, image_size); memset(this->out[1], 128, image_size/4); memset(this->out[2], 128, image_size/4); - lprintf("Using YUY2->YV12 conversion\n"); + lprintf("Using YUY2->YV12 conversion\n"); } - + /* resolution must be a multiple of two */ if ((frame->vo_frame.pitches[0] % 2 != 0) || (frame->oheight % 2 != 0)) { - xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, "dxr3_mpeg_encoder: lavc only handles video dimensions which are multiples of 2\n"); return 0; } @@ -148,7 +150,7 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) xprintf(drv->class->xine, XINE_VERBOSITY_LOG, "dxr3_mpeg_encoder: Couldn't start the ffmpeg library\n"); return 0; - } + } this->picture = avcodec_alloc_frame(); if (!this->picture) { xprintf(drv->class->xine, XINE_VERBOSITY_LOG, @@ -158,7 +160,7 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) /* mpeg1 encoder only support YUV420P */ this->context->pix_fmt = PIX_FMT_YUVJ420P; - + /* put sample parameters */ this->context->bit_rate = drv->class->xine->config->register_range(drv->class->xine->config, "dxr3.encoding.lavc_bitrate", 10000, 1000, 20000, @@ -167,7 +169,7 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) "Higher values will increase quality and CPU usage.\n" "This setting is only considered, when constant quality mode is disabled."), 10, NULL, NULL); this->context->bit_rate *= 1000; /* config in kbit/s, libavcodec wants bit/s */ - + use_quantizer = drv->class->xine->config->register_bool(drv->class->xine->config, "dxr3.encoding.lavc_quantizer", 1, _("constant quality mode"), @@ -175,18 +177,18 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) "compressing the images based on their complexity. When disabled, libavcodec " "will use constant bitrate mode."), 10, NULL, NULL); - if (use_quantizer) { + if (use_quantizer) { this->context->qmin = drv->class->xine->config->register_range(drv->class->xine->config, "dxr3.encoding.lavc_qmin", 1, 1, 10, _("minimum compression"), _("The minimum compression to apply to an image in constant quality mode."), 10, NULL, NULL); - + this->context->qmax = drv->class->xine->config->register_range(drv->class->xine->config, "dxr3.encoding.lavc_qmax", 2, 1, 20, _("maximum quantizer"), _("The maximum compression to apply to an image in constant quality mode."), - 10, NULL, NULL); + 10, NULL, NULL); } lprintf("lavc -> bitrate %d \n", this->context->bit_rate); @@ -196,7 +198,7 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) this->context->gop_size = 0; /*intra frames only */ this->context->me_method = ME_ZERO; /*motion estimation type*/ - + this->context->time_base.den = 90000; if (frame->vo_frame.duration > 90000 / 24) this->context->time_base.num = 90000 / 24; @@ -207,14 +209,14 @@ static int lavc_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) /* ffmpeg can complain about illegal framerates, but since this seems no * problem for the DXR3, we just tell ffmpeg to be more lax with */ this->context->strict_std_compliance = -1; - + /* open avcodec */ if (avcodec_open(this->context, codec) < 0) { xprintf(drv->class->xine, XINE_VERBOSITY_LOG, "dxr3_mpeg_encoder: could not open codec\n"); return 0; } lprintf("dxr3_mpeg_encoder: lavc MPEG1 codec opened.\n"); - + if (!this->ffmpeg_buffer) this->ffmpeg_buffer = (unsigned char *)malloc(DEFAULT_BUFFER_SIZE); /* why allocate more than needed ?! */ if (!this->ffmpeg_buffer) { @@ -231,7 +233,7 @@ static int lavc_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) int size; lavc_data_t* this = (lavc_data_t *)drv->enc; ssize_t written; - + if (frame->vo_frame.bad_frame) return 1; /* ignore old frames */ if ((frame->vo_frame.pitches[0] != this->context->width) || (frame->oheight != this->context->height)) { @@ -284,7 +286,7 @@ static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_ { int i, j, w2; uint8_t *yuy2; - + if (frame->vo_frame.bad_frame) return 1; if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { @@ -320,7 +322,7 @@ static int lavc_prepare_frame(lavc_data_t *this, dxr3_driver_t *drv, dxr3_frame_ this->picture->data[1] = this->out[1]; this->picture->data[2] = this->out[2]; } - else { /* YV12 **/ + else { /* YV12 **/ this->picture->data[0] = frame->real_base[0]; this->picture->data[1] = frame->real_base[1]; this->picture->data[2] = frame->real_base[2]; diff --git a/src/combined/ffmpeg/mkcodeclist.pl b/src/combined/ffmpeg/mkcodeclist.pl new file mode 100755 index 000000000..b4a10921a --- /dev/null +++ b/src/combined/ffmpeg/mkcodeclist.pl @@ -0,0 +1,95 @@ +#! /usr/bin/perl -w + +# Make codec lists for #inclusion by ff_*_decoder.c. +# Parameters: +# list of ffmpeg CODEC_ID_* (pre-processed, one per line) +# list of codecs recognised by xine-lib (see list for details) +# output file name, or "-" to generate a report on unhandled codecs + +my ($ffmpeg, $xine, $out) = @ARGV; +my $line; + +# Read in the ffmpeg codec IDs +my %codecs; +open LIST, "< $ffmpeg" or die $!; +$line = <LIST>; +while (defined $line) { + chomp $line; + $line =~ s/^CODEC_ID_//o; + $codecs{$line} = 0; + $line = <LIST>; +} +close LIST or die $!; + +# Read in the xine-lib codec IDs +my %config; +my @known; +my $type = 'audio'; # default type +my $Type = 'AUDIO'; +my ($a, $f, $t); +open LIST, "< $xine" or die $!; +while (defined ($line = <LIST>)) { + next if substr ($line, 0, 1) eq '#' or $line =~ /^\s*$/o; + chomp $line; + if (substr ($line, 0, 5) eq 'type=') { + # codec type; "FOO" in "BUF_FOO_BAR" + $type = substr ($line, 5); + $type =~ tr/A-Z/a-z/; + $Type = $type; + $Type =~ tr/a-z/A-Z/; + } elsif (substr ($line, 0, 7) eq 'config=') { + # "#ifdef CONFIG_FOO_DECODER" mappings + ($a, $f, $t) = split (/=/, $line, 3); + $config{$f} = $t; + } else { + # codec details + push @known, [split (/\s+/, $line, 3)]; + } +} +close LIST or die $!; + +# Look through the mappings. +# Mark what we can handle and report on what the installed ffmpeg can't +foreach $line (@known) { + if (defined $codecs{$line->[1]}) { + ++$codecs{$line->[1]}; + } else { + print "Ignored $line->[0] = $line->[1]\n"; + } +} + +my $w = ($out ne '-'); + +if ($w) { + # Write the C source code for the codec lists + open LIST, "> $out" or die $!; + print LIST "static const ff_codec_t ff_${type}_lookup[] = {\n" or die $!; + foreach $line (@known) { + next if $line->[0] eq '!'; + next unless defined $codecs{$line->[1]}; + print LIST " { BUF_${Type}_$line->[0], CODEC_ID_$line->[1], \"$line->[2] (ffmpeg)\" },\n" or die $!; + } + print LIST "};\n\nstatic uint32_t supported_${type}_types[] = {\n" or die $!; + foreach $line (@known) { + next if $line->[0] eq '!'; + next unless defined $codecs{$line->[1]}; + $a = $line->[1]; + $a = $config{$a} if defined $config{$a}; + if ($a eq '') { + print LIST " BUF_${Type}_$line->[0],\n" or die $!; + } else { + print LIST " #ifdef CONFIG_${a}_DECODER\n BUF_${Type}_$line->[0],\n #endif\n" or die $!; + } + } + print LIST " 0,\n};\n" or die $!; + close LIST or die $!; +} +else { + # Report on ffmpeg codecs which we don't handle + print "Unhandled $type codecs:\n"; + foreach $line (sort keys %codecs) { + print " $line\n" if $codecs{$line} == 0; + } +} + +exit 0; diff --git a/src/combined/ffmpeg/xine_audio.list b/src/combined/ffmpeg/xine_audio.list new file mode 100644 index 000000000..4b6932474 --- /dev/null +++ b/src/combined/ffmpeg/xine_audio.list @@ -0,0 +1,55 @@ +type=audio +config=MP3ADU= + +# xine-lib BUF_AUDIO_ ffmpeg CODEC_ID_ description or comment +# ("!"=ignore) (quote any "s) + +WMAV1 WMAV1 MS Windows Media Audio 1 +WMAV2 WMAV2 MS Windows Media Audio 2 +14_4 RA_144 Real 14.4 +28_8 RA_288 Real 28.8 +MPEG MP3 MP3 +MP3ADU MP3ADU MPEG-3 adu +MSADPCM ADPCM_MS MS ADPCM +QTIMAADPCM ADPCM_IMA_QT QT IMA ADPCM +MSIMAADPCM ADPCM_IMA_WAV MS IMA ADPCM +DK3ADPCM ADPCM_IMA_DK3 Duck DK3 ADPCM +DK4ADPCM ADPCM_IMA_DK4 Duck DK4 ADPCM +VQA_IMA ADPCM_IMA_WS Westwood Studios IMA +SMJPEG_IMA ADPCM_IMA_SMJPEG SMJPEG IMA +XA_ADPCM ADPCM_XA CD-ROM/XA ADPCM +4X_ADPCM ADPCM_4XM 4X ADPCM +EA_ADPCM ADPCM_EA Electronic Arts ADPCM +MULAW PCM_MULAW mu-law logarithmic PCM +ALAW PCM_ALAW A-law logarithmic PCM +ROQ ROQ_DPCM RoQ DPCM +INTERPLAY INTERPLAY_DPCM Interplay DPCM +MAC3 MACE3 MACE 3:1 +MAC6 MACE6 MACE 6:1 +XAN_DPCM XAN_DPCM Origin Xan DPCM +VMD VMDAUDIO Sierra VMD Audio +FLAC FLAC FLAC +SHORTEN SHORTEN Shorten +ALAC ALAC ALAC +QDESIGN2 QDM2 QDesign +COOK COOK RealAudio Cooker +TRUESPEECH TRUESPEECH TrueSpeech +TTA TTA True Audio Lossless +SMACKER SMACKAUDIO Smacker +FLVADPCM ADPCM_SWF Flash ADPCM +WAVPACK WAVPACK WavPack +AMR_NB AMR_NB AMR narrow band +AMR_WB AMR_WB AMR wide band + +# disabled codecs (ref. configure.ac) +! AAC +! AC3 +! ADPCM_ADX +! ADPCM_G726 +! DSICINAUDIO +! DVAUDIO +! IMC +! MP3ON4 +! SONIC +! SONIC_LS +! VORBIS diff --git a/src/combined/ffmpeg/xine_video.list b/src/combined/ffmpeg/xine_video.list new file mode 100644 index 000000000..a3c961d13 --- /dev/null +++ b/src/combined/ffmpeg/xine_video.list @@ -0,0 +1,109 @@ +type=video +config=VP6F=VP6 +config=FLV1=FLV +config=THEORA= + +# xine-lib BUF_VIDEO_ ffmpeg CODEC_ID_ description or comment +# ("!"=ignore) (quote any "s) + +MSMPEG4_V1 MSMPEG4V1 Microsoft MPEG-4 v1 +MSMPEG4_V2 MSMPEG4V2 Microsoft MPEG-4 v2 +MSMPEG4_V3 MSMPEG4V3 Microsoft MPEG-4 v3 +WMV7 WMV1 MS Windows Media Video 7 +WMV8 WMV2 MS Windows Media Video 8 +WMV9 WMV3 MS Windows Media Video 9 +VC1 VC1 MS Windows Media Video VC-1 +MPEG4 MPEG4 ISO MPEG-4 +XVID MPEG4 ISO MPEG-4 (XviD) +DIVX5 MPEG4 ISO MPEG-4 (DivX5) +3IVX MPEG4 ISO MPEG-4 (3ivx) +JPEG MJPEG Motion JPEG +MJPEG MJPEG Motion JPEG +MJPEG_B MJPEGB Motion JPEG B +I263 H263I ITU H.263 +H263 H263 H.263 +RV10 RV10 Real Video 1.0 +RV20 RV20 Real Video 2.0 +IV31 INDEO3 Indeo Video 3.1 +IV32 INDEO3 Indeo Video 3.2 +SORENSON_V1 SVQ1 Sorenson Video 1 +SORENSON_V3 SVQ3 Sorenson Video 3 +DV DVVIDEO DV +HUFFYUV HUFFYUV HuffYUV +VP31 VP3 On2 VP3.1 +VP5 VP5 On2 VP5 +VP6 VP6 On2 VP6 +VP6F VP6F On2 VP6 +4XM 4XM 4X Video +CINEPAK CINEPAK Cinepak +MSVC MSVIDEO1 Microsoft Video 1 +MSRLE MSRLE Microsoft RLE +RPZA RPZA Apple Quicktime Video/RPZA +CYUV CYUV Creative YUV +ROQ ROQ Id Software RoQ +IDCIN IDCIN Id Software CIN +WC3 XAN_WC3 Xan +VQA WS_VQA Westwood Studios VQA +INTERPLAY INTERPLAY_VIDEO Interplay MVE +FLI FLIC FLIC Video +8BPS 8BPS Planar RGB +SMC SMC Apple Quicktime Graphics/SMC +DUCKTM1 TRUEMOTION1 Duck TrueMotion v1 +DUCKTM2 TRUEMOTION2 Duck TrueMotion v2 +VMD VMDVIDEO Sierra VMD Video +ZLIB ZLIB ZLIB Video +MSZH MSZH MSZH Video +ASV1 ASV1 ASV v1 Video +ASV2 ASV2 ASV v2 Video +ATIVCR1 VCR1 ATI VCR-1 +FLV1 FLV1 Flash Video +QTRLE QTRLE Apple Quicktime Animation/RLE +H264 H264 H.264/AVC +H261 H261 H.261 +AASC AASC Autodesk Video +LOCO LOCO LOCO +QDRW QDRAW QuickDraw +QPEG QPEG Q-Team QPEG +TSCC TSCC TechSmith Video +ULTI ULTI IBM UltiMotion +WNV1 WNV1 Winnow Video +XL VIXL Miro/Pinnacle VideoXL +RT21 INDEO2 Indeo/RealTime 2 +FPS1 FRAPS Fraps +MPEG MPEG1VIDEO MPEG 1/2 +CSCD CSCD CamStudio +AVS AVS AVS +ALGMM MMVIDEO American Laser Games MM +ZMBV ZMBV Zip Motion Blocks Video +SMACKER SMACKVIDEO Smacker +NUV NUV NuppelVideo +KMVC KMVC Karl Morton's Video Codec +FLASHSV FLASHSV Flash Screen Video +CAVS CAVS Chinese AVS +VMNC VMNC VMware Screen Codec +THEORA_RAW THEORA Theora +SNOW SNOW Snow + +# disabled codecs (ref. configure.ac) +! BMP +! CLJR +! DSICINVIDEO +! FFV1 +! FFVHUFF +! GIF +! H263P +! JPEGLS +! LJPEG +! MDEC +! PAM +! PBM +! PGM +! PGMYUV +! PNG +! PPM +! RAWVIDEO +! SP5X +! TARGA +! TIERTEXSEQVIDEO +! TIFF +! XVID ⇒ MPEG4 diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index ffbfa0a8d..027f6750f 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(VISIBILITY_FLAG) @@ -8,7 +9,7 @@ ogg_module = xineplug_dmx_ogg.la endif if BUILD_ASF -asf_module = xineplug_dmx_asf.la +asf_module = xineplug_dmx_asf.la endif if BUILD_NOSEFART @@ -48,7 +49,7 @@ xineplug_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module) xineplug_dmx_nsv.la \ xineplug_dmx_matroska.la \ xineplug_dmx_iff.la \ - xineplug_dmx_flv.la + xineplug_dmx_flv.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c xineplug_dmx_ogg_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(LTLIBINTL) @@ -61,7 +62,7 @@ xineplug_dmx_mpeg_block_la_SOURCES = demux_mpeg_block.c xineplug_dmx_mpeg_block_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c -xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB) +xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB) @@ -70,10 +71,10 @@ xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c -xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB) +xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_qt_la_SOURCES = demux_qt.c -xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) +xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(LTLIBINTL) xineplug_dmx_qt_la_CPPFLAGS = $(ZLIB_CPPFLAGS) xineplug_dmx_asf_la_SOURCES = demux_asf.c asfheader.c @@ -129,8 +130,8 @@ xineplug_dmx_image_la_LIBADD = $(XINE_LIB) xineplug_dmx_nsv_la_SOURCES = demux_nsv.c xineplug_dmx_nsv_la_LIBADD = $(XINE_LIB) -xineplug_dmx_matroska_la_SOURCES = demux_matroska.c ebml.c -xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) +xineplug_dmx_matroska_la_SOURCES = demux_matroska.c demux_matroska-chapters.c ebml.c +xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(LTLIBINTL) xineplug_dmx_matroska_la_CPPFLAGS = $(ZLIB_CPPFLAGS) xineplug_dmx_matroska_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing @@ -141,4 +142,4 @@ xineplug_dmx_flv_la_SOURCES = demux_flv.c xineplug_dmx_flv_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineinclude_HEADERS = demux.h -noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h iff.h flacutils.h +noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h demux_matroska.h iff.h flacutils.h real_common.h diff --git a/src/demuxers/asfheader.c b/src/demuxers/asfheader.c index ea92f878b..e9a36fc29 100644 --- a/src/demuxers/asfheader.c +++ b/src/demuxers/asfheader.c @@ -142,9 +142,9 @@ static uint8_t *asf_reader_get_bytes(asf_reader_t *reader, size_t size) { static char *asf_reader_get_string(asf_reader_t *reader, size_t size, iconv_t cd) {
char *inbuf, *outbuf;
size_t inbytesleft, outbytesleft;
- char scratch[2048];
+ char scratch[2048];
- if ((reader->size - reader->pos) < size)
+ if ((size == 0) ||((reader->size - reader->pos) < size))
return NULL;
inbuf = (char *)reader->buffer + reader->pos;
@@ -399,7 +399,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin if (asf_stream_extension->stream_name_count) {
asf_stream_extension->stream_names = malloc (asf_stream_extension->stream_name_count * sizeof(void*));
for (i = 0; i < asf_stream_extension->stream_name_count; i++) {
- uint16_t lang_index, length;
+ uint16_t lang_index, length = 0;
asf_reader_get_16(&reader, &lang_index);
asf_reader_get_16(&reader, &length);
asf_stream_extension->stream_names[i] = (char*)asf_reader_get_bytes(&reader, length); /* store them */
@@ -411,7 +411,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin for (i = 0; i < asf_stream_extension->payload_extension_system_count; i++) {
GUID guid;
uint16_t data_size;
- uint32_t length;
+ uint32_t length = 0;
asf_reader_get_guid(&reader, &guid);
asf_reader_get_16(&reader, &data_size);
asf_reader_get_32(&reader, &length);
@@ -427,7 +427,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin /* embeded stream properties */
if (asf_reader_get_size(&reader) >= 24) {
GUID guid;
- uint64_t object_length;
+ uint64_t object_length = 0;
asf_reader_get_guid(&reader, &guid);
asf_reader_get_64(&reader, &object_length);
@@ -490,8 +490,8 @@ static int asf_header_parse_stream_bitrate_properties(asf_header_t *header_pub, lprintf (" bitrate count: %d\n", bitrate_count);
for(i = 0; i < bitrate_count; i++) {
- uint16_t flags;
- uint32_t bitrate;
+ uint16_t flags = 0;
+ uint32_t bitrate = 0;
int stream_number;
uint8_t *bitrate_pointer;
@@ -511,6 +511,61 @@ static int asf_header_parse_stream_bitrate_properties(asf_header_t *header_pub, return 1;
}
+static int asf_header_parse_metadata(asf_header_t *header_pub, uint8_t *buffer, int buffer_len)
+{
+ asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
+ asf_reader_t reader;
+ uint16_t i, records_count;
+ iconv_t iconv_cd;
+
+ if (buffer_len < 2)
+ return 0;
+
+ if ((iconv_cd = iconv_open ("UTF-8", "UCS-2LE")) == (iconv_t)-1)
+ return 0;
+
+ asf_reader_init(&reader, buffer, buffer_len);
+ asf_reader_get_16(&reader, &records_count);
+
+ for (i = 0; i < records_count; i++)
+ {
+ uint16_t index, stream, name_len = 0, data_type;
+ uint32_t data_len = 0;
+ int stream_id;
+
+ asf_reader_get_16 (&reader, &index);
+ asf_reader_get_16 (&reader, &stream);
+ stream &= 0x7f;
+ asf_reader_get_16 (&reader, &name_len);
+ asf_reader_get_16 (&reader, &data_type);
+ asf_reader_get_32 (&reader, &data_len);
+
+ stream_id = asf_header_get_stream_id (&header->pub, stream);
+
+ if (data_len >= 4)
+ {
+ char *name = asf_reader_get_string (&reader, name_len, iconv_cd);
+ if (name && !strcmp (name, "AspectRatioX"))
+ {
+ asf_reader_get_32 (&reader, &header->pub.aspect_ratios[stream_id].x);
+ data_len -= 4;
+ }
+ else if (name && !strcmp (name, "AspectRatioY"))
+ {
+ asf_reader_get_32 (&reader, &header->pub.aspect_ratios[stream_id].y);
+ data_len -= 4;
+ }
+ free (name);
+ asf_reader_skip (&reader, data_len);
+ }
+ else
+ asf_reader_skip (&reader, data_len + name_len);
+ }
+
+ iconv_close (iconv_cd);
+ return 1;
+}
+
static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buffer, int buffer_len) {
asf_reader_t reader;
@@ -533,7 +588,7 @@ static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buff GUID guid;
int object_id;
- uint64_t object_length, object_data_length;
+ uint64_t object_length = 0, object_data_length;
if (asf_reader_get_size(&reader) < 24) {
printf("invalid buffer size\n");
@@ -549,12 +604,14 @@ static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buff case GUID_EXTENDED_STREAM_PROPERTIES:
asf_header_parse_stream_extended_properties(header, asf_reader_get_buffer(&reader), object_data_length);
break;
+ case GUID_METADATA:
+ asf_header_parse_metadata(header, asf_reader_get_buffer(&reader), object_data_length);
+ break;
case GUID_ADVANCED_MUTUAL_EXCLUSION:
case GUID_GROUP_MUTUAL_EXCLUSION:
case GUID_STREAM_PRIORITIZATION:
case GUID_BANDWIDTH_SHARING:
case GUID_LANGUAGE_LIST:
- case GUID_METADATA:
case GUID_METADATA_LIBRARY:
case GUID_INDEX_PARAMETERS:
case GUID_MEDIA_OBJECT_INDEX_PARAMETERS:
@@ -581,10 +638,9 @@ static int asf_header_parse_content_description(asf_header_t *header_pub, uint8_ if (buffer_len < 10)
return 0;
- content = malloc(sizeof(asf_content_t));
+ content = calloc(1, sizeof(asf_content_t));
if (!content)
return 0;
- memset(content, 0, sizeof(asf_content_t));
asf_reader_init(&reader, buffer, buffer_len);
asf_reader_get_16(&reader, &title_length);
@@ -599,6 +655,12 @@ static int asf_header_parse_content_description(asf_header_t *header_pub, uint8_ content->description = asf_reader_get_string(&reader, description_length, header->iconv_cd);
content->rating = asf_reader_get_string(&reader, rating_length, header->iconv_cd);
+ lprintf("title: %d chars: \"%s\"\n", title_length, content->title);
+ lprintf("author: %d chars: \"%s\"\n", author_length, content->author);
+ lprintf("copyright: %d chars: \"%s\"\n", copyright_length, content->copyright);
+ lprintf("description: %d chars: \"%s\"\n", description_length, content->description);
+ lprintf("rating: %d chars: \"%s\"\n", rating_length, content->rating);
+
header->pub.content = content;
return 1;
}
@@ -611,10 +673,9 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) { uint32_t object_count;
uint16_t junk;
- asf_header = malloc(sizeof(asf_header_internal_t));
+ asf_header = calloc(1, sizeof(asf_header_internal_t));
if (!asf_header)
return NULL;
- memset(asf_header, 0, sizeof(asf_header_internal_t));
lprintf("parsing_asf_header\n");
if (buffer_len < 6) {
@@ -638,7 +699,7 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) { GUID guid;
int object_id;
- uint64_t object_length, object_data_length;
+ uint64_t object_length = 0, object_data_length;
if (asf_reader_get_size(&reader) < 24) {
printf("invalid buffer size\n");
@@ -697,10 +758,9 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) { }
if (!asf_header->pub.content) {
lprintf("no content object present\n");
- asf_header->pub.content = malloc(sizeof(asf_content_t));
+ asf_header->pub.content = calloc(1, sizeof(asf_content_t));
if (!asf_header->pub.content)
goto exit_error;
- memset(asf_header->pub.content, 0, sizeof(asf_content_t));
}
return &asf_header->pub;
diff --git a/src/demuxers/asfheader.h b/src/demuxers/asfheader.h index 4bd13ab3f..265f0e643 100644 --- a/src/demuxers/asfheader.h +++ b/src/demuxers/asfheader.h @@ -320,6 +320,7 @@ struct asf_header_s { asf_stream_t *streams[ASF_MAX_NUM_STREAMS];
asf_stream_extension_t *stream_extensions[ASF_MAX_NUM_STREAMS];
uint32_t bitrates[ASF_MAX_NUM_STREAMS];
+ struct { uint32_t x, y; } aspect_ratios[ASF_MAX_NUM_STREAMS];
};
struct asf_file_s {
@@ -389,7 +390,7 @@ struct asf_stream_extension_s { int asf_find_object_id (GUID *g);
void asf_get_guid (uint8_t *buffer, GUID *value);
-asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len);
+asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) XINE_MALLOC;
void asf_header_choose_streams (asf_header_t *header, uint32_t bandwidth,
int *video_id, int *audio_id);
void asf_header_disable_streams (asf_header_t *header,
diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h index 81907cfcf..a824730ea 100644 --- a/src/demuxers/demux.h +++ b/src/demuxers/demux.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -63,7 +63,7 @@ struct demux_class_s { */ const char* (*get_identifier) (demux_class_t *this); - + /* * return MIME types supported for this plugin */ @@ -73,7 +73,7 @@ struct demux_class_s { /* * return ' ' seperated list of file extensions this * demuxer is likely to handle - * (will be used to filter media files in + * (will be used to filter media files in * file selection dialogs) */ @@ -100,7 +100,7 @@ struct demux_plugin_s { void (*send_headers) (demux_plugin_t *this); /* - * ask demux to seek + * ask demux to seek * * for seekable streams, a start position can be specified * @@ -118,11 +118,11 @@ struct demux_plugin_s { * starting the demuxer) */ - int (*seek) (demux_plugin_t *this, + int (*seek) (demux_plugin_t *this, off_t start_pos, int start_time, int playing ); /* - * send a chunk of data down to decoder fifos + * send a chunk of data down to decoder fifos * * the meaning of "chunk" is specific to every demux, usually * it involves parsing one unit of data from stream. @@ -132,15 +132,15 @@ struct demux_plugin_s { */ int (*send_chunk) (demux_plugin_t *this); - + /* - * free resources + * free resources */ void (*dispose) (demux_plugin_t *this) ; /* - * returns DEMUX_OK or DEMUX_FINISHED + * returns DEMUX_OK or DEMUX_FINISHED */ int (*get_status) (demux_plugin_t *this) ; @@ -157,12 +157,12 @@ struct demux_plugin_s { */ uint32_t (*get_capabilities) (demux_plugin_t *this); - + /* * request optional data from input plugin. */ int (*get_optional_data) (demux_plugin_t *this, void *data, int data_type); - + /* * "backwards" link to plugin class */ @@ -181,8 +181,8 @@ struct demux_plugin_s { /* * DEMUX_CAP_AUDIOLANG: * DEMUX_CAP_SPULANG: - * demux plugin knows something about audio/spu languages, - * e.g. knows that audio stream #0 is english, + * demux plugin knows something about audio/spu languages, + * e.g. knows that audio stream #0 is english, * audio stream #1 is german, ... Same bits as INPUT * capabilities . */ diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c index 24aee1ac4..a58cf0f22 100644 --- a/src/demuxers/demux_4xm.c +++ b/src/demuxers/demux_4xm.c @@ -125,25 +125,15 @@ static float get_le_float(unsigned char *buffer) * This function is called from the _open() function of this demuxer. * It returns 1 if 4xm file was opened successfully. */ static int open_fourxm_file(demux_fourxm_t *fourxm) { - unsigned char preview[12]; - int header_size; - unsigned char *header; - int i; - unsigned int fourcc_tag; - unsigned int size; - unsigned int current_track; - unsigned int audio_type; - unsigned int total_frames; - float fps; /* the file signature will be in the first 12 bytes */ if (_x_demux_read_header(fourxm->input, preview, 12) != 12) return 0; /* check for the signature tags */ - if ((_X_LE_32(&preview[0]) != RIFF_TAG) || - (_X_LE_32(&preview[8]) != _4XMV_TAG)) + if (!_x_is_fourcc(&preview[0], "RIFF") || + !_x_is_fourcc(&preview[8], "4XMV")) return 0; /* file is qualified; skip over the header bytes in the stream */ @@ -152,14 +142,14 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { /* fetch the LIST-HEAD header */ if (fourxm->input->read(fourxm->input, preview, 12) != 12) return 0; - if ((_X_LE_32(&preview[0]) != LIST_TAG) || - (_X_LE_32(&preview[8]) != HEAD_TAG)) + if (!_x_is_fourcc(&preview[0], "LIST") || + !_x_is_fourcc(&preview[8], "HEAD") ) return 0; /* read the whole header */ - header_size = _X_LE_32(&preview[4]) - 4; - header = xine_xmalloc(header_size); - if (fourxm->input->read(fourxm->input, header, header_size) != header_size) { + const uint32_t header_size = _X_LE_32(&preview[4]) - 4; + uint8_t *const header = malloc(header_size); + if (!header || fourxm->input->read(fourxm->input, header, header_size) != header_size) { free(header); return 0; } @@ -171,12 +161,13 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { fourxm->video_pts_inc = 0; /* take the lazy approach and search for any and all vtrk and strk chunks */ + int i; for (i = 0; i < header_size - 8; i++) { - fourcc_tag = _X_LE_32(&header[i]); - size = _X_LE_32(&header[i + 4]); + const uint32_t fourcc_tag = _X_LE_32(&header[i]); + const uint32_t size = _X_LE_32(&header[i + 4]); if (fourcc_tag == std__TAG) { - fps = get_le_float(&header[i + 12]); + const float fps = get_le_float(&header[i + 12]); fourxm->video_pts_inc = (int64_t)(90000.0 / fps); } else if (fourcc_tag == vtrk_TAG) { /* check that there is enough data */ @@ -184,7 +175,7 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { free(header); return 0; } - total_frames = _X_LE_32(&header[i + 24]); + const uint32_t total_frames = _X_LE_32(&header[i + 24]); fourxm->duration_in_ms = total_frames; fourxm->duration_in_ms *= fourxm->video_pts_inc; fourxm->duration_in_ms /= 90000; @@ -198,9 +189,13 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { free(header); return 0; } - current_track = _X_LE_32(&header[i + 8]); - if (current_track + 1 > fourxm->track_count) { + const uint32_t current_track = _X_LE_32(&header[i + 8]); + if (current_track >= fourxm->track_count) { fourxm->track_count = current_track + 1; + if (!fourxm->track_count || fourxm->track_count >= UINT_MAX / sizeof(audio_track_t)) { + free(header); + return 0; + } fourxm->tracks = realloc(fourxm->tracks, fourxm->track_count * sizeof(audio_track_t)); if (!fourxm->tracks) { @@ -212,7 +207,7 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) { fourxm->tracks[current_track].channels = _X_LE_32(&header[i + 36]); fourxm->tracks[current_track].sample_rate = _X_LE_32(&header[i + 40]); fourxm->tracks[current_track].bits = _X_LE_32(&header[i + 44]); - audio_type = _X_LE_32(&header[i + 12]); + const uint32_t audio_type = _X_LE_32(&header[i + 12]); if (audio_type == 0) fourxm->tracks[current_track].audio_type = BUF_AUDIO_LPCM_LE; else if (audio_type == 1) @@ -239,20 +234,18 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) { demux_fourxm_t *this = (demux_fourxm_t *) this_gen; buf_element_t *buf = NULL; - unsigned int fourcc_tag; - unsigned int size; - unsigned char header[8]; unsigned int remaining_bytes; unsigned int current_track; /* read the next header */ + uint8_t header[8]; if (this->input->read(this->input, header, 8) != 8) { this->status = DEMUX_FINISHED; return this->status; } - fourcc_tag = _X_LE_32(&header[0]); - size = _X_LE_32(&header[4]); + const uint32_t fourcc_tag = _X_LE_32(&header[0]); + const uint32_t size = _X_LE_32(&header[4]); switch (fourcc_tag) { @@ -263,7 +256,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_4XM; if( this->filesize ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->filesize ); buf->extra_info->input_time = this->video_pts / 90; buf->pts = this->video_pts; @@ -278,7 +271,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_4XM; if( this->filesize ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->filesize ); buf->extra_info->input_time = this->video_pts / 90; buf->pts = this->video_pts; @@ -327,7 +320,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = this->tracks[current_track].audio_type; if( this->filesize ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->filesize ); /* let the engine sort it out */ buf->extra_info->input_time = 0; @@ -361,7 +354,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) { break; default: - lprintf("bad chunk: %c%c%c%c (%02X%02X%02X%02X)\n", + lprintf("bad chunk: %c%c%c%c (%02X%02X%02X%02X)\n", header[0], header[1], header[2], header[3], header[0], header[1], header[2], header[3]); this->status = DEMUX_FINISHED; @@ -472,7 +465,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_fourxm_t *this; - this = xine_xmalloc (sizeof (demux_fourxm_t)); + this = calloc(1, sizeof(demux_fourxm_t)); this->stream = stream; this->input = input; @@ -491,10 +484,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - const char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); + const char *const mrl = input->get_mrl (input); + const char *const extensions = class_gen->get_extensions (class_gen); if (!_x_demux_check_extension (mrl, extensions)) { free (this); @@ -546,7 +537,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_fourxm_init_plugin (xine_t *xine, void *data) { demux_fourxm_class_t *this; - this = xine_xmalloc (sizeof (demux_fourxm_class_t)); + this = calloc(1, sizeof(demux_fourxm_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_aac.c b/src/demuxers/demux_aac.c index d80413f83..6615f4f61 100644 --- a/src/demuxers/demux_aac.c +++ b/src/demuxers/demux_aac.c @@ -95,8 +95,7 @@ static int open_aac_file(demux_aac_t *this) { return 0; /* Check for an ADIF header - should be at the start of the file */ - if ((peak[0] == 'A') && (peak[1] == 'D') && - (peak[2] == 'I') && (peak[3] == 'F')) { + if (_x_is_fourcc(peak, "AIDF")) { lprintf("found ADIF header\n"); return 1; } @@ -109,7 +108,7 @@ static int open_aac_file(demux_aac_t *this) { if ( this->input->read(this->input, peak, MAX_PREVIEW_SIZE) != MAX_PREVIEW_SIZE ) return 0; this->input->seek(this->input, 0, SEEK_SET); - } else if (_x_demux_read_header(this->input, peak, MAX_PREVIEW_SIZE) != + } else if (_x_demux_read_header(this->input, peak, MAX_PREVIEW_SIZE) != MAX_PREVIEW_SIZE) return 0; @@ -134,9 +133,7 @@ static int open_aac_file(demux_aac_t *this) { if ((frame_size > 0) && (data_start+frame_size < MAX_PREVIEW_SIZE-1) && /* first 28 bits must be identical */ - (peak[data_start ] ==peak[data_start+frame_size ]) && - (peak[data_start+1] ==peak[data_start+frame_size+1]) && - (peak[data_start+2] ==peak[data_start+frame_size+2]) && + memcmp(&peak[data_start], &peak[data_start+frame_size], 4) == 0 && (peak[data_start+3]>>4==peak[data_start+frame_size+3]>>4)) { lprintf("found second ADTS header\n"); @@ -176,11 +173,11 @@ static int demux_aac_send_chunk(demux_plugin_t *this_gen) { buf->extra_info->input_time = (8*current_pos) / (bitrate/1000); bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; - } else + } else buf->size = bytes_read; /* each buffer stands on its own */ @@ -262,7 +259,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_aac_t *this; - this = xine_xmalloc (sizeof (demux_aac_t)); + this = calloc(1, sizeof(demux_aac_t)); this->stream = stream; this->input = input; @@ -333,7 +330,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_aac_init_plugin (xine_t *xine, void *data) { demux_aac_class_t *this; - this = xine_xmalloc (sizeof (demux_aac_class_t)); + this = calloc(1, sizeof(demux_aac_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c index c0fae275b..f13144254 100644 --- a/src/demuxers/demux_ac3.c +++ b/src/demuxers/demux_ac3.c @@ -37,6 +37,9 @@ #ifdef HAVE_ALLOCA_H #include <alloca.h> #endif +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif #define LOG_MODULE "demux_ac3" #define LOG_VERBOSE @@ -304,17 +307,11 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) { } } else { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->size = this->input->read(this->input, buf->content, + buf->size = this->input->read(this->input, buf->content, this->frame_size); } - if (buf->size == 0) { - buf->free_buffer(buf); - this->status = DEMUX_FINISHED; - return this->status; - } - - if (buf->size == 0) { + if (buf->size <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; @@ -322,7 +319,7 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) { buf->type = this->buf_type; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) current_stream_pos * + buf->extra_info->input_normpos = (int)( (double) current_stream_pos * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = audio_pts / 90; buf->pts = audio_pts; @@ -417,7 +414,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_ac3_t *this; - this = xine_xmalloc (sizeof (demux_ac3_t)); + this = calloc(1, sizeof(demux_ac3_t)); this->stream = stream; this->input = input; @@ -491,7 +488,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_ac3_init_plugin (xine_t *xine, void *data) { demux_ac3_class_t *this; - this = xine_xmalloc (sizeof (demux_ac3_class_t)); + this = calloc(1, sizeof(demux_ac3_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_aiff.c b/src/demuxers/demux_aiff.c index 3f2d0df11..ee45963a5 100644 --- a/src/demuxers/demux_aiff.c +++ b/src/demuxers/demux_aiff.c @@ -46,6 +46,10 @@ #define COMM_TAG FOURCC_TAG('C', 'O', 'M', 'M') #define SSND_TAG FOURCC_TAG('S', 'S', 'N', 'D') #define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M') +#define NAME_TAG FOURCC_TAG('N', 'A', 'M', 'E') +#define AUTH_TAG FOURCC_TAG('A', 'U', 'T', 'H') +#define COPY_TAG FOURCC_TAG('(', 'c', ')', ' ') +#define ANNO_TAG FOURCC_TAG('A', 'N', 'N', 'O') #define PREAMBLE_SIZE 8 #define AIFF_SIGNATURE_SIZE 12 @@ -80,6 +84,24 @@ typedef struct { demux_class_t demux_class; } demux_aiff_class_t; +/* converts IEEE 80bit extended into int, based on FFMPEG code */ +static int extended_to_int(const unsigned char p[10]) +{ + uint64_t m = 0; + int e, i; + + for (i = 0; i < 8; i++) + m = (m<<8) + p[2+i];; + e = (((int)p[0]&0x7f)<<8) | p[1]; + if (e == 0x7fff && m) + return 0.0/0.0; + e -= 16383 + 63; + + if (p[0]&0x80) + m= -m; + return (int) ldexp(m, e); +} + /* returns 1 if the AIFF file was opened successfully, 0 otherwise */ static int open_aiff_file(demux_aiff_t *this) { @@ -87,13 +109,14 @@ static int open_aiff_file(demux_aiff_t *this) { unsigned char preamble[PREAMBLE_SIZE]; unsigned int chunk_type; unsigned int chunk_size; + unsigned char extended_sample_rate[10]; if (_x_demux_read_header(this->input, signature, AIFF_SIGNATURE_SIZE) != AIFF_SIGNATURE_SIZE) return 0; /* check the signature */ - if ((_X_BE_32(&signature[0]) != FORM_TAG) || - (_X_BE_32(&signature[8]) != AIFF_TAG)) + if( !_x_is_fourcc(&signature[0], "FORM") || + !_x_is_fourcc(&signature[8], "AIFF") ) return 0; /* file is qualified; skip over the header bytes in the stream */ @@ -116,7 +139,7 @@ static int open_aiff_file(demux_aiff_t *this) { } chunk_type = _X_BE_32(&preamble[0]); chunk_size = _X_BE_32(&preamble[4]); - + if (chunk_type == COMM_TAG) { unsigned char buffer[100]; @@ -135,7 +158,8 @@ static int open_aiff_file(demux_aiff_t *this) { this->audio_channels = _X_BE_16(&buffer[0]); this->audio_frames = _X_BE_32(&buffer[2]); this->audio_bits = _X_BE_16(&buffer[6]); - this->audio_sample_rate = _X_BE_16(&buffer[0x0A]); + memcpy(&extended_sample_rate, &buffer[8], sizeof(extended_sample_rate)); + this->audio_sample_rate = extended_to_int(extended_sample_rate); this->audio_bytes_per_second = this->audio_channels * (this->audio_bits / 8) * this->audio_sample_rate; @@ -150,11 +174,18 @@ static int open_aiff_file(demux_aiff_t *this) { (this->audio_bits / 8); this->running_time = (this->audio_frames / this->audio_sample_rate) * 1000; - this->audio_block_align = PCM_BLOCK_ALIGN; + /* we should send only complete frames to decoder, as it + * doesn't handle underconsumption yet */ + this->audio_block_align = PCM_BLOCK_ALIGN - PCM_BLOCK_ALIGN % (this->audio_bits / 8 * this->audio_channels); break; } else { + /* if chunk contains metadata, it will be word-aligned (as seen at sox and ffmpeg) */ + if ( ((chunk_type == NAME_TAG) || (chunk_type==AUTH_TAG) || + (chunk_type == COPY_TAG) || (chunk_type==ANNO_TAG)) && (chunk_size&1)) + chunk_size++; + /* unrecognized; skip it */ this->input->seek(this->input, chunk_size, SEEK_CUR); } @@ -179,7 +210,7 @@ static int demux_aiff_send_chunk (demux_plugin_t *this_gen) { /* just load data chunks from wherever the stream happens to be * pointing; issue a DEMUX_FINISHED status if EOF is reached */ remaining_sample_bytes = this->audio_block_align; - current_file_pos = + current_file_pos = this->input->get_current_pos(this->input) - this->data_start; current_pts = current_file_pos; @@ -227,7 +258,7 @@ static int demux_aiff_send_chunk (demux_plugin_t *this_gen) { this->audio_fifo->put (this->audio_fifo, buf); } - + return this->status; } @@ -338,7 +369,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_aiff_t *this; - this = xine_xmalloc (sizeof (demux_aiff_t)); + this = calloc(1, sizeof(demux_aiff_t)); this->stream = stream; this->input = input; @@ -414,7 +445,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_aiff_init_plugin (xine_t *xine, void *data) { demux_aiff_class_t *this; - this = xine_xmalloc (sizeof (demux_aiff_class_t)); + this = calloc(1, sizeof(demux_aiff_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index 9aab59977..e2da05c75 100644 --- a/src/demuxers/demux_asf.c +++ b/src/demuxers/demux_asf.c @@ -70,6 +70,7 @@ #define ASF_MODE_HTTP_REF 2 #define ASF_MODE_ASF_REF 3 #define ASF_MODE_ENCRYPTED_CONTENT 4 +#define ASF_MODE_NO_CONTENT 5 typedef struct { int seq; @@ -87,13 +88,13 @@ typedef struct { int skip; int resync; int first_seq; - + int payload_size; /* palette handling */ int palette_count; palette_entry_t palette[256]; - + } asf_demux_stream_t; typedef struct demux_asf_s { @@ -108,13 +109,13 @@ typedef struct demux_asf_s { int64_t keyframe_ts; int keyframe_found; - + int seqno; uint32_t packet_size; uint8_t packet_len_flags; uint32_t data_size; uint64_t packet_count; - + asf_demux_stream_t streams[MAX_NUM_STREAMS]; int video_stream; int audio_stream; @@ -144,7 +145,7 @@ typedef struct demux_asf_s { int reorder_b; int buf_flag_seek; - + /* first packet position */ int64_t first_packet_pos; @@ -266,7 +267,7 @@ static int get_guid (demux_asf_t *this) { for(i = 0; i < 8; i++) { g.Data4[i] = get_byte(this); } - + return get_guid_id(this, &g); } @@ -305,7 +306,7 @@ static void asf_send_audio_header (demux_asf_t *this, int stream) { this->status = DEMUX_FINISHED; return; } - + memcpy (buf->content, wavex, asf_stream->private_data_length); _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, wavex->wFormatTag); @@ -346,11 +347,19 @@ static void asf_send_video_header (demux_asf_t *this, int stream) { this->status = DEMUX_FINISHED; return; } - + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE| BUF_FLAG_FRAME_END; - + buf->decoder_info[0] = 0; + + if (this->asf_header->aspect_ratios[stream].x && this->asf_header->aspect_ratios[stream].y) + { + buf->decoder_flags |= BUF_FLAG_ASPECT; + buf->decoder_info[1] = bih->biWidth * this->asf_header->aspect_ratios[stream].x; + buf->decoder_info[2] = bih->biHeight * this->asf_header->aspect_ratios[stream].y; + } + buf->size = asf_stream->private_data_length - 11; memcpy (buf->content, bih, buf->size); buf->type = this->streams[stream].buf_type; @@ -360,7 +369,7 @@ static void asf_send_video_header (demux_asf_t *this, int stream) { /* send off the palette, if there is one */ if (demux_stream->palette_count) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_asf: stream %d, palette : %d entries\n", stream, demux_stream->palette_count); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER; @@ -379,10 +388,21 @@ static int asf_read_header (demux_asf_t *this) { char *asf_header_buffer = NULL; asf_header_len = get_le64(this); - asf_header_buffer = alloca(asf_header_len); + if (asf_header_len > 4 * 1024 * 1024) + { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_asf: asf_read_header: overly-large header? (%"PRIu64" bytes)\n", + asf_header_len); + return 0; + } + + asf_header_buffer = malloc (asf_header_len); if (this->input->read (this->input, asf_header_buffer, asf_header_len) != asf_header_len) + { + free (asf_header_buffer); return 0; + } /* delete previous header */ if (this->asf_header) { @@ -395,19 +415,23 @@ static int asf_read_header (demux_asf_t *this) { */ this->asf_header = asf_header_new(asf_header_buffer, asf_header_len); if (!this->asf_header) + { + free (asf_header_buffer); return 0; + } + free (asf_header_buffer); lprintf("asf header parsing ok\n"); this->packet_size = this->asf_header->file->packet_size; this->packet_count = this->asf_header->file->data_packet_count; - + /* compute stream duration */ - this->length = (this->asf_header->file->send_duration - + this->length = (this->asf_header->file->send_duration - this->asf_header->file->preroll) / 10000; if (this->length < 0) this->length = 0; - + /* compute average byterate (needed for seeking) */ if (this->asf_header->file->max_bitrate) this->rate = this->asf_header->file->max_bitrate >> 3; @@ -420,6 +444,17 @@ static int asf_read_header (demux_asf_t *this) { asf_stream_t *asf_stream = this->asf_header->streams[i]; asf_demux_stream_t *demux_stream = &this->streams[i]; + if (!asf_stream) { + if (this->mode != ASF_MODE_NO_CONTENT) { + xine_log(this->stream->xine, XINE_LOG_MSG, + _("demux_asf: warning: A stream appears to be missing.\n")); + _x_message(this->stream, XINE_MSG_READ_ERROR, + _("Media stream missing?"), NULL); + this->mode = ASF_MODE_NO_CONTENT; + } + return 0; + } + if (asf_stream->encrypted_flag) { if (this->mode != ASF_MODE_ENCRYPTED_CONTENT) { xine_log(this->stream->xine, XINE_LOG_MSG, @@ -438,14 +473,14 @@ static int asf_read_header (demux_asf_t *this) { this->reorder_w = (asf_stream->error_correction_data[2]<<8)|asf_stream->error_correction_data[1]; this->reorder_b = (asf_stream->error_correction_data[4]<<8)|asf_stream->error_correction_data[3]; this->reorder_w /= this->reorder_b; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: audio conceal interleave detected (%d x %d x %d)\n", this->reorder_w, this->reorder_h, this->reorder_b ); } else { this->reorder_b = this->reorder_h = this->reorder_w = 1; } - - + + demux_stream->buf_type = _x_formattag_to_buf_audio ( ((xine_waveformatex *)asf_stream->private_data)->wFormatTag ); if ( !demux_stream->buf_type ) { @@ -454,9 +489,9 @@ static int asf_read_header (demux_asf_t *this) { ((xine_waveformatex *)asf_stream->private_data)->wFormatTag); demux_stream->buf_type = BUF_AUDIO_UNKNOWN; } - + _x_meta_info_set(this->stream, XINE_META_INFO_AUDIOCODEC, _x_buf_audio_name(demux_stream->buf_type)); - + this->streams[i].fifo = this->audio_fifo; this->streams[i].frag_offset = 0; this->streams[i].seq = 0; @@ -466,12 +501,12 @@ static int asf_read_header (demux_asf_t *this) { this->streams[i].defrag = 1; } else this->streams[i].defrag = 0; - + lprintf ("found an audio stream id=%d \n", asf_stream->stream_number); break; - + case GUID_ASF_VIDEO_MEDIA: - { + { /* video private data * 11 bytes : header * 40 bytes : bmiheader @@ -480,38 +515,38 @@ static int asf_read_header (demux_asf_t *this) { uint32_t width, height; uint16_t bmiheader_size; xine_bmiheader *bmiheader; - + width = _X_LE_32(asf_stream->private_data); height = _X_LE_32(asf_stream->private_data + 4); /* there is one unknown byte between height and the bmiheader size */ bmiheader_size = _X_LE_16(asf_stream->private_data + 9); - + /* FIXME: bmiheader_size must be >= sizeof(xine_bmiheader) */ - + bmiheader = (xine_bmiheader *) (asf_stream->private_data + 11); _x_bmiheader_le2me(bmiheader); - + /* FIXME: check if (bmi_header_size == bmiheader->biSize) ? */ demux_stream->buf_type = _x_fourcc_to_buf_video(bmiheader->biCompression); if( !demux_stream->buf_type ) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: unknown video format %.4s\n", (char*)&(bmiheader->biCompression)); - + demux_stream->buf_type = BUF_VIDEO_UNKNOWN; } - + _x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name(demux_stream->buf_type)); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height); - + this->streams[i].fifo = this->video_fifo; this->streams[i].frag_offset = 0; this->streams[i].defrag = 0; - + /* load the palette, if there is one */ demux_stream->palette_count = bmiheader->biClrUsed; - + lprintf ("palette_count: %d\n", demux_stream->palette_count); if (demux_stream->palette_count > 256) { lprintf ("number of colours exceeded 256 (%d)", demux_stream->palette_count); @@ -520,10 +555,10 @@ static int asf_read_header (demux_asf_t *this) { if ((asf_stream->private_data_length - sizeof(xine_bmiheader) - 11) >= (demux_stream->palette_count * 4)) { int j; uint8_t *palette; - + /* according to msdn the palette is located here : */ palette = (uint8_t *)bmiheader + bmiheader->biSize; - + /* load the palette */ for (j = 0; j < demux_stream->palette_count; j++) { demux_stream->palette[j].b = *(palette + j * 4 + 0); @@ -532,7 +567,7 @@ static int asf_read_header (demux_asf_t *this) { } } else { int j; - + /* generate a greyscale palette */ demux_stream->palette_count = 256; for (j = 0; j < demux_stream->palette_count; j++) { @@ -541,7 +576,7 @@ static int asf_read_header (demux_asf_t *this) { demux_stream->palette[j].b = j; } } - + lprintf ("found a video stream id=%d, buf_type=%08x \n", this->asf_header->streams[i]->stream_number, this->streams[i].buf_type); } @@ -703,12 +738,15 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str bufsize = stream->fifo->buffer_pool_buf_size; buf = stream->fifo->buffer_pool_alloc (stream->fifo); - this->input->read (this->input, buf->content, bufsize); + if (this->input->read (this->input, buf->content, bufsize) != bufsize) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n"); + return ; + } lprintf ("data: %d %d %d %d\n", buf->content[0], buf->content[1], buf->content[2], buf->content[3]); if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = timestamp; @@ -723,6 +761,9 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str buf->size = bufsize; timestamp = 0; + if (stream->frag_offset == 0) + buf->decoder_flags |= BUF_FLAG_FRAME_START; + stream->frag_offset += bufsize; frag_len -= bufsize; @@ -733,10 +774,6 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str else check_newpts (this, buf->pts, PTS_AUDIO, package_done); - - if (frag_offset == 0) - buf->decoder_flags |= BUF_FLAG_FRAME_START; - /* test if whole packet read */ if (package_done) { buf->decoder_flags |= BUF_FLAG_FRAME_END; @@ -783,7 +820,10 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *strea if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: buffer overflow on defrag!\n"); } else { - this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len); + if (this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len) != frag_len) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n"); + return ; + } stream->frag_offset += frag_len; } @@ -792,46 +832,46 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *strea if (package_done) { int bufsize; uint8_t *p; - + lprintf("packet done: offset=%d, payload=%d\n", stream->frag_offset, stream->payload_size); if (stream->fifo == this->audio_fifo && this->reorder_h > 1 && this->reorder_w > 1 ) { asf_reorder(this,stream->buffer,stream->frag_offset); } - + p = stream->buffer; while( stream->frag_offset ) { if ( stream->frag_offset < stream->fifo->buffer_pool_buf_size ) bufsize = stream->frag_offset; else bufsize = stream->fifo->buffer_pool_buf_size; - + buf = stream->fifo->buffer_pool_alloc (stream->fifo); xine_fast_memcpy (buf->content, p, bufsize); - + if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = stream->timestamp; - + /* send the same pts for the entire frame */ buf->pts = stream->timestamp * 90; - + buf->type = stream->buf_type; buf->size = bufsize; - + lprintf ("buffer type %08x %8d bytes, %8lld pts\n", buf->type, buf->size, buf->pts); - + stream->frag_offset -= bufsize; p+=bufsize; - + if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE) check_newpts (this, buf->pts, PTS_VIDEO, !stream->frag_offset); else check_newpts (this, buf->pts, PTS_AUDIO, !stream->frag_offset); - + /* test if whole packet read */ if ( !stream->frag_offset ) buf->decoder_flags |= BUF_FLAG_FRAME_END; @@ -848,9 +888,9 @@ static int asf_parse_packet_align(demux_asf_t *this) { uint32_t mod; uint64_t packet_num; - + current_pos = this->input->get_current_pos (this->input); - + /* seek to the beginning of the next packet */ mod = (current_pos - this->first_packet_pos) % this->packet_size; this->packet_size_left = mod ? this->packet_size - mod : 0; @@ -864,7 +904,7 @@ static int asf_parse_packet_align(demux_asf_t *this) { } } this->packet_size_left = 0; - + /* check packet_count */ packet_num = (packet_pos - this->first_packet_pos) / this->packet_size; lprintf("packet_num=%"PRId64", packet_count=%"PRId64"\n", packet_num, this->packet_count); @@ -885,7 +925,7 @@ static int asf_parse_packet_align(demux_asf_t *this) { } } } - + return 0; } @@ -911,7 +951,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) { ecd_opaque = (ecd_flags >> 4) & 0x1; ecd_len_type = (ecd_flags >> 5) & 0x3; ecd_present = (ecd_flags >> 7) & 0x1; - + /* skip ecd */ if (ecd_present && !ecd_opaque && !ecd_len_type) { int read_size; @@ -925,7 +965,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) { } else { GUID *guid = (GUID *)buf; - + /* check if it's a new stream */ buf[0] = ecd_flags; if (this->input->read (this->input, buf + 1, 15) != 15) { @@ -942,7 +982,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) { if (demux_asf_send_headers_common(this)) return 1; } else { - + /* skip invalid packet */ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: skip invalid packet: %2X\n", ecd_flags); this->input->seek (this->input, this->packet_size - *p_hdr_size, SEEK_CUR); @@ -951,7 +991,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) { } } } while (invalid_packet); - + return 0; } @@ -1020,7 +1060,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: invalid padsize: %d\n", this->packet_padsize); return 1; } - + /* Multiple frames */ if (this->packet_len_flags & 0x01) { this->frame_flag = get_byte(this); p_hdr_size += 1; @@ -1057,7 +1097,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this, *stream = NULL; lprintf ("got raw_id=%d, stream_id=%d\n", raw_id, stream_id); - + for (i = 0; i < this->asf_header->stream_count; i++) { lprintf ("stream_number = %d\n", this->asf_header->streams[i]->stream_number); if ((this->asf_header->streams[i]->stream_number == stream_id) && @@ -1067,7 +1107,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this, break; } } - + switch ((this->packet_prop_flags >> 4) & 3){ case 1: seq = get_byte(this); s_hdr_size += 1; @@ -1224,10 +1264,10 @@ static int asf_parse_packet_compressed_payload(demux_asf_t *this, stream->resync = 0; stream->skip = 0; } - + if (!stream->skip) { lprintf ("sending buffer of type %08x\n", stream->buf_type); - + if (stream->defrag) asf_send_buffer_defrag (this, stream, 0, *timestamp, object_length); else @@ -1399,15 +1439,15 @@ static int demux_asf_parse_http_references( demux_asf_t *this) { if (!end) goto failure; *end = '\0'; } - + /* replace http by mmsh */ if (!strncmp(href, "http", 4)) { memcpy(href, "mmsh", 4); } - + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: http ref: %s\n", href); _x_demux_send_mrl_reference (this->stream, 0, href, NULL, 0, 0); - + if (free_href) free(href); } @@ -1504,6 +1544,7 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) { int buf_used = 0; int len; xml_node_t *xml_tree, *asx_entry, *asx_ref; + xml_parser_t *xml_parser; int result; @@ -1526,9 +1567,13 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) { if(buf_used) buf[buf_used] = '\0'; - xml_parser_init(buf, buf_used, XML_PARSER_CASE_INSENSITIVE); - if((result = xml_parser_build_tree(&xml_tree)) != XML_PARSER_OK) + xml_parser = xml_parser_init_r(buf, buf_used, XML_PARSER_CASE_INSENSITIVE); + if((result = xml_parser_build_tree_r(xml_parser, &xml_tree)) != XML_PARSER_OK) { + xml_parser_finalize_r(xml_parser); goto failure; + } + + xml_parser_finalize_r(xml_parser); if(!strcasecmp(xml_tree->name, "ASX")) { /* Attributes: VERSION, PREVIEWMODE, BANNERBAR @@ -1586,13 +1631,13 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) { else if (!strcasecmp (asx_ref->name, "STARTTIME")) { - if (start_time == (uint32_t)-1) + if (start_time == (uint32_t)-1) start_time = asx_get_time_value (asx_ref); } else if (!strcasecmp (asx_ref->name, "DURATION")) { - if (duration == (uint32_t)-1) + if (duration == (uint32_t)-1) duration = asx_get_time_value (asx_ref); } @@ -1645,7 +1690,7 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) { uint32_t rlen = 0; uint8_t raw_id = 0; int64_t ts = 0; - + switch (this->mode) { case ASF_MODE_ASX_REF: return demux_asf_parse_asx_references(this); @@ -1657,13 +1702,14 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) { return demux_asf_parse_asf_references(this); case ASF_MODE_ENCRYPTED_CONTENT: + case ASF_MODE_NO_CONTENT: this->status = DEMUX_FINISHED; return this->status; default: - { + { int header_size = 0; - + if (asf_parse_packet_align(this)) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: asf_parse_packet_align failed\n"); this->status = DEMUX_FINISHED; @@ -1679,7 +1725,7 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) { this->status = DEMUX_FINISHED; return this->status; } - + for (this->frame = 0; this->frame < (this->nb_frames & 0x3f); this->frame++) { raw_id = get_byte(this); this->packet_size_left -= 1; @@ -1704,7 +1750,7 @@ static void demux_asf_dispose (demux_plugin_t *this_gen) { if (this->asf_header) { int i; - + for (i=0; i<this->asf_header->stream_count; i++) { asf_demux_stream_t *asf_stream; @@ -1717,7 +1763,7 @@ static void demux_asf_dispose (demux_plugin_t *this_gen) { asf_header_delete (this->asf_header); } - + free (this); } @@ -1777,11 +1823,11 @@ static int demux_asf_seek (demux_plugin_t *this_gen, start_pos, start_time); this->status = DEMUX_OK; - + if (this->mode != ASF_MODE_NORMAL) { return this->status; } - + /* * seek to start position */ @@ -1795,7 +1841,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, this->last_pts[PTS_AUDIO] = 0; this->keyframe_ts = 0; this->keyframe_found = 0; - + /* engine sync stuff */ this->send_newpts = 1; this->buf_flag_seek = 1; @@ -1803,11 +1849,11 @@ static int demux_asf_seek (demux_plugin_t *this_gen, if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) { _x_demux_flush_engine(this->stream); - + start_time /= 1000; start_pos = (off_t) ( (double) start_pos / 65535 * this->input->get_length (this->input) ); - + if ( (!start_pos) && (start_time)) start_pos = start_time * this->rate; @@ -1868,7 +1914,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, this->status = DEMUX_FINISHED; return this->status; } - + for (this->frame = 0; this->frame < (this->nb_frames & 0x3f); this->frame++) { raw_id = get_byte(this); this->packet_size_left -= 1; @@ -1877,7 +1923,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, stream_id = raw_id & 0x7f; if (asf_parse_packet_payload_common(this, raw_id, &stream, &frag_offset, &rlen)) break; - + if (rlen == 1) { if (asf_parse_packet_compressed_payload(this, stream, raw_id, frag_offset, &ts)) break; @@ -1885,7 +1931,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, if (asf_parse_packet_payload(this, stream, raw_id, frag_offset, rlen, &ts)) break; } - + if (state == 0) { if (this->keyframe_found) { if (this->audio_stream == -1) { @@ -1935,12 +1981,12 @@ static int demux_asf_seek (demux_plugin_t *this_gen, this->streams[this->audio_stream].resync = 1; this->streams[this->audio_stream].skip = 1; } - } else if (!playing && this->input->seek_time != NULL) { + } else if (!playing && this->input->seek_time != NULL) { if (start_pos && !start_time) start_time = this->length * start_pos / 65535; - + this->input->seek_time (this->input, start_time, SEEK_SET); - + this->keyframe_ts = 0; this->keyframe_found = 0; /* means next keyframe */ if (this->video_stream >= 0) { @@ -1965,7 +2011,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, } } return this->status; - + error: this->status = DEMUX_FINISHED; return this->status; @@ -2059,7 +2105,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, return NULL; } - this = xine_xmalloc (sizeof (demux_asf_t)); + this = calloc(1, sizeof(demux_asf_t)); this->stream = stream; this->input = input; @@ -2094,7 +2140,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; - + return &this->demux_plugin; } @@ -2134,7 +2180,7 @@ static void *init_class (xine_t *xine, void *data) { demux_asf_class_t *this; - this = xine_xmalloc (sizeof (demux_asf_class_t)); + this = calloc(1, sizeof(demux_asf_class_t)); this->config = xine->config; this->xine = xine; @@ -2155,7 +2201,7 @@ static void *init_class (xine_t *xine, void *data) { static const demuxer_info_t demux_info_asf = { 10 /* priority */ }; - + const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "asf", XINE_VERSION_CODE, &demux_info_asf, init_class }, diff --git a/src/demuxers/demux_aud.c b/src/demuxers/demux_aud.c index a6f88ff48..caaa4e91a 100644 --- a/src/demuxers/demux_aud.c +++ b/src/demuxers/demux_aud.c @@ -105,7 +105,7 @@ remove this case for the time being since this audio type is not supported anyway. if (header[11] == 1) this->audio_type = BUF_AUDIO_WESTWOOD; - else + else #endif if (header[11] == 99) this->audio_type = BUF_AUDIO_VQA_IMA; @@ -143,7 +143,7 @@ static int demux_aud_send_chunk(demux_plugin_t *this_gen) { } /* validate the chunk */ - if (_X_LE_32(&chunk_preamble[4]) != 0x0000DEAF) { + if (!_x_is_fourcc(&chunk_preamble[4], "\xAF\xDE\x00\x00")) { this->status = DEMUX_FINISHED; return this->status; } @@ -270,7 +270,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_aud_t *this; - this = xine_xmalloc (sizeof (demux_aud_t)); + this = calloc(1, sizeof(demux_aud_t)); this->stream = stream; this->input = input; @@ -343,7 +343,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_aud_init_plugin (xine_t *xine, void *data) { demux_aud_class_t *this; - this = xine_xmalloc (sizeof (demux_aud_class_t)); + this = calloc(1, sizeof(demux_aud_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index 6bb0b289c..100828bd2 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -7,12 +7,12 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -134,7 +134,7 @@ typedef struct _avistdindex_chunk { uint32_t dwReserved3; /* must be 0 */ avistdindex_entry *aIndex; } avistdindex_chunk; - + /* Base Index Form 'indx' */ typedef struct _avisuperindex_chunk { @@ -150,7 +150,7 @@ typedef struct _avisuperindex_chunk { avisuperindex_entry *aIndex; /* where are the ix## chunks */ avistdindex_chunk **stdindex; /* the ix## chunks itself (array) */ } avisuperindex_chunk; - + /* These next three are the video and audio structures that can grow * during the playback of a streaming file. */ @@ -317,6 +317,8 @@ typedef struct { getIndex==0, but an operation has been performed that needs an index */ +#define AVI_ERR_BAD_SIZE 14 /* A chunk has an invalid size */ + #define AVI_HEADER_UNKNOWN -1 #define AVI_HEADER_AUDIO 0 #define AVI_HEADER_VIDEO 1 @@ -471,7 +473,7 @@ static int start_pos_stopper(demux_avi_t *this, void *data) { maxframe--; } return -1; -} +} /* Use this one to ensure that a video frame with the given timestamp * is in the index. */ @@ -598,11 +600,11 @@ static int idx_grow(demux_avi_t *this, int (*stopper)(demux_avi_t *, void *), } } else { int i; - + /* Audio chunk */ for(i = 0; i < this->avi->n_audio; ++i) { avi_audio_t *audio = this->avi->audio[i]; - + if ((data[0] == audio->audio_tag[0]) && (data[1] == audio->audio_tag[1])) { off_t pos = chunk_pos + AVI_HEADER_SIZE; @@ -615,7 +617,7 @@ static int idx_grow(demux_avi_t *this, int (*stopper)(demux_avi_t *, void *), } else { audio->block_no += 1; } - + if (audio_index_append(this->avi, i, pos, chunk_len, audio->audio_tot, audio->block_no) == -1) { /* As above. */ @@ -709,17 +711,17 @@ do { \ static void reset_idx(demux_avi_t *this, avi_t *AVI) { int n; - + this->idx_grow.nexttagoffset = AVI->movi_start; this->has_index = 0; - + AVI->video_idx.video_frames = 0; for(n = 0; n < AVI->n_audio; n++) { AVI->audio[n]->audio_idx.audio_chunks = 0; } } -static avi_t *AVI_init(demux_avi_t *this) { +static avi_t *XINE_MALLOC AVI_init(demux_avi_t *this) { avi_t *AVI; int i, j, idx_type; @@ -739,7 +741,7 @@ static avi_t *AVI_init(demux_avi_t *this) { /* Create avi_t structure */ lprintf("start\n"); - AVI = (avi_t *) xine_xmalloc(sizeof(avi_t)); + AVI = (avi_t *) calloc(1, sizeof(avi_t)); if(AVI==NULL) { this->AVI_errno = AVI_ERR_NO_MEM; return 0; @@ -776,28 +778,28 @@ static avi_t *AVI_init(demux_avi_t *this) { n = _X_LE_32(data + 4); n = PAD_EVEN(n); next_chunk = this->idx_grow.nexttagoffset + 8 + n; - + lprintf("chunk: %c%c%c%c, size: %" PRId64 "\n", data[0], data[1], data[2], data[3], (int64_t)n); - - if((strncasecmp(data,"LIST",4) == 0) && (n >= 4)) { + + if (n >= 4 && strncasecmp(data,"LIST",4) == 0) { if( this->input->read(this->input, data,4) != 4 ) ERR_EXIT(AVI_ERR_READ); n -= 4; - + lprintf(" chunk: %c%c%c%c\n", data[0], data[1], data[2], data[3]); if(strncasecmp(data,"hdrl",4) == 0) { hdrl_len = n; - hdrl_data = (unsigned char *) xine_xmalloc(n); + hdrl_data = (unsigned char *) malloc(n); if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM); if (this->input->read(this->input, hdrl_data,n) != n ) ERR_EXIT(AVI_ERR_READ); } else if(strncasecmp(data,"movi",4) == 0) { - + AVI->movi_start = this->input->get_current_pos(this->input); AVI->movi_end = AVI->movi_start + n - 1; @@ -812,9 +814,8 @@ static avi_t *AVI_init(demux_avi_t *this) { break if this is not the case */ AVI->n_idx = AVI->max_idx = n / 16; - if (AVI->idx) - free(AVI->idx); /* On the off chance there are multiple index chunks */ - AVI->idx = (unsigned char((*)[16])) xine_xmalloc(n); + free(AVI->idx); /* On the off chance there are multiple index chunks */ + AVI->idx = (unsigned char((*)[16])) malloc(n); if (AVI->idx == 0) ERR_EXIT(AVI_ERR_NO_MEM); @@ -836,6 +837,8 @@ static avi_t *AVI_init(demux_avi_t *this) { /* Interpret the header list */ for (i = 0; i < hdrl_len;) { + const int old_i = i; + /* List tags are completly ignored */ lprintf("tag: %c%c%c%c\n", hdrl_data[i], hdrl_data[i+1], hdrl_data[i+2], hdrl_data[i+3]); @@ -874,15 +877,14 @@ static avi_t *AVI_init(demux_avi_t *this) { lasttag = 1; /* vids */ lprintf("dwScale=%d, dwRate=%d, dwInitialFrames=%d, dwStart=%d, num_stream=%d\n", AVI->dwScale, AVI->dwRate, AVI->dwInitialFrames, AVI->dwStart, num_stream); - + } else if (strncasecmp (hdrl_data+i,"auds",4) ==0 /* && ! auds_strh_seen*/) { if(AVI->n_audio < MAX_AUDIO_STREAMS) { - avi_audio_t *a = (avi_audio_t *) xine_xmalloc(sizeof(avi_audio_t)); + avi_audio_t *a = (avi_audio_t *) calloc(1, sizeof(avi_audio_t)); if(a==NULL) { this->AVI_errno = AVI_ERR_NO_MEM; return 0; } - memset((void *)a,0,sizeof(avi_audio_t)); AVI->audio[AVI->n_audio] = a; a->audio_strn = num_stream; @@ -890,10 +892,10 @@ static avi_t *AVI_init(demux_avi_t *this) { a->dwScale = _X_LE_32(hdrl_data + i + 20); a->dwRate = _X_LE_32(hdrl_data + i + 24); a->dwStart = _X_LE_32(hdrl_data + i + 28); - + lprintf("dwScale=%d, dwRate=%d, dwInitialFrames=%d, dwStart=%d, num_stream=%d\n", a->dwScale, a->dwRate, a->dwInitialFrames, a->dwStart, num_stream); - + a->dwSampleSize = _X_LE_32(hdrl_data + i + 44); a->audio_tot = 0; auds_strh_seen = 1; @@ -907,14 +909,14 @@ static avi_t *AVI_init(demux_avi_t *this) { lasttag = 0; } num_stream++; - + } else if(strncasecmp(hdrl_data+i,"dmlh",4) == 0) { AVI->total_frames = _X_LE_32(hdrl_data+i+8); #ifdef DEBUG_ODML lprintf( "AVI: real number of frames %d\n", AVI->total_frames); #endif i += 8; - + } else if(strncasecmp(hdrl_data + i, "strf", 4) == 0) { i += 4; strf_size = _X_LE_32(hdrl_data + i); @@ -922,7 +924,7 @@ static avi_t *AVI_init(demux_avi_t *this) { if(lasttag == 1) { /* lprintf ("size : %d\n",sizeof(AVI->bih)); */ AVI->bih = (xine_bmiheader *) - xine_xmalloc((n < sizeof(xine_bmiheader)) ? sizeof(xine_bmiheader) : n); + malloc((n < sizeof(xine_bmiheader)) ? sizeof(xine_bmiheader) : n); if(AVI->bih == NULL) { this->AVI_errno = AVI_ERR_NO_MEM; return 0; @@ -971,8 +973,12 @@ static avi_t *AVI_init(demux_avi_t *this) { } else if(lasttag == 2) { xine_waveformatex *wavex; - + wavex = (xine_waveformatex *)malloc(n); + if (!wavex) { + this->AVI_errno = AVI_ERR_NO_MEM; + return 0; + } memcpy((void *)wavex, hdrl_data+i, n); _x_waveformatex_le2me( wavex ); @@ -1079,6 +1085,8 @@ static avi_t *AVI_init(demux_avi_t *this) { lasttag = 0; } i += n; + if (i <= old_i) + ERR_EXIT(AVI_ERR_BAD_SIZE); } if( hdrl_data ) @@ -1167,7 +1175,7 @@ static avi_t *AVI_init(demux_avi_t *this) { } lprintf("idx_type=%d, AVI->n_idx=%d\n", idx_type, AVI->n_idx); - + if (idx_type != 0 && !AVI->is_opendml) { /* Now generate the video index and audio index arrays from the * idx1 record. */ @@ -1224,7 +1232,7 @@ static avi_t *AVI_init(demux_avi_t *this) { xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "demux_avi: This is an OpenDML stream\n"); nvi = 0; - for(audtr=0; audtr<AVI->n_audio; ++audtr) nai[audtr] = 0; + for(audtr=0; audtr<AVI->n_audio; ++audtr) nai[audtr] = 0; /* ************************ */ /* VIDEO */ @@ -1237,6 +1245,9 @@ static avi_t *AVI_init(demux_avi_t *this) { /* read from file */ chunk_start = en = malloc (AVI->video_superindex->aIndex[j].dwSize+hdrl_len); + if (!chunk_start) + ERR_EXIT(AVI_ERR_NO_MEM); + if (this->input->seek(this->input, AVI->video_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { lprintf("cannot seek to 0x%" PRIx64 "\n", AVI->video_superindex->aIndex[j].qwOffset); free(chunk_start); @@ -1289,7 +1300,7 @@ static avi_t *AVI_init(demux_avi_t *this) { "demux_avi: Warning: the video super index is NULL\n"); } - + /* ************************ */ /* AUDIO */ /* ************************ */ @@ -1308,6 +1319,9 @@ static avi_t *AVI_init(demux_avi_t *this) { /* read from file */ chunk_start = en = malloc (audio->audio_superindex->aIndex[j].dwSize+hdrl_len); + if (!chunk_start) + ERR_EXIT(AVI_ERR_NO_MEM); + if (this->input->seek(this->input, audio->audio_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) { lprintf("cannot seek to 0x%" PRIx64 "\n", audio->audio_superindex->aIndex[j].qwOffset); free(chunk_start); @@ -1330,7 +1344,7 @@ static avi_t *AVI_init(demux_avi_t *this) { /* skip header */ en += hdrl_len; nai[audtr] += nrEntries; - + while (k < nai[audtr]) { off_t pos; @@ -1338,7 +1352,7 @@ static avi_t *AVI_init(demux_avi_t *this) { pos = offset + _X_LE_32(en); en += 4; len = odml_len(en); en += 4; - + /* VBR streams (hack from mplayer) */ if (audio->wavex && audio->wavex->nBlockAlign) { audio->block_no += (len + audio->wavex->nBlockAlign - 1) / @@ -1380,7 +1394,7 @@ static avi_t *AVI_init(demux_avi_t *this) { this->idx_grow.nexttagoffset = AVI->movi_start; this->has_index = 0; } - + /* Reposition the file */ if (!this->streaming) this->input->seek(this->input, AVI->movi_start, SEEK_SET); @@ -1466,7 +1480,7 @@ static int AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf, nr = 0; /* total number of bytes read */ left = vie->len - AVI->video_posb; - + while ((bytes > 0) && (left > 0)) { if (bytes < left) todo = bytes; @@ -1508,7 +1522,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { int audio_sent = 0; lprintf("begin\n"); - + /* Try to grow the index, in case more of the avi file has shown up * since we last checked. If it's still too small, well then we're at * the end of the stream. */ @@ -1517,7 +1531,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { lprintf("end of stream\n"); } } - + for (i = 0; i < this->avi->n_audio; i++) { avi_audio_t *audio = this->avi->audio[i]; @@ -1528,7 +1542,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { } } } - + video_pts = get_video_pts (this, this->avi->video_posf); for (i=0; i < this->avi->n_audio; i++) { @@ -1554,7 +1568,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { /* read audio */ buf->pts = audio_pts; - + buf->size = AVI_read_audio (this, audio, buf->mem, buf->max_size, &buf->decoder_flags); buf->decoder_flags |= decoder_flags; @@ -1566,12 +1580,12 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { buf->type = audio->audio_type | i; buf->extra_info->input_time = audio_pts / 90; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); - + check_newpts (this, buf->pts, PTS_AUDIO); this->audio_fifo->put (this->audio_fifo, buf); - + audio_sent++; } } else @@ -1581,7 +1595,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { if (audio_sent == 0) { do_read_video = 1; } - + if (do_read_video) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); @@ -1597,12 +1611,12 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { if (this->has_index && this->avi->video_idx.video_frames > 2) { /* use video_frames-2 instead of video_frames-1 to fix problems with weird non-interleaved streams */ - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->avi->video_idx.vindex[this->avi->video_idx.video_frames - 2].pos); } else { if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); } buf->extra_info->frame_number = this->avi->video_posf; @@ -1617,7 +1631,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) { lprintf ("adding buf %d to video fifo, decoder_info[0]: %d\n", buf, buf->decoder_info[0]); */ - + check_newpts (this, buf->pts, PTS_VIDEO); this->video_fifo->put (this->video_fifo, buf); video_sent++; @@ -1738,7 +1752,7 @@ static int demux_avi_next_streaming (demux_avi_t *this, int decoder_flags) { } buf->extra_info->input_time = audio_pts / 90; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->type = audio->audio_type | audio_stream; @@ -1769,7 +1783,7 @@ static int demux_avi_next_streaming (demux_avi_t *this, int decoder_flags) { /* read video */ buf->pts = video_pts; lprintf("video pts: %" PRId64 "\n", video_pts); - + if (left > this->video_fifo->buffer_pool_buf_size) { buf->size = this->video_fifo->buffer_pool_buf_size; buf->decoder_flags = 0; @@ -1824,7 +1838,7 @@ static int demux_avi_send_chunk (demux_plugin_t *this_gen) { this->seek_request = 0; demux_avi_seek_internal(this); } - + if (!demux_avi_next (this, 0)) { this->status = DEMUX_FINISHED; } @@ -1904,7 +1918,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) { this->avi->bih->biCompression = this->avi->compressor; this->avi->video_type = BUF_VIDEO_XVID; } - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, !this->no_audio); _x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name(this->avi->video_type)); @@ -1922,7 +1936,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) { _x_demux_control_start (this->stream); buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - + if (this->avi->bih->biSize > buf->max_size) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_avi: private video decoder data length (%d) is greater than fifo buffer length (%d)\n", @@ -1931,9 +1945,9 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) { this->status = DEMUX_FINISHED; return; } - + /* wait, before sending out the video header, one more special case hack: - * if the video type is RGB, indicate that it is upside down with a + * if the video type is RGB, indicate that it is upside down with a * negative height */ if (this->avi->video_type == BUF_VIDEO_RGB) { this->avi->bih->biHeight = -this->avi->bih->biHeight; @@ -1944,7 +1958,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) { buf->decoder_info[0] = this->video_step; memcpy (buf->content, this->avi->bih, this->avi->bih->biSize); buf->size = this->avi->bih->biSize; - + if (this->avi->video_type) { this->avi->compressor = this->avi->bih->biCompression; } else { @@ -1992,7 +2006,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) { buf->size = todo; } todo -= buf->size; - + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER; if (todo == 0) buf->decoder_flags |= BUF_FLAG_FRAME_END; @@ -2009,7 +2023,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) { } if(this->avi->n_audio == 1) - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->avi->audio[0]->wavex->wFormatTag); } @@ -2059,7 +2073,7 @@ static int demux_avi_seek_internal (demux_avi_t *this) { int64_t audio_pts; off_t start_pos = this->seek_start_pos; int start_time = this->seek_start_time; - + start_pos = (off_t) ( (double) start_pos / 65535 * this->input->get_length (this->input) ); @@ -2094,12 +2108,12 @@ static int demux_avi_seek_internal (demux_avi_t *this) { video_pts = start_time * 90; idx_grow(this, start_time_stopper, &video_pts); } - + if (start_pos || start_time) max_pos = this->avi->video_idx.video_frames - 1; else max_pos=0; - + cur_pos = this->avi->video_posf; if (max_pos < 0) { this->status = DEMUX_FINISHED; @@ -2127,7 +2141,7 @@ static int demux_avi_seek_internal (demux_avi_t *this) { } } } - + while (vie && !(vie->flags & AVIIF_KEYFRAME) && cur_pos) { this->avi->video_posf = --cur_pos; vie = video_cur_index_entry(this); @@ -2150,7 +2164,7 @@ static int demux_avi_seek_internal (demux_avi_t *this) { if (!this->no_audio && this->status == DEMUX_OK) { audio_index_entry_t *aie; int i; - + for(i = 0; i < this->avi->n_audio; i++) { max_pos = this->avi->audio[i]->audio_idx.audio_chunks - 1; min_pos = 0; @@ -2271,7 +2285,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_avi_t)); + this = calloc(1, sizeof(demux_avi_t)); this->stream = stream; this->input = input; @@ -2337,7 +2351,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_class (xine_t *xine, void *data) { demux_avi_class_t *this; - this = xine_xmalloc (sizeof (demux_avi_class_t)); + this = calloc(1, sizeof(demux_avi_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_cdda.c b/src/demuxers/demux_cdda.c index 0f34a7cec..6aee5042e 100644 --- a/src/demuxers/demux_cdda.c +++ b/src/demuxers/demux_cdda.c @@ -60,6 +60,7 @@ typedef struct { input_plugin_t *input; int status; + int send_newpts; int seek_flag; /* this is set when a seek just occurred */ } demux_cdda_t; @@ -83,7 +84,7 @@ static int demux_cdda_send_chunk (demux_plugin_t *this_gen) { buf->type = BUF_AUDIO_LPCM_LE; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->pts = this->input->get_current_pos(this->input); buf->pts *= 90000; @@ -91,9 +92,9 @@ static int demux_cdda_send_chunk (demux_plugin_t *this_gen) { buf->extra_info->input_time = buf->pts / 90; buf->decoder_flags |= BUF_FLAG_FRAME_END; - if (this->seek_flag) { - _x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK); - this->seek_flag = 0; + if (this->send_newpts) { + _x_demux_control_newpts(this->stream, buf->pts, this->seek_flag); + this->send_newpts = this->seek_flag = 0; } this->audio_fifo->put (this->audio_fifo, buf); @@ -146,9 +147,14 @@ static int demux_cdda_seek (demux_plugin_t *this_gen, off_t start_pos, int start this->input->seek(this->input, start_pos & ~3, SEEK_SET); else this->input->seek(this->input, start_time * CD_BYTES_PER_SECOND, SEEK_SET); - this->seek_flag = 1; + this->status = DEMUX_OK; - _x_demux_flush_engine (this->stream); + + this->send_newpts = 1; + if (playing) { + this->seek_flag = BUF_FLAG_SEEK; + _x_demux_flush_engine (this->stream); + } return this->status; } @@ -187,7 +193,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_cdda_t *this; - this = xine_xmalloc (sizeof (demux_cdda_t)); + this = calloc(1, sizeof(demux_cdda_t)); this->stream = stream; this->input = input; @@ -250,7 +256,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_cdda_init_plugin (xine_t *xine, void *data) { demux_cdda_class_t *this; - this = xine_xmalloc (sizeof (demux_cdda_class_t)); + this = calloc(1, sizeof(demux_cdda_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c index 7c9b47fcd..0c73877e9 100644 --- a/src/demuxers/demux_dts.c +++ b/src/demuxers/demux_dts.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005 the xine project + * Copyright (C) 2005-2008 the xine project * * This file is part of xine, a free video player. * @@ -33,6 +33,9 @@ #ifdef HAVE_ALLOCA_H #include <alloca.h> #endif +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif #define LOG_MODULE "demux_dts" #define LOG_VERBOSE @@ -140,29 +143,69 @@ static int open_dts_file(demux_dts_t *this) { } } + /* DTS bitstream encoding version + * -1 - not detected + * 0 - 16 bits and big endian + * 1 - 16 bits and low endian (detection not implemented) + * 2 - 14 bits and big endian (detection not implemented) + * 3 - 14 bits and low endian + */ + int dts_version = -1; + /* Look for a valid DTS syncword */ for (i=offset; i<peak_size-1; i++) { + /* 16 bits and big endian bitstream */ + if (syncword == 0x7ffe8001) { + dts_version = 0; + break; + } /* 14 bits and little endian bitstream */ - if ((syncword == 0xff1f00e8) && - ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) { - this->data_start = i-4; - lprintf("found DTS syncword at offset %d\n", i-4); - break; + else if ((syncword == 0xff1f00e8) && + ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) { + dts_version = 3; + break; } syncword = (syncword << 8) | peak[i]; } + if (dts_version == -1) { + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": unsupported DTS stream type, or not a DTS stream\n"); + return 0; + } + + this->data_start = i-4; + lprintf("found DTS syncword at offset %d\n", i-4); + if (i < peak_size-9) { unsigned int nblks, fsize, sfreq; + switch (dts_version) + { + case 0: /* BE16 */ + nblks = ((peak[this->data_start+4] & 0x01) << 6) | + ((peak[this->data_start+5] & 0xfc) >> 2); + fsize = (((peak[this->data_start+5] & 0x03) << 12) |(peak[this->data_start+6] << 4) | + ((peak[this->data_start+7] & 0xf0) >> 4)) + 1; + sfreq = (peak[this->data_start+8] & 0x3c) >> 2; + break; - /* 14 bits and little endian bitstream */ - nblks = ((peak[this->data_start+4] & 0x07) << 4) | - ((peak[this->data_start+7] & 0x3c) >> 2); - fsize = (((peak[this->data_start+7] & 0x03) << 12) | - (peak[this->data_start+6] << 4) | - ((peak[this->data_start+9] & 0x3c) >> 2)) + 1; - sfreq = peak[this->data_start+8] & 0x0f; + case 3: /* LE14 */ + nblks = ((peak[this->data_start+4] & 0x07) << 4) | + ((peak[this->data_start+7] & 0x3c) >> 2); + fsize = (((peak[this->data_start+7] & 0x03) << 12) | + (peak[this->data_start+6] << 4) | + ((peak[this->data_start+9] & 0x3c) >> 2)) + 1; + sfreq = peak[this->data_start+8] & 0x0f; + break; + + default: + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": unsupported DTS bitstream encoding %d\n", + dts_version); + return 0; + + } if ((sfreq > sizeof(dts_sample_rates)/sizeof(int)) || (dts_sample_rates[sfreq] == 0)) @@ -170,7 +213,19 @@ static int open_dts_file(demux_dts_t *this) { /* Big assumption - this is CBR data */ this->samples_per_frame = (nblks + 1) * 32; - this->frame_size = fsize * 8 / 14 * 2; + + switch (dts_version) + { + case 0: /* BE16 */ + case 1: /* LE16 */ + this->frame_size = fsize * 8 / 16 * 2; + break; + case 2: /* BE14 */ + case 3: /* LE14 */ + this->frame_size = fsize * 8 / 14 * 2; + break; + } + this->sample_rate = dts_sample_rates[sfreq]; lprintf("samples per frame: %d\n", this->samples_per_frame); @@ -195,7 +250,7 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) { int frame_number; uint32_t blocksize; - current_stream_pos = this->input->get_current_pos(this->input) - + current_stream_pos = this->input->get_current_pos(this->input) - this->data_start; frame_number = current_stream_pos / this->frame_size; @@ -219,11 +274,11 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) { } } else { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->size = this->input->read(this->input, buf->content, + buf->size = this->input->read(this->input, buf->content, this->frame_size); } - if (buf->size == 0) { + if (buf->size <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; @@ -231,7 +286,7 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) { buf->type = BUF_AUDIO_DTS; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) current_stream_pos * + buf->extra_info->input_normpos = (int)( (double) current_stream_pos * 65535 / (this->input->get_length(this->input) - this->data_start) ); buf->extra_info->input_time = audio_pts / 90; buf->pts = audio_pts; @@ -305,7 +360,7 @@ static int demux_dts_seek (demux_plugin_t *this_gen, if (start_time) { int length = demux_dts_get_stream_length (this_gen); if (length != 0) { - start_pos = start_time * + start_pos = start_time * (this->input->get_length(this->input) - this->data_start) / length; } } @@ -346,7 +401,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_dts_t *this; - this = xine_xmalloc (sizeof (demux_dts_t)); + this = calloc(1, sizeof(demux_dts_t)); this->stream = stream; this->input = input; @@ -418,7 +473,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_dts_init_plugin (xine_t *xine, void *data) { demux_dts_class_t *this; - this = xine_xmalloc (sizeof (demux_dts_class_t)); + this = calloc(1, sizeof(demux_dts_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_eawve.c b/src/demuxers/demux_eawve.c index 2359d3baf..2e393847c 100644 --- a/src/demuxers/demux_eawve.c +++ b/src/demuxers/demux_eawve.c @@ -78,16 +78,16 @@ typedef struct { */ static uint32_t read_arbitary(input_plugin_t *input){ - uint8_t size, byte; - int i; - uint32_t word; + uint8_t size; if (input->read(input, (void*)&size, 1) != 1) { return 0; } - word = 0; + uint32_t word = 0; + int i; for (i=0;i<size;i++) { + uint8_t byte; if (input->read(input, (void*)&byte, 1) != 1) { return 0; } @@ -104,33 +104,25 @@ static uint32_t read_arbitary(input_plugin_t *input){ */ static int process_header(demux_eawve_t *this){ - int inHeader; - uint32_t blockid, size; + uint8_t header[12]; if (this->input->get_current_pos(this->input) != 0) this->input->seek(this->input, 0, SEEK_SET); - if (this->input->read(this->input, (void*)&blockid, 4) != 4) { - return 0; - } - if (be2me_32(blockid) != FOURCC_TAG('S', 'C', 'H', 'l')) { + if (this->input->read(this->input, header, sizeof(header)) != sizeof(header)) return 0; - } - if (this->input->read(this->input, (void*)&size, 4) != 4) { + if (!_x_is_fourcc(&header[0], "SCHl")) return 0; - } - size = le2me_32(size); - if (this->input->read(this->input, (void*)&blockid, 4) != 4) { - return 0; - } - if (be2me_32(blockid) != FOURCC_TAG('P', 'T', '\0', '\0')) { + if (!_x_is_fourcc(&header[8], "PT\0\0")) { lprintf("PT header missing\n"); return 0; } - inHeader = 1; + const uint32_t size = _X_LE_32(&header[4]); + + int inHeader = 1; while (inHeader) { int inSubheader; uint8_t byte; @@ -221,7 +213,7 @@ static int demux_eawve_send_chunk(demux_eawve_t *this){ buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); buf->type = BUF_AUDIO_EA_ADPCM; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = (int)((int64_t)this->sample_counter * 1000 / 22050); buf->pts = this->sample_counter; @@ -349,7 +341,7 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre if (!INPUT_IS_SEEKABLE(input)) return NULL; - this = xine_xmalloc(sizeof(demux_eawve_t)); + this = calloc(1, sizeof(demux_eawve_t)); this->stream = stream; this->input = input; @@ -421,7 +413,7 @@ static void class_dispose(demux_class_t *this){ void *demux_eawve_init_plugin(xine_t *xine, void *data) { demux_eawve_class_t *this; - this = xine_xmalloc(sizeof(demux_eawve_class_t)); + this = calloc(1, sizeof(demux_eawve_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index d0a821504..d38fe3c62 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -46,7 +46,7 @@ #define NUM_PREVIEW_BUFFERS 50 #define SCRATCH_SIZE 256 -typedef struct { +typedef struct { demux_plugin_t demux_plugin; xine_stream_t *stream; @@ -83,7 +83,7 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) { buf->content = buf->mem; buf->pts = 0; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->type = BUF_VIDEO_MPEG; @@ -91,7 +91,7 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) { buf->decoder_flags = BUF_FLAG_PREVIEW; this->video_fifo->put(this->video_fifo, buf); - + return 1; } @@ -240,7 +240,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_mpeg_elem_t)); + this = calloc(1, sizeof(demux_mpeg_elem_t)); this->stream = stream; this->input = input; @@ -284,7 +284,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_mpeg_elem_class_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_elem_class_t)); + this = calloc(1, sizeof(demux_mpeg_elem_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; @@ -304,7 +304,7 @@ static const demuxer_info_t demux_info_elem = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "elem", XINE_VERSION_CODE, &demux_info_elem, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c index 13036afc1..a8bd0b288 100644 --- a/src/demuxers/demux_film.c +++ b/src/demuxers/demux_film.c @@ -141,9 +141,9 @@ static int open_film_file(demux_film_t *film) { return 0; /* FILM signature correct? */ - if (strncmp(scratch, "FILM", 4)) { + if (!_x_is_fourcc(scratch, "FILM")) return 0; - } + llprintf(DEBUG_FILM_LOAD, "found 'FILM' signature\n"); /* file is qualified; skip over the header bytes in the stream */ @@ -151,7 +151,7 @@ static int open_film_file(demux_film_t *film) { /* header size = header size - 16-byte FILM signature */ film_header_size = _X_BE_32(&scratch[4]) - 16; - film_header = xine_xmalloc(film_header_size); + film_header = malloc(film_header_size); if (!film_header) return 0; strncpy(film->version, &scratch[8], 4); @@ -163,7 +163,7 @@ static int open_film_file(demux_film_t *film) { film->version[3]); /* load the rest of the FILM header */ - if (film->input->read(film->input, film_header, film_header_size) != + if (film->input->read(film->input, film_header, film_header_size) != film_header_size) { free (film->interleave_buffer); free (film->sample_table); @@ -202,7 +202,7 @@ static int open_film_file(demux_film_t *film) { if( !film->video_type ) film->video_type = BUF_VIDEO_UNKNOWN; - + /* fetch the audio information if the chunk size checks out */ if (chunk_size == 32) { film->audio_channels = film_header[21]; @@ -256,7 +256,9 @@ static int open_film_file(demux_film_t *film) { film->frequency = _X_BE_32(&film_header[i + 8]); film->sample_count = _X_BE_32(&film_header[i + 12]); film->sample_table = - xine_xmalloc(film->sample_count * sizeof(film_sample_t)); + calloc(film->sample_count, sizeof(film_sample_t)); + if (!film->sample_table) + goto film_abort; for (j = 0; j < film->sample_count; j++) { film->sample_table[j].sample_offset = @@ -329,15 +331,16 @@ static int open_film_file(demux_film_t *film) { /* allocate enough space in the interleave preload buffer for the * first chunk (which will be more than enough for successive chunks) */ if (film->audio_type) { - if (film->interleave_buffer) - free(film->interleave_buffer); - film->interleave_buffer = - xine_xmalloc(film->sample_table[0].sample_size); + free(film->interleave_buffer); + film->interleave_buffer = calloc(1, film->sample_table[0].sample_size); + if (!film->interleave_buffer) + goto film_abort; } break; default: xine_log(film->stream->xine, XINE_LOG_MSG, _("unrecognized FILM chunk\n")); + film_abort: free (film->interleave_buffer); free (film->sample_table); free (film_header); @@ -385,7 +388,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { } /* check if we're only sending audio samples until the next keyframe */ - if ((this->waiting_for_keyframe) && + if ((this->waiting_for_keyframe) && (!this->sample_table[i].audio)) { if (this->sample_table[i].keyframe) { this->waiting_for_keyframe = 0; @@ -425,7 +428,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { /* set the frame duration */ buf->decoder_flags |= BUF_FLAG_FRAMERATE; buf->decoder_info[0] = this->sample_table[i].duration; - + if (remaining_sample_bytes > buf->max_size) buf->size = buf->max_size; else @@ -440,11 +443,11 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { } /* skip over the extra non-spec CVID bytes */ - this->input->seek(this->input, + this->input->seek(this->input, this->sample_table[i].sample_size - cvid_chunk_size, SEEK_CUR); /* load the rest of the chunk */ - if (this->input->read(this->input, buf->content + 10, + if (this->input->read(this->input, buf->content + 10, buf->size - 10) != buf->size - 10) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; @@ -496,7 +499,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { /* set the frame duration */ buf->decoder_flags |= BUF_FLAG_FRAMERATE; buf->decoder_info[0] = this->sample_table[i].duration; - + if (remaining_sample_bytes > buf->max_size) buf->size = buf->max_size; else @@ -624,8 +627,8 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { buf->content[j] = this->interleave_buffer[k]; buf->content[j + 1] = this->interleave_buffer[k + 1]; } - for (j = 2, - k = interleave_index + this->sample_table[i].sample_size / 2; + for (j = 2, + k = interleave_index + this->sample_table[i].sample_size / 2; j < buf->size; j += 4, k += 2) { buf->content[j] = this->interleave_buffer[k]; buf->content[j + 1] = this->interleave_buffer[k + 1]; @@ -635,8 +638,8 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { for (j = 0, k = interleave_index; j < buf->size; j += 2, k += 1) { buf->content[j] = this->interleave_buffer[k] += 0x80; } - for (j = 1, - k = interleave_index + this->sample_table[i].sample_size / 2; + for (j = 1, + k = interleave_index + this->sample_table[i].sample_size / 2; j < buf->size; j += 2, k += 1) { buf->content[j] = this->interleave_buffer[k] += 0x80; } @@ -651,7 +654,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) { this->audio_fifo->put(this->audio_fifo, buf); } } - + return this->status; } @@ -734,13 +737,13 @@ static int demux_film_seek (demux_plugin_t *this_gen, off_t start_pos, int start this->waiting_for_keyframe = 0; this->last_sample = 0; } - + /* if input is non-seekable, do not proceed with the rest of this * seek function */ if (!INPUT_IS_SEEKABLE(this->input)) return this->status; - /* perform a binary search on the sample table, testing the offset + /* perform a binary search on the sample table, testing the offset * boundaries first */ if (start_pos) { if (start_pos <= 0) @@ -757,7 +760,7 @@ static int demux_film_seek (demux_plugin_t *this_gen, off_t start_pos, int start while (!found) { middle = (left + right) / 2; if ((start_pos >= this->sample_table[middle].sample_offset) && - (start_pos <= this->sample_table[middle].sample_offset + + (start_pos <= this->sample_table[middle].sample_offset + this->sample_table[middle].sample_size)) { found = 1; } else if (start_pos < this->sample_table[middle].sample_offset) { @@ -814,7 +817,7 @@ static int demux_film_seek (demux_plugin_t *this_gen, off_t start_pos, int start } this->current_sample = best_index; - + return this->status; } @@ -853,7 +856,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_film_t *this; - this = xine_xmalloc (sizeof (demux_film_t)); + this = calloc(1, sizeof(demux_film_t)); this->stream = stream; this->input = input; @@ -927,7 +930,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_film_init_plugin (xine_t *xine, void *data) { demux_film_class_t *this; - this = xine_xmalloc (sizeof (demux_film_class_t)); + this = calloc(1, sizeof(demux_film_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c index 3afb5b031..976656016 100644 --- a/src/demuxers/demux_flac.c +++ b/src/demuxers/demux_flac.c @@ -33,6 +33,9 @@ #include <unistd.h> #include <string.h> #include <stdlib.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif #define LOG_MODULE "demux_flac" #define LOG_VERBOSE @@ -116,7 +119,7 @@ static int open_flac_file(demux_flac_t *flac) { * will always be 1 metadata block */ do { - if (flac->input->read(flac->input, preamble, FLAC_SIGNATURE_SIZE) != + if (flac->input->read(flac->input, preamble, FLAC_SIGNATURE_SIZE) != FLAC_SIGNATURE_SIZE) return 0; @@ -130,11 +133,11 @@ static int open_flac_file(demux_flac_t *flac) { case 0: lprintf ("STREAMINFO metadata\n"); if (block_length != FLAC_STREAMINFO_SIZE) { - lprintf ("expected STREAMINFO chunk of %d bytes\n", + lprintf ("expected STREAMINFO chunk of %d bytes\n", FLAC_STREAMINFO_SIZE); return 0; } - if (flac->input->read(flac->input, + if (flac->input->read(flac->input, flac->streaminfo + sizeof(xine_waveformatex), FLAC_STREAMINFO_SIZE) != FLAC_STREAMINFO_SIZE) return 0; @@ -143,8 +146,8 @@ static int open_flac_file(demux_flac_t *flac) { flac->bits_per_sample = ((flac->sample_rate >> 4) & 0x1F) + 1; flac->sample_rate >>= 12; flac->total_samples = _X_BE_64(&streaminfo[10]) & UINT64_C(0x0FFFFFFFFF); /* 36 bits */ - lprintf ("%d Hz, %d bits, %d channels, %"PRId64" total samples\n", - flac->sample_rate, flac->bits_per_sample, + lprintf ("%d Hz, %d bits, %d channels, %"PRId64" total samples\n", + flac->sample_rate, flac->bits_per_sample, flac->channels, flac->total_samples); break; @@ -164,8 +167,10 @@ static int open_flac_file(demux_flac_t *flac) { case 3: lprintf ("SEEKTABLE metadata, %d bytes\n", block_length); flac->seekpoint_count = block_length / FLAC_SEEKPOINT_SIZE; - flac->seekpoints = xine_xmalloc(flac->seekpoint_count * + flac->seekpoints = calloc(flac->seekpoint_count, sizeof(flac_seekpoint_t)); + if (flac->seekpoint_count && !flac->seekpoints) + return 0; for (i = 0; i < flac->seekpoint_count; i++) { if (flac->input->read(flac->input, buffer, FLAC_SEEKPOINT_SIZE) != FLAC_SEEKPOINT_SIZE) return 0; @@ -173,7 +178,7 @@ static int open_flac_file(demux_flac_t *flac) { lprintf (" %d: sample %"PRId64", ", i, flac->seekpoints[i].sample_number); flac->seekpoints[i].offset = _X_BE_64(&buffer[8]); flac->seekpoints[i].size = _X_BE_16(&buffer[16]); - lprintf ("@ 0x%"PRIX64", size = %d bytes, ", + lprintf ("@ 0x%"PRIX64", size = %d bytes, ", flac->seekpoints[i].offset, flac->seekpoints[i].size); flac->seekpoints[i].pts = flac->seekpoints[i].sample_number; flac->seekpoints[i].pts *= 90000; @@ -182,14 +187,14 @@ static int open_flac_file(demux_flac_t *flac) { } break; - /* VORBIS_COMMENT + /* VORBIS_COMMENT * * For a description of the format please have a look at * http://www.xiph.org/vorbis/doc/v-comment.html */ case 4: lprintf ("VORBIS_COMMENT metadata\n"); { - char comments[block_length]; + char comments[block_length + 1]; /* last byte for NUL termination */ char *ptr = comments; uint32_t length, user_comment_list_length; int cn; @@ -202,27 +207,37 @@ static int open_flac_file(demux_flac_t *flac) { length = _X_LE_32(ptr); ptr += 4 + length; + if (length > block_length - 8) + return 0; /* bad length or too little left in the buffer */ user_comment_list_length = _X_LE_32(ptr); ptr += 4; cn = 0; for (; cn < user_comment_list_length; cn++) { + if (ptr > comments + block_length - 4) + return 0; /* too little left in the buffer */ + length = _X_LE_32(ptr); ptr += 4; + if (length >= block_length || ptr + length > comments + block_length) + return 0; /* bad length */ comment = (char*) ptr; c = comment[length]; - comment[length] = 0; + comment[length] = 0; /* NUL termination */ lprintf ("comment[%02d] = %s\n", cn, comment); - if ((strncasecmp ("TITLE=", comment, 6) == 0) + if ((strncasecmp ("TITLE=", comment, 6) == 0) && (length - 6 > 0)) { _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_TITLE, comment + 6); } else if ((strncasecmp ("ARTIST=", comment, 7) == 0) && (length - 7 > 0)) { _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_ARTIST, comment + 7); + } else if ((strncasecmp ("COMPOSER=", comment, 9) == 0) + && (length - 9 > 0)) { + _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_COMPOSER, comment + 9); } else if ((strncasecmp ("ALBUM=", comment, 6) == 0) && (length - 6 > 0)) { _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_ALBUM, comment + 6); @@ -248,8 +263,8 @@ static int open_flac_file(demux_flac_t *flac) { } if ((tracknumber > 0) && (tracktotal > 0)) { - char tn[16]; - snprintf (tn, 16, "%02d/%02d", tracknumber, tracktotal); + char tn[24]; + snprintf (tn, 24, "%02d/%02d", tracknumber, tracktotal); _x_meta_info_set(flac->stream, XINE_META_INFO_TRACK_NUMBER, tn); } else if (tracknumber > 0) { @@ -381,12 +396,13 @@ static int demux_flac_seek (demux_plugin_t *this_gen, demux_flac_t *this = (demux_flac_t *) this_gen; int seekpoint_index = 0; int64_t start_pts; - + unsigned char buf[4]; + start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); /* if thread is not running, initialize demuxer */ - if( !playing ) { + if( !playing && !start_pos) { /* send new pts */ _x_demux_control_newpts(this->stream, 0, 0); @@ -394,28 +410,39 @@ static int demux_flac_seek (demux_plugin_t *this_gen, this->status = DEMUX_OK; } else { - if (this->seekpoints == NULL) { + if (this->seekpoints == NULL && !start_pos) { /* cannot seek if there is no seekpoints */ this->status = DEMUX_OK; return this->status; } - /* do a lazy, linear seek based on the assumption that there are not - * that many seek points */ + /* Don't use seekpoints if start_pos != 0. This allows smooth seeking */ if (start_pos) { /* offset-based seek */ - if (start_pos < this->seekpoints[0].offset) - seekpoint_index = 0; - else { - for (seekpoint_index = 0; seekpoint_index < this->seekpoint_count - 1; - seekpoint_index++) { - if (start_pos < this->seekpoints[seekpoint_index + 1].offset) { - break; - } - } + this->status = DEMUX_OK; + start_pos += this->data_start; + this->input->seek(this->input, start_pos, SEEK_SET); + while(1){ /* here we try to find something that resembles a frame header */ + + if (this->input->read(this->input, buf, 2) != 2){ + this->status = DEMUX_FINISHED; /* we sought past the end of stream ? */ + break; + } + + if (buf[0] == 0xff && buf[1] == 0xf8) + break; /* this might be the frame header... or it may be not. We pass it to the decoder + * to decide, but this way we reduce the number of warnings */ + start_pos +=2; } + + _x_demux_flush_engine(this->stream); + this->input->seek(this->input, start_pos, SEEK_SET); + _x_demux_control_newpts(this->stream, 0, BUF_FLAG_SEEK); + return this->status; + } else { - /* time-based seek */ + /* do a lazy, linear seek based on the assumption that there are not + * that many seek points; time-based seek */ start_pts = start_time; start_pts *= 90; if (start_pts < this->seekpoints[0].pts) @@ -431,9 +458,9 @@ static int demux_flac_seek (demux_plugin_t *this_gen, } _x_demux_flush_engine(this->stream); - this->input->seek(this->input, this->seekpoints[seekpoint_index].offset, + this->input->seek(this->input, this->seekpoints[seekpoint_index].offset, SEEK_SET); - _x_demux_control_newpts(this->stream, + _x_demux_control_newpts(this->stream, this->seekpoints[seekpoint_index].pts, BUF_FLAG_SEEK); } @@ -444,6 +471,7 @@ static void demux_flac_dispose (demux_plugin_t *this_gen) { demux_flac_t *this = (demux_flac_t *) this_gen; free(this->seekpoints); + free(this); } static int demux_flac_get_status (demux_plugin_t *this_gen) { @@ -482,7 +510,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_flac_t)); + this = calloc(1, sizeof(demux_flac_t)); this->stream = stream; this->input = input; @@ -544,7 +572,8 @@ static const char *get_extensions (demux_class_t *this_gen) { } static const char *get_mimetypes (demux_class_t *this_gen) { - return NULL; + return "audio/x-flac: flac: FLAC Audio;" + "audio/flac: flac: FLAC Audio;"; } static void class_dispose (demux_class_t *this_gen) { @@ -556,7 +585,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_flac_init_plugin (xine_t *xine, void *data) { demux_flac_class_t *this; - this = xine_xmalloc (sizeof (demux_flac_class_t)); + this = calloc(1, sizeof(demux_flac_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_fli.c b/src/demuxers/demux_fli.c index 99843a68c..7735671b9 100644 --- a/src/demuxers/demux_fli.c +++ b/src/demuxers/demux_fli.c @@ -112,7 +112,7 @@ static int open_fli_file(demux_fli_t *this) { this->speed = _X_LE_32(&this->fli_header[16]); if (this->magic_number == FLI_FILE_MAGIC_1) { - /* + /* * in this case, the speed (n) is number of 1/70s ticks between frames: * * xine pts n * frame # @@ -123,7 +123,7 @@ static int open_fli_file(demux_fli_t *this) { */ this->frame_pts_inc = this->speed * 1285.7; } else if (this->magic_number == FLI_FILE_MAGIC_2) { - /* + /* * in this case, the speed (n) is number of milliseconds between frames: * * xine pts n * frame # @@ -244,7 +244,7 @@ static void demux_fli_send_headers(demux_plugin_t *this_gen) { BUF_FLAG_FRAME_END; buf->decoder_info[0] = this->frame_pts_inc; /* initial video_step */ buf->size = this->bih.biSize; - memcpy(buf->content, &this->bih, sizeof(xine_bmiheader) + this->bih.biSize); + memcpy(buf->content, &this->bih, this->bih.biSize); buf->type = BUF_VIDEO_FLI; this->video_fifo->put (this->video_fifo, buf); } @@ -303,7 +303,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_fli_t *this; - this = xine_xmalloc (sizeof (demux_fli_t)); + this = calloc(1, sizeof(demux_fli_t)); this->stream = stream; this->input = input; @@ -377,7 +377,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_fli_class_t *this; - this = xine_xmalloc (sizeof (demux_fli_class_t)); + this = calloc(1, sizeof(demux_fli_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_flv.c b/src/demuxers/demux_flv.c index bdb33d21d..813f33086 100644 --- a/src/demuxers/demux_flv.c +++ b/src/demuxers/demux_flv.c @@ -20,11 +20,11 @@ /* * Flash Video (.flv) File Demuxer - * by Mike Melanson (melanson@pcisys.net) and - * Claudio Ciccani (klan@directfb.org) + * by Mike Melanson (melanson@pcisys.net) and + * Claudio Ciccani (klan@users.sf.net) * * For more information on the FLV file format, visit: - * http://download.macromedia.com/pub/flash/flash_file_format_specification.pdf + * http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v9.pdf */ #ifdef HAVE_CONFIG_H @@ -67,28 +67,28 @@ typedef struct { unsigned char flags; off_t start; /* in bytes */ off_t size; /* in bytes */ - + unsigned char got_video_header; unsigned char got_audio_header; - + unsigned int length; /* in ms */ int width; int height; int duration; int videocodec; - + int samplerate; int samplesize; int stereo; int audiocodec; - + off_t filesize; - + flv_index_entry_t *index; - int num_indices; - + unsigned int num_indices; + unsigned int cur_pts; - + int64_t last_pts[2]; int send_newpts; int buf_flag_seek; @@ -110,14 +110,20 @@ typedef struct { #define FLV_SOUND_FORMAT_ADPCM 0x01 #define FLV_SOUND_FORMAT_MP3 0x02 #define FLV_SOUND_FORMAT_PCM_LE 0x03 +#define FLV_SOUND_FORMAT_NELLY16 0x04 /* Nellymoser 16KHz */ #define FLV_SOUND_FORMAT_NELLY8 0x05 /* Nellymoser 8KHz */ #define FLV_SOUND_FORMAT_NELLY 0x06 /* Nellymoser */ +#define FLV_SOUND_FORMAT_ALAW 0x07 /* G.711 A-LAW */ +#define FLV_SOUND_FORMAT_MULAW 0x08 /* G.711 MU-LAW */ +#define FLV_SOUND_FORMAT_AAC 0x0a +#define FLV_SOUND_FORMAT_MP38 0x0e /* MP3 8KHz */ #define FLV_VIDEO_FORMAT_FLV1 0x02 /* Sorenson H.263 */ #define FLV_VIDEO_FORMAT_SCREEN 0x03 #define FLV_VIDEO_FORMAT_VP6 0x04 /* On2 VP6 */ #define FLV_VIDEO_FORMAT_VP6A 0x05 /* On2 VP6 with alphachannel */ #define FLV_VIDEO_FORMAT_SCREEN2 0x06 +#define FLV_VIDEO_FORMAT_H264 0x07 #define FLV_DATA_TYPE_NUMBER 0x00 #define FLV_DATA_TYPE_BOOL 0x01 @@ -172,7 +178,7 @@ static int open_flv_file(demux_flv_t *this) { if ((buffer[0] != 'F') || (buffer[1] != 'L') || (buffer[2] != 'V')) return 0; - + if (buffer[3] != 0x01) { xprintf(this->xine, XINE_VERBOSITY_LOG, _("unsupported FLV version (%d).\n"), buffer[3]); @@ -188,10 +194,10 @@ static int open_flv_file(demux_flv_t *this) { this->start = _X_BE_32(&buffer[5]); this->size = this->input->get_length(this->input); - + this->input->seek(this->input, this->start, SEEK_SET); - - lprintf(" qualified FLV file, repositioned @ offset 0x%" PRIxMAX "\n", + + lprintf(" qualified FLV file, repositioned @ offset 0x%" PRIxMAX "\n", (intmax_t)this->start); return 1; @@ -203,19 +209,19 @@ static int open_flv_file(demux_flv_t *this) { _tmp.d;\ })\ -static int parse_flv_var(demux_flv_t *this, +static int parse_flv_var(demux_flv_t *this, unsigned char *buf, int size, char *key, int keylen) { unsigned char *tmp = buf; unsigned char *end = buf + size; char *str; unsigned char type; - int len, num; - + unsigned int len, num; + if (size < 1) return 0; - + type = *tmp++; - + switch (type) { case FLV_DATA_TYPE_NUMBER: lprintf(" got number (%f)\n", BE_F64(tmp)); @@ -283,6 +289,8 @@ static int parse_flv_var(demux_flv_t *this, str = tmp + 2; tmp += len + 2; len = parse_flv_var(this, tmp, end-tmp, str, len); + if (!len) + return 0; tmp += len; } if (*tmp++ != FLV_DATA_TYPE_ENDOBJECT) @@ -298,6 +306,8 @@ static int parse_flv_var(demux_flv_t *this, str = tmp + 2; tmp += len + 2; len = parse_flv_var(this, tmp, end-tmp, str, len); + if (!len) + return 0; tmp += len; } break; @@ -306,10 +316,14 @@ static int parse_flv_var(demux_flv_t *this, num = _X_BE_32(tmp); tmp += 4; if (key && keylen == 5 && !strncmp(key, "times", 5)) { - if (this->index) - free (this->index); - this->index = xine_xmalloc(num*sizeof(flv_index_entry_t)); - this->num_indices = num; + if (!this->index || this->num_indices != num) { + if (this->index) + free(this->index); + this->index = calloc(num, sizeof(flv_index_entry_t)); + if (!this->index) + return 0; + this->num_indices = num; + } for (num = 0; num < this->num_indices && tmp < end; num++) { if (*tmp++ == FLV_DATA_TYPE_NUMBER) { lprintf(" got number (%f)\n", BE_F64(tmp)); @@ -320,19 +334,27 @@ static int parse_flv_var(demux_flv_t *this, break; } if (key && keylen == 13 && !strncmp(key, "filepositions", 13)) { - if (this->index && this->num_indices == num) { - for (num = 0; num < this->num_indices && tmp < end; num++) { - if (*tmp++ == FLV_DATA_TYPE_NUMBER) { - lprintf(" got number (%f)\n", BE_F64(tmp)); - this->index[num].offset = BE_F64(tmp); - tmp += 8; - } + if (!this->index || this->num_indices != num) { + if (this->index) + free(this->index); + this->index = calloc(num, sizeof(flv_index_entry_t)); + if (!this->index) + return 0; + this->num_indices = num; + } + for (num = 0; num < this->num_indices && tmp < end; num++) { + if (*tmp++ == FLV_DATA_TYPE_NUMBER) { + lprintf(" got number (%f)\n", BE_F64(tmp)); + this->index[num].offset = BE_F64(tmp); + tmp += 8; } - break; } + break; } while (num-- && tmp < end) { len = parse_flv_var(this, tmp, end-tmp, NULL, 0); + if (!len) + return 0; tmp += len; } break; @@ -344,17 +366,17 @@ static int parse_flv_var(demux_flv_t *this, lprintf(" got type %d\n", type); break; } - + return (tmp - buf); } static void parse_flv_script(demux_flv_t *this, int size) { - unsigned char *buf = xine_xmalloc(size); + unsigned char *buf = malloc(size); unsigned char *tmp = buf; unsigned char *end = buf + size; int len; - - if (this->input->read(this->input, buf, size ) != size) { + + if (!buf || this->input->read(this->input, buf, size ) != size) { this->status = DEMUX_FINISHED; free(buf); return; @@ -366,7 +388,7 @@ static void parse_flv_script(demux_flv_t *this, int size) { break; tmp += len; } - + free(buf); } @@ -379,7 +401,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) { unsigned int buf_type = 0; unsigned int buf_flags = 0; unsigned int pts; - + while (1) { lprintf (" reading FLV tag...\n"); this->input->seek(this->input, 4, SEEK_CUR); @@ -391,7 +413,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) { tag_type = buffer[0]; remaining_bytes = _X_BE_24(&buffer[1]); pts = _X_BE_24(&buffer[4]) | (buffer[7] << 24); - + lprintf(" tag_type = 0x%02X, 0x%X bytes, pts %u\n", tag_type, remaining_bytes, pts/90); @@ -400,10 +422,10 @@ static int read_flv_packet(demux_flv_t *this, int preview) { lprintf(" got audio tag..\n"); if (this->input->read(this->input, buffer, 1) != 1) { this->status = DEMUX_FINISHED; - return this->status; + return this->status; } remaining_bytes--; - + this->audiocodec = buffer[0] >> 4; /* override */ switch (this->audiocodec) { case FLV_SOUND_FORMAT_PCM_BE: @@ -413,17 +435,30 @@ static int read_flv_packet(demux_flv_t *this, int preview) { buf_type = BUF_AUDIO_FLVADPCM; break; case FLV_SOUND_FORMAT_MP3: + case FLV_SOUND_FORMAT_MP38: buf_type = BUF_AUDIO_MPEG; break; case FLV_SOUND_FORMAT_PCM_LE: buf_type = BUF_AUDIO_LPCM_LE; break; + case FLV_SOUND_FORMAT_ALAW: + buf_type = BUF_AUDIO_ALAW; + break; + case FLV_SOUND_FORMAT_MULAW: + buf_type = BUF_AUDIO_MULAW; + break; + case FLV_SOUND_FORMAT_AAC: + buf_type = BUF_AUDIO_AAC; + /* AAC extra header */ + this->input->read(this->input, buffer, 1 ); + remaining_bytes--; + break; default: lprintf(" unsupported audio format (%d)...\n", buffer[0] >> 4); buf_type = BUF_AUDIO_UNKNOWN; break; } - + fifo = this->audio_fifo; if (preview && !this->got_audio_header) { /* send init info to audio decoder */ @@ -439,7 +474,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) { this->got_audio_header = 1; } break; - + case FLV_TAG_TYPE_VIDEO: lprintf(" got video tag..\n"); if (this->input->read(this->input, buffer, 1) != 1) { @@ -447,10 +482,19 @@ static int read_flv_packet(demux_flv_t *this, int preview) { return this->status; } remaining_bytes--; - - if ((buffer[0] >> 4) == 0x01) - buf_flags = BUF_FLAG_KEYFRAME; - + + switch ((buffer[0] >> 4)) { + case 0x01: + buf_flags = BUF_FLAG_KEYFRAME; + break; + case 0x05: + /* skip server command */ + this->input->seek(this->input, remaining_bytes, SEEK_CUR); + continue; + default: + break; + } + this->videocodec = buffer[0] & 0x0F; /* override */ switch (this->videocodec) { case FLV_VIDEO_FORMAT_FLV1: @@ -468,17 +512,23 @@ static int read_flv_packet(demux_flv_t *this, int preview) { this->input->read(this->input, buffer, 4); remaining_bytes -= 4; break; + case FLV_VIDEO_FORMAT_H264: + buf_type = BUF_VIDEO_H264; + /* AVC extra header */ + this->input->read(this->input, buffer, 4); + remaining_bytes -= 4; + break; default: lprintf(" unsupported video format (%d)...\n", buffer[0] & 0x0F); buf_type = BUF_VIDEO_UNKNOWN; break; } - + fifo = this->video_fifo; if (preview && !this->got_video_header) { xine_bmiheader *bih; /* send init info to video decoder; send the bitmapinfo header to the decoder - * primarily as a formality since there is no real data inside */ + * primarily as a formality since there is no real data inside */ buf = fifo->buffer_pool_alloc(fifo); buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_STDHEADER | BUF_FLAG_FRAMERATE | BUF_FLAG_FRAME_END; @@ -495,16 +545,33 @@ static int read_flv_packet(demux_flv_t *this, int preview) { bih->biSize++; buf->size++; } + else if (buf_type == BUF_VIDEO_H264 && buffer[0] == 0) { + /* AVC sequence header */ + if (remaining_bytes > buf->max_size-buf->size) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("sequence header too big (%u bytes)!\n"), remaining_bytes); + this->input->read(this->input, buf->content+buf->size, buf->max_size-buf->size); + this->input->seek(this->input, remaining_bytes-buf->max_size-buf->size, SEEK_CUR); + bih->biSize = buf->max_size; + buf->size = buf->max_size; + } + else { + this->input->read(this->input, buf->content+buf->size, remaining_bytes); + bih->biSize += remaining_bytes; + buf->size += remaining_bytes; + } + remaining_bytes = 0; + } fifo->put(fifo, buf); this->got_video_header = 1; } break; - + case FLV_TAG_TYPE_SCRIPT: lprintf(" got script tag...\n"); - parse_flv_script(this, remaining_bytes); - if (preview) { + parse_flv_script(this, remaining_bytes); + /* send init info to decoders using script information as reference */ if (!this->got_audio_header && this->audiocodec) { buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); @@ -521,11 +588,21 @@ static int read_flv_packet(demux_flv_t *this, int preview) { buf->type = BUF_AUDIO_FLVADPCM; break; case FLV_SOUND_FORMAT_MP3: + case FLV_SOUND_FORMAT_MP38: buf->type = BUF_AUDIO_MPEG; break; case FLV_SOUND_FORMAT_PCM_LE: buf->type = BUF_AUDIO_LPCM_LE; break; + case FLV_SOUND_FORMAT_ALAW: + buf->type = BUF_AUDIO_ALAW; + break; + case FLV_SOUND_FORMAT_MULAW: + buf->type = BUF_AUDIO_MULAW; + break; + case FLV_SOUND_FORMAT_AAC: + buf->type = BUF_AUDIO_AAC; + break; default: buf->type = BUF_AUDIO_UNKNOWN; break; @@ -533,9 +610,10 @@ static int read_flv_packet(demux_flv_t *this, int preview) { buf->size = 0; this->audio_fifo->put(this->audio_fifo, buf); this->got_audio_header = 1; + lprintf(" got audio header from metadata...\n"); } - - if (!this->got_video_header && this->videocodec) { + + if (!this->got_video_header && this->videocodec && this->videocodec != FLV_VIDEO_FORMAT_H264) { xine_bmiheader *bih; buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_STDHEADER | @@ -567,57 +645,88 @@ static int read_flv_packet(demux_flv_t *this, int preview) { } this->video_fifo->put(this->video_fifo, buf); this->got_video_header = 1; + lprintf(" got video header from metadata...\n"); } - + return this->status; - } + } + /* no preview */ + this->input->seek(this->input, remaining_bytes, SEEK_CUR); continue; - + default: lprintf(" skipping packet...\n"); this->input->seek(this->input, remaining_bytes, SEEK_CUR); continue; } - + while (remaining_bytes) { buf = fifo->buffer_pool_alloc(fifo); buf->type = buf_type; - buf->pts = (int64_t) pts * 90; - - if (!preview) - check_newpts(this, buf->pts, (tag_type == FLV_TAG_TYPE_VIDEO)); - + buf->extra_info->input_time = pts; if (this->input->get_length(this->input)) { - buf->extra_info->input_normpos = + buf->extra_info->input_normpos = (int)((double)this->input->get_current_pos(this->input) * 65535.0 / this->size); } - if (remaining_bytes > buf->max_size) - buf->size = buf->max_size; - else - buf->size = remaining_bytes; - remaining_bytes -= buf->size; + if ((buf_type == BUF_VIDEO_H264 || buf_type == BUF_AUDIO_AAC) && buffer[0] == 0) { + /* AVC/AAC sequence header */ + buf->pts = 0; + buf->size = 0; - buf->decoder_flags = buf_flags; - if (preview) - buf->decoder_flags |= BUF_FLAG_PREVIEW; - if (!remaining_bytes) - buf->decoder_flags |= BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_SPECIAL | BUF_FLAG_HEADER; + if (preview) + buf->decoder_flags |= BUF_FLAG_PREVIEW; - if (this->input->read(this->input, buf->content, buf->size) != buf->size) { - buf->free_buffer(buf); - this->status = DEMUX_FINISHED; - break; + buf->decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG; + buf->decoder_info[2] = MIN(remaining_bytes, buf->max_size); + buf->decoder_info_ptr[2] = buf->mem; + + if (this->input->read(this->input, buf->mem, buf->decoder_info[2]) != buf->decoder_info[2]) { + buf->free_buffer(buf); + this->status = DEMUX_FINISHED; + break; + } + + if (remaining_bytes > buf->max_size) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("sequence header too big (%u bytes)!\n"), remaining_bytes); + this->input->seek(this->input, remaining_bytes-buf->max_size, SEEK_CUR); + } + remaining_bytes = 0; + } + else { + buf->pts = (int64_t) pts * 90; + if (!preview) + check_newpts(this, buf->pts, (tag_type == FLV_TAG_TYPE_VIDEO)); + + if (remaining_bytes > buf->max_size) + buf->size = buf->max_size; + else + buf->size = remaining_bytes; + remaining_bytes -= buf->size; + + buf->decoder_flags = buf_flags; + if (preview) + buf->decoder_flags |= BUF_FLAG_PREVIEW; + if (!remaining_bytes) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + + if (this->input->read(this->input, buf->content, buf->size) != buf->size) { + buf->free_buffer(buf); + this->status = DEMUX_FINISHED; + break; + } } fifo->put(fifo, buf); } - + this->cur_pts = pts; break; } - + return this->status; } @@ -628,52 +737,50 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) { int next_tag = 0; int do_rewind = (seek_pts < this->cur_pts); int i; - - lprintf(" seeking %s to %d...\n", + + lprintf(" seeking %s to %d...\n", do_rewind ? "backward" : "forward", seek_pts); - - if (seek_pts == 0) { + + if (seek_pos == 0 && seek_pts == 0) { this->input->seek(this->input, this->start, SEEK_SET); this->cur_pts = 0; return; } - + if (this->index) { if (do_rewind) { for (i = this->num_indices-1; i > 0; i--) { if (this->index[i-1].pts < seek_pts) break; } - } + } else { for (i = 0; i < (this->num_indices-1); i++) { if (this->index[i+1].pts > seek_pts) break; } } - + if (this->index[i].offset >= this->start+4) { - lprintf(" seeking to index entry %d (pts:%u, offset:%u).\n", + lprintf(" seeking to index entry %d (pts:%u, offset:%u).\n", i, this->index[i].pts, this->index[i].offset); this->input->seek(this->input, this->index[i].offset-4, SEEK_SET); this->cur_pts = this->index[i].pts; - return; } } - - if (seek_pos && this->videocodec) { + else if (seek_pos && this->videocodec && abs(seek_pts-this->cur_pts) > 300000) { off_t pos, size; - + pos = this->input->get_current_pos(this->input); size = this->filesize ? : this->input->get_length(this->input); this->input->seek(this->input, (uint64_t)size * seek_pos / 65535, SEEK_SET); lprintf(" resyncing...\n"); - + /* resync */ for (i = 0; i < 200000; i++) { uint8_t buf[4]; - + if (this->input->read(this->input, buf, 1) < 1) { this->status = DEMUX_FINISHED; return; @@ -694,58 +801,59 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) { this->input->seek(this->input, -11, SEEK_CUR); } } - + lprintf(" ...resync failed!\n"); this->input->seek(this->input, pos, SEEK_SET); - return; - } - - while (do_rewind ? (seek_pts < this->cur_pts) : (seek_pts > this->cur_pts)) { - unsigned char tag_type; - int data_size; - int ptag_size; - - if (next_tag) - this->input->seek(this->input, next_tag, SEEK_CUR); - - len = this->input->read(this->input, buffer, 16); - if (len != 16) { - len = (len < 0) ? 0 : len; - break; - } - - ptag_size = _X_BE_32(&buffer[0]); - tag_type = buffer[4]; - data_size = _X_BE_24(&buffer[5]); - pts = _X_BE_24(&buffer[8]) | (buffer[11] << 24); - - if (do_rewind) { - if (!ptag_size) break; /* beginning of movie */ - next_tag = -(ptag_size + 16 + 4); - } - else { - next_tag = data_size - 1; - } - - if (this->flags & FLV_FLAG_HAS_VIDEO) { - /* sync to video key frame */ - if (tag_type != FLV_TAG_TYPE_VIDEO || (buffer[15] >> 4) != 0x01) - continue; - lprintf(" video keyframe found at %d...\n", pts); + } + else if (seek_pts) { + while (do_rewind ? (seek_pts < this->cur_pts) : (seek_pts > this->cur_pts)) { + unsigned char tag_type; + int data_size; + int ptag_size; + + if (next_tag) + this->input->seek(this->input, next_tag, SEEK_CUR); + + len = this->input->read(this->input, buffer, 16); + if (len != 16) { + len = (len < 0) ? 0 : len; + break; + } + + ptag_size = _X_BE_32(&buffer[0]); + tag_type = buffer[4]; + data_size = _X_BE_24(&buffer[5]); + pts = _X_BE_24(&buffer[8]) | (buffer[11] << 24); + + if (do_rewind) { + if (!ptag_size) + break; /* beginning of movie */ + next_tag = -(ptag_size + 16 + 4); + } + else { + next_tag = data_size - 1; + } + + if (this->flags & FLV_FLAG_HAS_VIDEO) { + /* sync to video key frame */ + if (tag_type != FLV_TAG_TYPE_VIDEO || (buffer[15] >> 4) != 0x01) + continue; + lprintf(" video keyframe found at %d...\n", pts); + } + this->cur_pts = pts; } - this->cur_pts = pts; + + /* seek back to the beginning of the tag */ + this->input->seek(this->input, -len, SEEK_CUR); + + lprintf( " seeked to %d.\n", pts); } - - /* seek back to the beginning of the tag */ - this->input->seek(this->input, -len, SEEK_CUR); - - lprintf( " seeked to %d.\n", pts); } static int demux_flv_send_chunk(demux_plugin_t *this_gen) { demux_flv_t *this = (demux_flv_t *) this_gen; - + return read_flv_packet(this, 0); } @@ -757,11 +865,11 @@ static void demux_flv_send_headers(demux_plugin_t *this_gen) { this->audio_fifo = this->stream->audio_fifo; this->status = DEMUX_OK; - + this->buf_flag_seek = 1; /* load stream information */ - _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, (this->flags & FLV_FLAG_HAS_VIDEO) ? 1 : 0); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, (this->flags & FLV_FLAG_HAS_AUDIO) ? 1 : 0); @@ -789,18 +897,22 @@ static int demux_flv_seek (demux_plugin_t *this_gen, this->status = DEMUX_OK; if (INPUT_IS_SEEKABLE(this->input)) { - if (start_pos && !start_time) - start_time = (int64_t) this->length * start_pos / 65535; + if (start_pos && !start_time) { + if (this->length) + start_time = (int64_t) this->length * start_pos / 65535; + else if (this->index) + start_time = this->index[(int)(start_pos * (this->num_indices-1) / 65535)].pts; + } if (!this->length || start_time < this->length) { seek_flv_file(this, start_pos, start_time); - + if (playing) { this->buf_flag_seek = 1; _x_demux_flush_engine(this->stream); } } - } + } return this->status; } @@ -838,7 +950,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str input_plugin_t *input) { demux_flv_t *this; - this = xine_xmalloc(sizeof (demux_flv_t)); + this = calloc(1, sizeof(demux_flv_t)); this->xine = stream->xine; this->stream = stream; this->input = input; @@ -857,12 +969,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: - if (!_x_demux_check_extension(input->get_mrl(input), "flv")) { - free (this); - return NULL; - } - - /* falling through is intended */ case METHOD_BY_CONTENT: case METHOD_EXPLICIT: if (!open_flv_file(this)) { @@ -906,7 +1012,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_flv_class_t *this; - this = xine_xmalloc (sizeof (demux_flv_class_t)); + this = calloc(1, sizeof(demux_flv_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_idcin.c b/src/demuxers/demux_idcin.c index 99754c797..46d4c284b 100644 --- a/src/demuxers/demux_idcin.c +++ b/src/demuxers/demux_idcin.c @@ -328,7 +328,7 @@ static int open_idcin_file(demux_idcin_t *this) { this->input->seek(this->input, IDCIN_HEADER_SIZE, SEEK_SET); /* read the Huffman table */ - if (this->input->read(this->input, huffman_table, HUFFMAN_TABLE_SIZE) != + if (this->input->read(this->input, huffman_table, HUFFMAN_TABLE_SIZE) != HUFFMAN_TABLE_SIZE) return 0; @@ -347,7 +347,7 @@ static int open_idcin_file(demux_idcin_t *this) { _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, this->wave.wBitsPerSample); - this->filesize = this->input->get_length(this->input) - + this->filesize = this->input->get_length(this->input) - IDCIN_HEADER_SIZE - HUFFMAN_TABLE_SIZE; return 1; @@ -433,7 +433,7 @@ static int demux_idcin_seek (demux_plugin_t *this_gen, off_t start_pos, int star this->status = DEMUX_OK; /* reposition stream past the Huffman tables */ - this->input->seek(this->input, IDCIN_HEADER_SIZE + HUFFMAN_TABLE_SIZE, + this->input->seek(this->input, IDCIN_HEADER_SIZE + HUFFMAN_TABLE_SIZE, SEEK_SET); this->pts_counter = 0; @@ -472,7 +472,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_idcin_t *this; - this = xine_xmalloc (sizeof (demux_idcin_t)); + this = calloc(1, sizeof(demux_idcin_t)); this->stream = stream; this->input = input; @@ -547,7 +547,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_idcin_init_plugin (xine_t *xine, void *data) { demux_idcin_class_t *this; - this = xine_xmalloc (sizeof (demux_idcin_class_t)); + this = calloc(1, sizeof(demux_idcin_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_iff.c b/src/demuxers/demux_iff.c index d914405db..1785e86d7 100644 --- a/src/demuxers/demux_iff.c +++ b/src/demuxers/demux_iff.c @@ -212,7 +212,7 @@ static int read_iff_chunk(demux_iff_t *this) { break; case IFF_VHDR_CHUNK: if( this->vhdr == NULL ) - this->vhdr = (Voice8Header *)xine_xmalloc(sizeof(Voice8Header)); + this->vhdr = (Voice8Header *)calloc(1, sizeof(Voice8Header)); this->vhdr->oneShotHiSamples = _X_BE_32(&buffer[0]); this->vhdr->repeatHiSamples = _X_BE_32(&buffer[4]); this->vhdr->samplesPerHiCycle = _X_BE_32(&buffer[8]); @@ -330,7 +330,7 @@ static int read_iff_chunk(demux_iff_t *this) { break; case IFF_BMHD_CHUNK: if( this->bmhd == NULL ) - this->bmhd = (BitMapHeader *)xine_xmalloc(sizeof(BitMapHeader)); + this->bmhd = (BitMapHeader *)calloc(1, sizeof(BitMapHeader)); this->bmhd->w = _X_BE_16(&buffer[0]); this->bmhd->h = _X_BE_16(&buffer[2]); this->bmhd->x = _X_BE_16(&buffer[4]); @@ -399,20 +399,20 @@ static int read_iff_chunk(demux_iff_t *this) { case IFF_CMAP_CHUNK: /* every color contains red, green and blue componente using 8Bit */ this->cmap_num = junk_size / PIC_SIZE_OF_COLOR_REGISTER; - this->cmap = (ColorRegister *)xine_xmalloc(junk_size); + this->cmap = (ColorRegister *)malloc(junk_size); this->video_send_palette = 1; - if (this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size) + if (!this->cmap || this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size) return 0; break; case IFF_GRAB_CHUNK: if( this->grab == NULL ) - this->grab = (Point2D *)xine_xmalloc(sizeof(Point2D)); + this->grab = (Point2D *)calloc(1, sizeof(Point2D)); this->grab->x = _X_BE_16(&buffer[0]); this->grab->y = _X_BE_16(&buffer[2]); break; case IFF_DEST_CHUNK: if( this->dest == NULL ) - this->dest = (DestMerge *)xine_xmalloc(sizeof(DestMerge)); + this->dest = (DestMerge *)calloc(1, sizeof(DestMerge)); this->dest->depth = buffer[0]; this->dest->pad1 = buffer[1]; this->dest->plane_pick = _X_BE_16(&buffer[2]); @@ -424,7 +424,7 @@ static int read_iff_chunk(demux_iff_t *this) { break; case IFF_CAMG_CHUNK: if( this->camg == NULL ) - this->camg = (CamgChunk *)xine_xmalloc(sizeof(CamgChunk)); + this->camg = (CamgChunk *)calloc(1, sizeof(CamgChunk)); this->camg->view_modes = _X_BE_32(&buffer[0]); this->bih.biCompression = this->camg->view_modes; if( this->camg->view_modes & CAMG_PAL && @@ -443,7 +443,7 @@ static int read_iff_chunk(demux_iff_t *this) { break; case IFF_CCRT_CHUNK: if( this->ccrt == NULL ) - this->ccrt = (CcrtChunk *)xine_xmalloc(sizeof(CcrtChunk)); + this->ccrt = (CcrtChunk *)calloc(1, sizeof(CcrtChunk)); this->ccrt->direction = _X_BE_16(&buffer[0]); this->ccrt->start = buffer[2]; this->ccrt->end = buffer[3]; @@ -453,13 +453,13 @@ static int read_iff_chunk(demux_iff_t *this) { break; case IFF_DPI_CHUNK: if( this->dpi == NULL ) - this->dpi = (DPIHeader *)xine_xmalloc(sizeof(DPIHeader)); + this->dpi = (DPIHeader *)calloc(1, sizeof(DPIHeader)); this->dpi->x = _X_BE_16(&buffer[0]); this->dpi->y = _X_BE_16(&buffer[0]); break; case IFF_ANHD_CHUNK: if( this->anhd == NULL ) - this->anhd = (AnimHeader *)xine_xmalloc(sizeof(AnimHeader)); + this->anhd = (AnimHeader *)calloc(1, sizeof(AnimHeader)); this->anhd->operation = buffer[0]; this->anhd->mask = buffer[1]; this->anhd->w = _X_BE_16(&buffer[2]); @@ -500,7 +500,7 @@ static int read_iff_chunk(demux_iff_t *this) { break; case IFF_DPAN_CHUNK: if( this->dpan == NULL ) - this->dpan = (DPAnimChunk *)xine_xmalloc(sizeof(DPAnimChunk)); + this->dpan = (DPAnimChunk *)calloc(1, sizeof(DPAnimChunk)); this->dpan->version = _X_BE_16(&buffer[0]); this->dpan->nframes = _X_BE_16(&buffer[2]); this->dpan->fps = buffer[4]; @@ -709,11 +709,19 @@ static int demux_iff_send_chunk(demux_plugin_t *this_gen) { /* load the whole chunk into the buffer */ if (this->audio_buffer_filled == 0) { if (this->audio_interleave_buffer_size > 0) + { this->audio_interleave_buffer = - xine_xmalloc(this->audio_interleave_buffer_size); + calloc(1, this->audio_interleave_buffer_size); + if (!this->audio_interleave_buffer) + return this->status = DEMUX_FINISHED; + } if (this->audio_read_buffer_size > 0) + { this->audio_read_buffer = - xine_xmalloc(this->audio_read_buffer_size); + calloc(1, this->audio_read_buffer_size); + if (!this->audio_read_buffer) + return this->status = DEMUX_FINISHED; + } if (this->audio_read_buffer) { if (this->input->read(this->input, this->audio_read_buffer, this->data_size) != this->data_size) { @@ -1234,7 +1242,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_iff_t *this; - this = xine_xmalloc (sizeof (demux_iff_t)); + this = calloc(1, sizeof(demux_iff_t)); this->stream = stream; this->input = input; @@ -1315,7 +1323,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_iff_class_t *this; - this = xine_xmalloc (sizeof (demux_iff_class_t)); + this = calloc(1, sizeof(demux_iff_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_image.c b/src/demuxers/demux_image.c index 9f53e4173..08136edba 100644 --- a/src/demuxers/demux_image.c +++ b/src/demuxers/demux_image.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2003-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -82,7 +82,7 @@ static int demux_image_next (demux_plugin_t *this_gen, int preview) { } else { this->status = DEMUX_OK; } - + if (preview) buf->decoder_flags = BUF_FLAG_PREVIEW; @@ -198,7 +198,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, * if we reach this point, the input has been accepted. */ - this = xine_xmalloc (sizeof (demux_image_t)); + this = calloc(1, sizeof(demux_image_t)); this->stream = stream; this->input = input; @@ -211,7 +211,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->demux_plugin.get_capabilities = demux_image_get_capabilities; this->demux_plugin.get_optional_data = demux_image_get_optional_data; this->demux_plugin.demux_class = class_gen; - + this->status = DEMUX_FINISHED; this->buf_type = buf_type; @@ -226,7 +226,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, static const char *get_description (demux_class_t *this_gen) { return "image demux plugin"; } - + static const char *get_identifier (demux_class_t *this_gen) { return "imagedmx"; } @@ -249,7 +249,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_class (xine_t *xine, void *data) { demux_image_class_t *this; - this = xine_xmalloc (sizeof (demux_image_class_t)); + this = calloc(1, sizeof(demux_image_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_ipmovie.c b/src/demuxers/demux_ipmovie.c index cd21896c0..5b4e12ef8 100644 --- a/src/demuxers/demux_ipmovie.c +++ b/src/demuxers/demux_ipmovie.c @@ -183,7 +183,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) { /* read the next chunk, wherever the file happens to be pointing */ - if (this->input->read(this->input, opcode_preamble, + if (this->input->read(this->input, opcode_preamble, OPCODE_PREAMBLE_SIZE) != OPCODE_PREAMBLE_SIZE) { chunk_type = CHUNK_BAD; break; @@ -221,7 +221,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { chunk_type = CHUNK_BAD; break; } - if (this->input->read(this->input, scratch, opcode_size) != + if (this->input->read(this->input, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; @@ -239,7 +239,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { chunk_type = CHUNK_BAD; break; } - if (this->input->read(this->input, scratch, opcode_size) != + if (this->input->read(this->input, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; @@ -275,7 +275,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { chunk_type = CHUNK_BAD; break; } - if (this->input->read(this->input, scratch, opcode_size) != + if (this->input->read(this->input, scratch, opcode_size) != opcode_size) { chunk_type = CHUNK_BAD; break; @@ -283,9 +283,10 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { this->bih.biWidth = _X_LE_16(&scratch[0]) * 8; this->bih.biHeight = _X_LE_16(&scratch[2]) * 8; /* set up staging area for decode map */ - this->decode_map_size = (this->bih.biWidth * this->bih.biHeight) / - (8 * 8) / 2; + this->decode_map_size = (this->bih.biWidth / 8) * (this->bih.biHeight / 8) / 2; this->decode_map = xine_xmalloc(this->decode_map_size); + if (!this->decode_map) + this->status = DEMUX_FINISHED; lprintf("video resolution: %d x %d\n", this->bih.biWidth, this->bih.biHeight); break; @@ -335,23 +336,23 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->data_size); buf->extra_info->input_time = audio_pts / 90; buf->pts = audio_pts; - + if (opcode_size > buf->max_size) buf->size = buf->max_size; else buf->size = opcode_size; opcode_size -= buf->size; - + if (this->input->read(this->input, buf->content, buf->size) != buf->size) { buf->free_buffer(buf); chunk_type = CHUNK_BAD; break; } - + if (!opcode_size) buf->decoder_flags |= BUF_FLAG_FRAME_END; - + this->audio_fifo->put (this->audio_fifo, buf); } }else{ @@ -376,7 +377,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { case OPCODE_SET_PALETTE: lprintf("set palette\n"); - /* check for the logical maximum palette size + /* check for the logical maximum palette size * (3 * 256 + 4 bytes) */ if (opcode_size > 0x304) { lprintf("set_palette opcode too large\n"); @@ -671,7 +672,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_ipmovie_t *this; - this = xine_xmalloc (sizeof (demux_ipmovie_t)); + this = calloc(1, sizeof(demux_ipmovie_t)); this->stream = stream; this->input = input; @@ -746,7 +747,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_ipmovie_init_plugin (xine_t *xine, void *data) { demux_ipmovie_class_t *this; - this = xine_xmalloc (sizeof (demux_ipmovie_class_t)); + this = calloc(1, sizeof(demux_ipmovie_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_matroska-chapters.c b/src/demuxers/demux_matroska-chapters.c new file mode 100644 index 000000000..4bfafe0da --- /dev/null +++ b/src/demuxers/demux_matroska-chapters.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2009 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * demultiplexer for matroska streams: chapter handling + * + * TODO: + * - nested chapters + * + * Authors: + * Nicos Gollan <gtdev@spearhead.de> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define LOG_MODULE "demux_matroska_chapters" +#define LOG_VERBOSE +/* +#define LOG +*/ + +#include "xine_internal.h" +#include "xineutils.h" +#include "demux.h" + +#include "ebml.h" +#include "matroska.h" +#include "demux_matroska.h" + +/* TODO: this only handles one single (title, language, country) tuple. + * See the header for information. */ +static int parse_chapter_display(demux_matroska_t *this, matroska_chapter_t *chap, int level) { + ebml_parser_t *ebml = this->ebml; + int next_level = level+1; + char* tmp_name = NULL; + char* tmp_lang = NULL; + char* tmp_country = NULL; + + while (next_level == level+1) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + + case MATROSKA_ID_CH_STRING: + tmp_name = ebml_alloc_read_ascii(ebml, &elem); + break; + + case MATROSKA_ID_CH_LANGUAGE: + tmp_lang = ebml_alloc_read_ascii(ebml, &elem); + break; + + case MATROSKA_ID_CH_COUNTRY: + tmp_country = ebml_alloc_read_ascii(ebml, &elem); + break; + + default: + lprintf("Unhandled ID (inside ChapterDisplay): 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + if (NULL != chap->title) { + chap->title = tmp_name; + + free(chap->language); + chap->language = tmp_lang; + + free(chap->country); + chap->country = tmp_country; + } else if (tmp_lang != NULL && !strcmp("eng", tmp_lang) && (chap->language == NULL || strcmp("eng", chap->language))) { + free(chap->title); + chap->title = tmp_name; + + free(chap->language); + chap->language = tmp_lang; + + free(chap->country); + chap->country = tmp_country; + } else { + free(tmp_name); + free(tmp_lang); + free(tmp_country); + } + + return 1; +} + +static int parse_chapter_atom(demux_matroska_t *this, matroska_chapter_t *chap, int level) { + ebml_parser_t *ebml = this->ebml; + int next_level = level+1; + uint64_t num; + + chap->time_start = 0; + chap->time_end = 0; + chap->hidden = 0; + chap->enabled = 1; + + while (next_level == level+1) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) { + lprintf("invalid head\n"); + return 0; + } + + switch (elem.id) { + case MATROSKA_ID_CH_UID: + if (!ebml_read_uint(ebml, &elem, &chap->uid)) { + lprintf("invalid UID\n"); + return 0; + } + break; + + case MATROSKA_ID_CH_TIMESTART: + if (!ebml_read_uint(ebml, &elem, &chap->time_start)) { + lprintf("invalid start time\n"); + return 0; + } + /* convert to xine timing: Matroska timestamps are in nanoseconds, + * xine's PTS are in 1/90,000s */ + chap->time_start /= 100000; + chap->time_start *= 9; + break; + + case MATROSKA_ID_CH_TIMEEND: + if (!ebml_read_uint(ebml, &elem, &chap->time_end)) { + lprintf("invalid end time\n"); + return 0; + } + /* convert to xine timing */ + chap->time_end /= 100000; + chap->time_end *= 9; + break; + + case MATROSKA_ID_CH_DISPLAY: + if (!ebml_read_master(ebml, &elem)) + return 0; + + lprintf("ChapterDisplay\n"); + if(!parse_chapter_display(this, chap, level+1)) { + lprintf("invalid display information\n"); + return 0; + } + break; + + case MATROSKA_ID_CH_HIDDEN: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + chap->hidden = (int)num; + break; + + case MATROSKA_ID_CH_ENABLED: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + chap->enabled = (int)num; + break; + + case MATROSKA_ID_CH_ATOM: /* TODO */ + xprintf(this->stream->xine, XINE_VERBOSITY_NONE, + LOG_MODULE ": Warning: Nested chapters are not supported, playback may suffer!\n"); + if (!ebml_skip(ebml, &elem)) + return 0; + break; + + case MATROSKA_ID_CH_TRACK: /* TODO */ + xprintf(this->stream->xine, XINE_VERBOSITY_NONE, + LOG_MODULE ": Warning: Specific track information in chapters is not supported, playback may suffer!\n"); + if (!ebml_skip(ebml, &elem)) + return 0; + break; + + default: + lprintf("Unhandled ID (inside ChapterAtom): 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + /* fallback information */ + /* FIXME: check allocations! */ + if (NULL == chap->title) { + chap->title = malloc(9); + if (chap->title != NULL) + strncpy(chap->title, "No title", 9); + } + + if (NULL == chap->language) { + chap->language = malloc(4); + if (chap->language != NULL) + strncpy(chap->language, "unk", 4); + } + + if (NULL == chap->country) { + chap->country = malloc(3); + if (chap->country != NULL) + strncpy(chap->country, "XX", 3); + } + + lprintf( "Chapter 0x%" PRIx64 ": %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n", + chap->uid, chap->time_start, chap->time_end, + chap->title, chap->language, + (chap->hidden ? "" : "not "), + (chap->enabled ? "" : "not ")); + + return 1; +} + +static void free_chapter(demux_matroska_t *this, matroska_chapter_t *chap) { + free(chap->title); + free(chap->language); + free(chap->country); + + free(chap); +} + +static int parse_edition_entry(demux_matroska_t *this, matroska_edition_t *ed) { + ebml_parser_t *ebml = this->ebml; + int next_level = 3; + uint64_t num; + int i; + + ed->hidden = 0; + ed->is_default = 0; + ed->ordered = 0; + + while (next_level == 3) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CH_ED_UID: + if (!ebml_read_uint(ebml, &elem, &ed->uid)) + return 0; + break; + + case MATROSKA_ID_CH_ED_HIDDEN: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + ed->hidden = (int)num; + break; + + case MATROSKA_ID_CH_ED_DEFAULT: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + ed->is_default = (int)num; + break; + + case MATROSKA_ID_CH_ED_ORDERED: + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + ed->ordered = (int)num; + break; + + case MATROSKA_ID_CH_ATOM: + { + matroska_chapter_t *chapter = calloc(1, sizeof(matroska_chapter_t)); + if (NULL == chapter) + return 0; + + lprintf("ChapterAtom\n"); + if (!ebml_read_master(ebml, &elem)) + return 0; + + if (!parse_chapter_atom(this, chapter, next_level)) + return 0; + + /* resize chapters array if necessary */ + if (ed->num_chapters >= ed->cap_chapters) { + matroska_chapter_t** old_chapters = ed->chapters; + ed->cap_chapters += 10; + ed->chapters = realloc(ed->chapters, ed->cap_chapters * sizeof(matroska_chapter_t*)); + + if (NULL == ed->chapters) { + ed->chapters = old_chapters; + ed->cap_chapters -= 10; + return 0; + } + } + + ed->chapters[ed->num_chapters] = chapter; + ++ed->num_chapters; + + break; + } + + default: + lprintf("Unhandled ID (inside EditionEntry): 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + xprintf( this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": Edition 0x%" PRIx64 ": %shidden, %sdefault, %sordered. %d chapters:\n", + ed->uid, + (ed->hidden ? "" : "not "), + (ed->is_default ? "" : "not "), + (ed->ordered ? "" : "not "), + ed->num_chapters ); + + for (i=0; i<ed->num_chapters; ++i) { + matroska_chapter_t* chap = ed->chapters[i]; + xprintf( this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": Chapter %d: %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n", + i+1, chap->time_start, chap->time_end, + chap->title, chap->language, + (chap->hidden ? "" : "not "), + (chap->enabled ? "" : "not ")); + } + + return 1; +} + +static void free_edition(demux_matroska_t *this, matroska_edition_t *ed) { + int i; + + for(i=0; i<ed->num_chapters; ++i) { + free_chapter(this, ed->chapters[i]); + } + free(ed->chapters); + free(ed); +} + +int matroska_parse_chapters(demux_matroska_t *this) { + ebml_parser_t *ebml = this->ebml; + int next_level = 2; + + while (next_level == 2) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CH_EDITIONENTRY: + { + matroska_edition_t *edition = calloc(1, sizeof(matroska_edition_t)); + if (NULL == edition) + return 0; + + lprintf("EditionEntry\n"); + if (!ebml_read_master(ebml, &elem)) + return 0; + + if (!parse_edition_entry(this, edition)) + return 0; + + /* resize editions array if necessary */ + if (this->num_editions >= this->cap_editions) { + matroska_edition_t** old_editions = this->editions; + this->cap_editions += 10; + this->editions = realloc(this->editions, this->cap_editions * sizeof(matroska_edition_t*)); + + if (NULL == this->editions) { + this->editions = old_editions; + this->cap_editions -= 10; + return 0; + } + } + + this->editions[this->num_editions] = edition; + ++this->num_editions; + + break; + } + + default: + lprintf("Unhandled ID: 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + + next_level = ebml_get_next_level(ebml, &elem); + } + + return 1; +} + +void matroska_free_editions(demux_matroska_t *this) { + int i; + + for(i=0; i<this->num_editions; ++i) { + free_edition(this, this->editions[i]); + } + free(this->editions); + this->num_editions = 0; + this->cap_editions = 0; +} + +int matroska_get_chapter(demux_matroska_t *this, uint64_t tc, matroska_edition_t** ed) { + uint64_t block_pts = (tc * this->timecode_scale) / 100000 * 9; + int chapter_idx = 0; + + if (this->num_editions < 1) + return -1; + + while (chapter_idx < (*ed)->num_chapters && block_pts > (*ed)->chapters[chapter_idx]->time_start) + ++chapter_idx; + + if (chapter_idx > 0) + --chapter_idx; + + return chapter_idx; +} diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index b973c1caf..94f47db44 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2007 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -42,6 +42,7 @@ /* #define LOG */ + #include "xine_internal.h" #include "xineutils.h" #include "demux.h" @@ -50,96 +51,7 @@ #include "ebml.h" #include "matroska.h" - -#define NUM_PREVIEW_BUFFERS 10 - -#define MAX_STREAMS 128 -#define MAX_FRAMES 32 - -#define WRAP_THRESHOLD 90000 - -#if !defined(MIN) -#define MIN(a, b) ((a)<(b)?(a):(b)) -#endif -#if !defined(MAX) -#define MAX(a, b) ((a)>(b)?(a):(b)) -#endif - -typedef struct { - int track_num; - off_t *pos; - uint64_t *timecode; - int num_entries; - -} matroska_index_t; - -typedef struct { - - demux_plugin_t demux_plugin; - - xine_stream_t *stream; - - input_plugin_t *input; - - int status; - - ebml_parser_t *ebml; - - /* segment element */ - ebml_elem_t segment; - uint64_t timecode_scale; - int duration; /* in millis */ - int preview_sent; - int preview_mode; - - /* meta seek info */ - int has_seekhead; - int seekhead_handled; - - /* seek info */ - matroska_index_t *indexes; - int num_indexes; - int first_cluster_found; - int skip_to_timecode; - int skip_for_track; - - /* tracks */ - int num_tracks; - int num_video_tracks; - int num_audio_tracks; - int num_sub_tracks; - - matroska_track_t *tracks[MAX_STREAMS]; - - /* block */ - uint8_t *block_data; - int block_data_size; - - /* current tracks */ - matroska_track_t *video_track; /* to remove */ - matroska_track_t *audio_track; /* to remove */ - matroska_track_t *sub_track; /* to remove */ - - int send_newpts; - int buf_flag_seek; - - /* seekhead parsing */ - int top_level_list_size; - int top_level_list_max_size; - off_t *top_level_list; - -} demux_matroska_t ; - -typedef struct { - - demux_class_t demux_class; - - /* class-wide, global variables here */ - - xine_t *xine; - -} demux_matroska_class_t; - +#include "demux_matroska.h" static void check_newpts (demux_matroska_t *this, int64_t pts, matroska_track_t *track) { @@ -147,7 +59,7 @@ static void check_newpts (demux_matroska_t *this, int64_t pts, if ((track->track_type == MATROSKA_TRACK_VIDEO) || (track->track_type == MATROSKA_TRACK_AUDIO)) { - + diff = pts - track->last_pts; if (pts && (this->send_newpts || (track->last_pts && abs(diff)>WRAP_THRESHOLD)) ) { @@ -213,10 +125,10 @@ static int parse_info(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; int next_level = 2; double duration = 0.0; /* in matroska unit */ - + while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -226,14 +138,22 @@ static int parse_info(demux_matroska_t *this) { if (!ebml_read_uint(ebml, &elem, &this->timecode_scale)) return 0; break; - case MATROSKA_ID_I_DURATION: { - + + case MATROSKA_ID_I_DURATION: lprintf("duration\n"); if (!ebml_read_float(ebml, &elem, &duration)) return 0; - } - break; - + break; + + case MATROSKA_ID_I_TITLE: + lprintf("title\n"); + if (NULL != this->title) + free(this->title); + + this->title = ebml_alloc_read_ascii(ebml, &elem); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->title); + break; + default: lprintf("Unhandled ID: 0x%x\n", elem.id); if (!ebml_skip(ebml, &elem)) @@ -247,6 +167,8 @@ static int parse_info(demux_matroska_t *this) { this->duration = (int)(duration * (double)this->timecode_scale / 1000000.0); lprintf("timecode_scale: %" PRId64 "\n", this->timecode_scale); lprintf("duration: %d\n", this->duration); + lprintf("title: %s\n", (NULL != this->title ? this->title : "(none)")); + return 1; } @@ -488,9 +410,9 @@ static int parse_content_encodings (demux_matroska_t *this, matroska_track_t *tr static void init_codec_video(demux_matroska_t *this, matroska_track_t *track) { buf_element_t *buf; - + buf = track->fifo->buffer_pool_alloc (track->fifo); - + if (track->codec_private_len > buf->max_size) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_matroska: private decoder data length (%d) is greater than fifo buffer length (%" PRId32 ")\n", @@ -507,20 +429,20 @@ static void init_codec_video(demux_matroska_t *this, matroska_track_t *track) { xine_fast_memcpy (buf->content, track->codec_private, buf->size); else buf->content = NULL; - + if(track->default_duration) { buf->decoder_flags |= BUF_FLAG_FRAMERATE; - buf->decoder_info[0] = (int64_t)track->default_duration * + buf->decoder_info[0] = (int64_t)track->default_duration * (int64_t)90 / (int64_t)1000000; } - - if(track->video_track && track->video_track->display_width && + + if(track->video_track && track->video_track->display_width && track->video_track->display_height) { buf->decoder_flags |= BUF_FLAG_ASPECT; buf->decoder_info[1] = track->video_track->display_width; buf->decoder_info[2] = track->video_track->display_height; } - + track->fifo->put (track->fifo, buf); } @@ -538,7 +460,7 @@ static void init_codec_audio(demux_matroska_t *this, matroska_track_t *track) { return; } buf->size = track->codec_private_len; - + /* default param */ buf->decoder_info[0] = 0; buf->decoder_info[1] = 44100; @@ -570,9 +492,9 @@ static void init_codec_audio(demux_matroska_t *this, matroska_track_t *track) { static void init_codec_real(demux_matroska_t *this, matroska_track_t * track) { buf_element_t *buf; - + buf = track->fifo->buffer_pool_alloc (track->fifo); - + if (track->codec_private_len > buf->max_size) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_matroska: private decoder data length (%d) is greater than fifo buffer length (%" PRId32 ")\n", @@ -580,30 +502,30 @@ static void init_codec_real(demux_matroska_t *this, matroska_track_t * track) { buf->free_buffer(buf); return; } - + buf->size = track->codec_private_len; buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_END; buf->type = track->buf_type; buf->pts = 0; - + if (buf->size) xine_fast_memcpy (buf->content, track->codec_private, buf->size); else buf->content = NULL; - + if(track->default_duration) { buf->decoder_flags |= BUF_FLAG_FRAMERATE; - buf->decoder_info[0] = (int64_t)track->default_duration * + buf->decoder_info[0] = (int64_t)track->default_duration * (int64_t)90 / (int64_t)1000000; } - - if(track->video_track && track->video_track->display_width && + + if(track->video_track && track->video_track->display_width && track->video_track->display_height) { buf->decoder_flags |= BUF_FLAG_ASPECT; buf->decoder_info[1] = track->video_track->display_width; buf->decoder_info[2] = track->video_track->display_height; } - + track->fifo->put (track->fifo, buf); } @@ -614,6 +536,8 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { int i; uint8_t *data; + if (track->codec_private_len < 3) + return; nb_lace = track->codec_private[0]; if (nb_lace != 2) return; @@ -621,11 +545,13 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { frame[0] = track->codec_private[1]; frame[1] = track->codec_private[2]; frame[2] = track->codec_private_len - frame[0] - frame[1] - 3; + if (frame[2] < 0) + return; data = track->codec_private + 3; for (i = 0; i < 3; i++) { buf = track->fifo->buffer_pool_alloc (track->fifo); - + if (frame[i] > buf->max_size) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_matroska: private decoder data length (%d) is greater than fifo buffer length (%" PRId32 ")\n", @@ -634,10 +560,8 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { return; } buf->size = frame[i]; - - buf->decoder_flags = BUF_FLAG_HEADER; - if (i == 2) - buf->decoder_flags |= BUF_FLAG_FRAME_END; + + buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_START | BUF_FLAG_FRAME_END; buf->type = track->buf_type; buf->pts = 0; @@ -685,7 +609,11 @@ static void init_codec_aac(demux_matroska_t *this, matroska_track_t *track) { /* Create a DecoderSpecificInfo for initialising libfaad */ sr_index = aac_get_sr_index(atrack->sampling_freq); - if (!strncmp (&track->codec_id[12], "MAIN", 4)) + /* newer specification with appended CodecPrivate */ + if (strlen(track->codec_id) <= 12) + profile = 3; + /* older specification */ + else if (!strncmp (&track->codec_id[12], "MAIN", 4)) profile = 0; else if (!strncmp (&track->codec_id[12], "LC", 2)) profile = 1; @@ -884,7 +812,7 @@ static void init_codec_vobsub(demux_matroska_t *this, static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track, int decoder_flags, - uint8_t *data, int data_len, + uint8_t *data, size_t data_len, int64_t data_pts, int data_duration, int input_normpos, int input_time) { demux_matroska_t *this = (demux_matroska_t *) this_gen; @@ -921,7 +849,7 @@ static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track, buf->decoder_info[1] = BUF_SPECIAL_RV_CHUNK_TABLE; buf->decoder_info[2] = chunks; buf->decoder_info_ptr[2] = buf->content; - + buf->size = 0; buf->type = track->buf_type; @@ -933,7 +861,7 @@ static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track, static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track, int decoder_flags, - uint8_t *data, int data_len, + uint8_t *data, size_t data_len, int64_t data_pts, int data_duration, int input_normpos, int input_time) { buf_element_t *buf; @@ -988,7 +916,7 @@ static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track, } } } - + last_char = *data; data++; data_len--; } @@ -999,16 +927,16 @@ static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track, buf->size = dest - (char *)buf->content; buf->extra_info->input_normpos = input_normpos; buf->extra_info->input_time = input_time; - + track->fifo->put(track->fifo, buf); } else { buf->free_buffer(buf); - } + } } static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track, int decoder_flags, - uint8_t *data, int data_len, + uint8_t *data, size_t data_len, int64_t data_pts, int data_duration, int input_normpos, int input_time) { demux_matroska_t *this = (demux_matroska_t *) this_gen; @@ -1018,7 +946,7 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track, buf = track->fifo->buffer_pool_alloc(track->fifo); buf->size = data_len + 9; /* 2 uint32_t + '\0' */ - + if (buf->max_size >= buf->size) { buf->decoder_flags = decoder_flags; @@ -1027,7 +955,7 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track, buf->decoder_info[1] = BUF_SPECIAL_CHARSET_ENCODING; buf->decoder_info_ptr[2] = "utf-8"; buf->decoder_info[2] = strlen(buf->decoder_info_ptr[2]); - + val = (uint32_t *)buf->content; *val++ = data_pts / 90; /* start time */ *val++ = (data_pts + data_duration) / 90; /* end time */ @@ -1055,7 +983,7 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track, */ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, int decoder_flags, - uint8_t *data, int data_len, + uint8_t *data, size_t data_len, int64_t data_pts, int data_duration, int input_normpos, int input_time) { demux_matroska_t *this = (demux_matroska_t *) this_gen; @@ -1092,7 +1020,7 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, (int)track->track_num, result); free(dest); inflateEnd(&zstream); - + if (result == Z_DATA_ERROR && track->compress_algo == MATROSKA_COMPRESS_UNKNOWN) { track->compress_algo = MATROSKA_COMPRESS_NONE; data_len = old_data_len; @@ -1105,11 +1033,11 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, zstream.avail_out += 4000; } while ((zstream.avail_out == 4000) && (zstream.avail_in != 0) && (result != Z_STREAM_END)); - + if (track->compress_algo != MATROSKA_COMPRESS_NONE) { data_len = zstream.total_out; inflateEnd(&zstream); - + data = dest; track->compress_algo = MATROSKA_COMPRESS_ZLIB; lprintf("VobSub: decompression for track %d from %d to %d\n", @@ -1152,120 +1080,140 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { ebml_parser_t *ebml = this->ebml; int next_level = 3; - + while (next_level == 3) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; switch (elem.id) { - case MATROSKA_ID_TR_NUMBER: { - uint64_t num; - lprintf("TrackNumber\n"); - if (!ebml_read_uint(ebml, &elem, &num)) - return 0; - track->track_num = num; - } - break; - - case MATROSKA_ID_TR_TYPE: { - uint64_t num; - lprintf("TrackType\n"); - if (!ebml_read_uint(ebml, &elem, &num)) - return 0; - track->track_type = num; - } - break; - - case MATROSKA_ID_TR_CODECID: { - char *codec_id = malloc (elem.len + 1); - lprintf("CodecID\n"); - if (!ebml_read_ascii(ebml, &elem, codec_id)) { - free(codec_id); - return 0; - } - codec_id[elem.len] = '\0'; - track->codec_id = codec_id; - } - break; - - case MATROSKA_ID_TR_CODECPRIVATE: { - char *codec_private = malloc (elem.len); - lprintf("CodecPrivate\n"); - if (!ebml_read_binary(ebml, &elem, codec_private)) { - free(codec_private); - return 0; - } - track->codec_private = codec_private; - track->codec_private_len = elem.len; - } - break; - - case MATROSKA_ID_TR_LANGUAGE: { - char *language = malloc (elem.len + 1); - lprintf("Language\n"); - if (!ebml_read_ascii(ebml, &elem, language)) { - free(language); - return 0; - } - language[elem.len] = '\0'; - track->language = language; - } - break; - + case MATROSKA_ID_TR_NUMBER: + { + uint64_t num; + lprintf("TrackNumber\n"); + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + track->track_num = num; + } + break; + + case MATROSKA_ID_TR_TYPE: + { + uint64_t num; + lprintf("TrackType\n"); + if (!ebml_read_uint(ebml, &elem, &num)) + return 0; + track->track_type = num; + } + break; + + case MATROSKA_ID_TR_CODECID: + { + char *codec_id = ebml_alloc_read_ascii (ebml, &elem); + lprintf("CodecID\n"); + if (!codec_id) + return 0; + track->codec_id = codec_id; + } + break; + + case MATROSKA_ID_TR_CODECPRIVATE: + { + char *codec_private; + if (elem.len >= 0x80000000) + return 0; + codec_private = malloc (elem.len); + if (! codec_private) + return 0; + lprintf("CodecPrivate\n"); + if (!ebml_read_binary(ebml, &elem, codec_private)) { + free(codec_private); + return 0; + } + track->codec_private = codec_private; + track->codec_private_len = elem.len; + } + break; + + case MATROSKA_ID_TR_LANGUAGE: + { + char *language = ebml_alloc_read_ascii (ebml, &elem); + lprintf("Language\n"); + if (!language) + return 0; + track->language = language; + } + break; + case MATROSKA_ID_TV: lprintf("Video\n"); if (track->video_track) return 1; - track->video_track = (matroska_video_track_t *)xine_xmalloc(sizeof(matroska_video_track_t)); + track->video_track = (matroska_video_track_t *)calloc(1, sizeof(matroska_video_track_t)); if (!ebml_read_master (ebml, &elem)) return 0; if ((elem.len > 0) && !parse_video_track(this, track->video_track)) return 0; - break; - + break; + case MATROSKA_ID_TA: lprintf("Audio\n"); if (track->audio_track) return 1; - track->audio_track = (matroska_audio_track_t *)xine_xmalloc(sizeof(matroska_audio_track_t)); + track->audio_track = (matroska_audio_track_t *)calloc(1, sizeof(matroska_audio_track_t)); if (!ebml_read_master (ebml, &elem)) return 0; if ((elem.len > 0) && !parse_audio_track(this, track->audio_track)) return 0; - break; - - case MATROSKA_ID_TR_FLAGDEFAULT: { - uint64_t val; - - lprintf("Default\n"); - if (!ebml_read_uint(ebml, &elem, &val)) - return 0; - track->default_flag = (int)val; - } - break; + break; - case MATROSKA_ID_TR_DEFAULTDURATION: { - uint64_t val; + case MATROSKA_ID_TR_FLAGDEFAULT: + { + uint64_t val; - if (!ebml_read_uint(ebml, &elem, &val)) - return 0; - track->default_duration = val; - lprintf("Default Duration: %"PRIu64"\n", track->default_duration); - } - break; + lprintf("Default\n"); + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + track->default_flag = (int)val; + } + break; - case MATROSKA_ID_CONTENTENCODINGS: { - lprintf("ContentEncodings\n"); - if (!ebml_read_master (ebml, &elem)) - return 0; - if ((elem.len > 0) && !parse_content_encodings(this, track)) - return 0; - } - break; + case MATROSKA_ID_TR_DEFAULTDURATION: + { + uint64_t val; + + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + track->default_duration = val; + lprintf("Default Duration: %"PRIu64"\n", track->default_duration); + } + break; + + case MATROSKA_ID_CONTENTENCODINGS: + { + lprintf("ContentEncodings\n"); + if (!ebml_read_master (ebml, &elem)) + return 0; + if ((elem.len > 0) && !parse_content_encodings(this, track)) + return 0; + } + break; case MATROSKA_ID_TR_UID: + { + uint64_t val; + + if (!ebml_read_uint(ebml, &elem, &val)) { + lprintf("Track UID (invalid)\n"); + return 0; + } + + track->uid = val; + lprintf("Track UID: 0x%" PRIx64 "\n", track->uid); + } + break; + case MATROSKA_ID_TR_FLAGENABLED: case MATROSKA_ID_TR_FLAGLACING: case MATROSKA_ID_TR_MINCACHE: @@ -1286,68 +1234,76 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { } next_level = ebml_get_next_level(ebml, &elem); } - + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_matroska: Track %d, %s %s\n", - track->track_num, - (track->codec_id ? track->codec_id : ""), - (track->language ? track->language : "")); + "demux_matroska: Track %d, %s %s\n", + track->track_num, + (track->codec_id ? track->codec_id : ""), + (track->language ? track->language : "")); if (track->codec_id) { void (*init_codec)(demux_matroska_t *, matroska_track_t *) = NULL; if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_VFW_FOURCC)) { xine_bmiheader *bih; - lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n"); - bih = (xine_bmiheader*)track->codec_private; - _x_bmiheader_le2me(bih); + if (track->codec_private_len >= sizeof(xine_bmiheader)) { + lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n"); + bih = (xine_bmiheader*)track->codec_private; + _x_bmiheader_le2me(bih); - track->buf_type = _x_fourcc_to_buf_video(bih->biCompression); - init_codec = init_codec_video; + track->buf_type = _x_fourcc_to_buf_video(bih->biCompression); + init_codec = init_codec_video; + } } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_UNCOMPRESSED)) { } else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_SP)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_ASP)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AP))) { + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_ASP)) || + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AP))) { xine_bmiheader *bih; - + lprintf("MATROSKA_CODEC_ID_V_MPEG4_*\n"); + if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader)) + track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader); + /* create a bitmap info header struct for MPEG 4 */ - bih = malloc(sizeof(xine_bmiheader) + track->codec_private_len); + bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len); bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len; bih->biCompression = ME_FOURCC('M', 'P', '4', 'S'); bih->biWidth = track->video_track->pixel_width; bih->biHeight = track->video_track->pixel_height; _x_bmiheader_le2me(bih); - + /* add bih extra data */ memcpy(bih + 1, track->codec_private, track->codec_private_len); free(track->codec_private); track->codec_private = (uint8_t *)bih; track->codec_private_len = bih->biSize; track->buf_type = BUF_VIDEO_MPEG4; - + /* init as a vfw decoder */ init_codec = init_codec_video; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AVC)) { xine_bmiheader *bih; - + lprintf("MATROSKA_CODEC_ID_V_MPEG4_AVC\n"); + if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader)) + track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader); + /* create a bitmap info header struct for h264 */ - bih = malloc(sizeof(xine_bmiheader) + track->codec_private_len); + bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len); bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len; bih->biCompression = ME_FOURCC('a', 'v', 'c', '1'); bih->biWidth = track->video_track->pixel_width; bih->biHeight = track->video_track->pixel_height; _x_bmiheader_le2me(bih); - + /* add bih extra data */ memcpy(bih + 1, track->codec_private, track->codec_private_len); free(track->codec_private); track->codec_private = (uint8_t *)bih; track->codec_private_len = bih->biSize; track->buf_type = BUF_VIDEO_H264; - + /* init as a vfw decoder */ init_codec = init_codec_video; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MSMPEG4V3)) { @@ -1368,7 +1324,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->handle_content = handle_realvideo; init_codec = init_codec_real; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_REAL_RV40)) { - + lprintf("MATROSKA_CODEC_ID_V_REAL_RV40\n"); track->buf_type = BUF_VIDEO_RV40; track->handle_content = handle_realvideo; @@ -1380,8 +1336,8 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_VIDEO_THEORA_RAW; init_codec = init_codec_xiph; } else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L1)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L2)) || - (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L3))) { + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L2)) || + (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L3))) { lprintf("MATROSKA_CODEC_ID_A_MPEG1\n"); track->buf_type = BUF_AUDIO_MPEG; init_codec = init_codec_audio; @@ -1393,7 +1349,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { lprintf("MATROSKA_CODEC_ID_A_AC3\n"); track->buf_type = BUF_AUDIO_A52; init_codec = init_codec_audio; - + } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_DTS)) { lprintf("MATROSKA_CODEC_ID_A_DTS\n"); track->buf_type = BUF_AUDIO_DTS; @@ -1409,13 +1365,15 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { xine_waveformatex *wfh; lprintf("MATROSKA_CODEC_ID_A_ACM\n"); - wfh = (xine_waveformatex*)track->codec_private; - _x_waveformatex_le2me(wfh); + if (track->codec_private_len >= sizeof(xine_waveformatex)) { + wfh = (xine_waveformatex*)track->codec_private; + _x_waveformatex_le2me(wfh); - track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag); - init_codec = init_codec_audio; + track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag); + init_codec = init_codec_audio; + } } else if (!strncmp(track->codec_id, MATROSKA_CODEC_ID_A_AAC, - sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) { + sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) { lprintf("MATROSKA_CODEC_ID_A_AAC\n"); track->buf_type = BUF_AUDIO_AAC; init_codec = init_codec_aac; @@ -1435,17 +1393,17 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_AUDIO_ATRK; init_codec = init_codec_real; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_UTF8) || - !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_UTF8)) { + !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_UTF8)) { lprintf("MATROSKA_CODEC_ID_S_TEXT_UTF8\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_utf8; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_SSA) || - !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_SSA)) { + !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_SSA)) { lprintf("MATROSKA_CODEC_ID_S_TEXT_SSA\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_ssa; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_ASS) || - !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_ASS)) { + !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_ASS)) { lprintf("MATROSKA_CODEC_ID_S_TEXT_ASS\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_ssa; @@ -1458,7 +1416,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_SPU_DVD; track->handle_content = handle_vobsub; init_codec = init_codec_vobsub; - + /* Enable autodetection of the zlib compression, unless it was * explicitely set. Most vobsubs are compressed with zlib but * are not declared as such. @@ -1494,12 +1452,17 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { break; } - if (init_codec) + if (init_codec) { + if (! track->fifo) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: Error: fifo not set up for track of type type %" PRIu32 "\n", track->track_type); + return 0; + } init_codec(this, track); - + } } } - + return 1; } @@ -1507,10 +1470,10 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { static int parse_tracks(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; int next_level = 2; - + while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -1518,8 +1481,14 @@ static int parse_tracks(demux_matroska_t *this) { case MATROSKA_ID_TR_ENTRY: { matroska_track_t *track; + /* bail out early if no more tracks can be handled! */ + if (this->num_tracks >= MAX_STREAMS) { + lprintf("Too many tracks!\n"); + return 0; + } + /* alloc and initialize a track with 0 */ - track = xine_xmalloc(sizeof(matroska_track_t)); + track = calloc(1, sizeof(matroska_track_t)); track->compress_algo = MATROSKA_COMPRESS_NONE; this->tracks[this->num_tracks] = track; @@ -1531,29 +1500,7 @@ static int parse_tracks(demux_matroska_t *this) { this->num_tracks++; } break; - - default: - lprintf("Unhandled ID: 0x%x\n", elem.id); - if (!ebml_skip(ebml, &elem)) - return 0; - } - next_level = ebml_get_next_level(ebml, &elem); - } - return 1; -} - -static int parse_chapters(demux_matroska_t *this) { - ebml_parser_t *ebml = this->ebml; - int next_level = 2; - - while (next_level == 2) { - ebml_elem_t elem; - - if (!ebml_read_elem_head(ebml, &elem)) - return 0; - - switch (elem.id) { default: lprintf("Unhandled ID: 0x%x\n", elem.id); if (!ebml_skip(ebml, &elem)) @@ -1564,15 +1511,14 @@ static int parse_chapters(demux_matroska_t *this) { return 1; } - static int parse_cue_trackposition(demux_matroska_t *this, int *track_num, int64_t *pos) { ebml_parser_t *ebml = this->ebml; int next_level = 4; - + while (next_level == 4) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -1609,10 +1555,10 @@ static int parse_cue_point(demux_matroska_t *this) { int next_level = 3; int64_t timecode = -1, pos = -1; int track_num = -1; - + while (next_level == 3) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -1677,10 +1623,10 @@ static int parse_cue_point(demux_matroska_t *this) { static int parse_cues(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; int next_level = 2; - + while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -1706,10 +1652,10 @@ static int parse_cues(demux_matroska_t *this) { static int parse_attachments(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; int next_level = 2; - + while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -1728,10 +1674,10 @@ static int parse_attachments(demux_matroska_t *this) { static int parse_tags(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; int next_level = 2; - + while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -1746,7 +1692,7 @@ static int parse_tags(demux_matroska_t *this) { return 1; } -static void alloc_block_data (demux_matroska_t *this, int len) { +static void alloc_block_data (demux_matroska_t *this, size_t len) { /* memory management */ if (this->block_data_size < len) { if (this->block_data) @@ -1770,7 +1716,7 @@ static int parse_ebml_uint(demux_matroska_t *this, uint8_t *data, uint64_t *num) } if (size > 8) { off_t pos = this->input->get_current_pos(this->input); - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "demux_matroska: Invalid Track Number at position %" PRIdMAX "\n", (intmax_t)pos); return 0; @@ -1799,7 +1745,7 @@ static int parse_ebml_sint(demux_matroska_t *this, uint8_t *data, int64_t *num) *num = -1; else *num = unum - ((1 << ((7 * size) - 1)) - 1); - + return size; } @@ -1818,10 +1764,15 @@ static int find_track_by_id(demux_matroska_t *this, int track_num, } -static int read_block_data (demux_matroska_t *this, int len) { +static int read_block_data (demux_matroska_t *this, size_t len) { alloc_block_data(this, len); /* block datas */ + if (! this->block_data) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: memory allocation error\n"); + return 0; + } if (this->input->read(this->input, this->block_data, len) != len) { off_t pos = this->input->get_current_pos(this->input); xprintf(this->stream->xine, XINE_VERBOSITY_LOG, @@ -1832,15 +1783,24 @@ static int read_block_data (demux_matroska_t *this, int len) { return 1; } -static int parse_block (demux_matroska_t *this, uint64_t block_size, +static int parse_int16(uint8_t *data) { + int value = (int)_X_BE_16(data); + if (value & 1<<15) + { + value -= 1<<16; + } + return value; +} + +static int parse_block (demux_matroska_t *this, size_t block_size, uint64_t cluster_timecode, uint64_t block_duration, int normpos, int is_key) { matroska_track_t *track; - int64_t track_num; + uint64_t track_num; uint8_t *data; uint8_t flags; int gap, lacing, num_len; - int timecode_diff; + int16_t timecode_diff; int64_t pts, xduration; int decoder_flags = 0; @@ -1848,14 +1808,15 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, if (!(num_len = parse_ebml_uint(this, data, &track_num))) return 0; data += num_len; - - timecode_diff = (int)_X_BE_16(data); + + /* timecode_diff is signed */ + timecode_diff = (int16_t)parse_int16(data); data += 2; flags = *data; data += 1; - - lprintf("track_num: %" PRId64 ", timecode_diff: %d, flags: 0x%x\n", track_num, timecode_diff, flags); + + lprintf("track_num: %" PRIu64 ", timecode_diff: %d, flags: 0x%x\n", track_num, timecode_diff, flags); gap = flags & 1; lacing = (flags >> 1) & 0x3; @@ -1863,7 +1824,7 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, if (!find_track_by_id(this, (int)track_num, &track)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_matroska: invalid track id: %" PRId64 "\n", track_num); + "demux_matroska: invalid track id: %" PRIu64 "\n", track_num); return 0; } @@ -1897,11 +1858,11 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, } if (lacing == MATROSKA_NO_LACING) { - int block_size_left; + size_t block_size_left; lprintf("no lacing\n"); block_size_left = (this->block_data + block_size) - data; - lprintf("size: %d, block_size: %" PRIu64 "\n", block_size_left, block_size); + lprintf("size: %d, block_size: %u\n", block_size_left, block_size); if (track->handle_content != NULL) { track->handle_content((demux_plugin_t *)this, track, @@ -1917,9 +1878,9 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, } } else { - int block_size_left; + size_t block_size_left; uint8_t lace_num; - int frame[MAX_FRAMES]; + size_t frame[MAX_FRAMES]; int i; /* number of laced frames */ @@ -1961,7 +1922,7 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, int frame_size; lprintf("fixed size lacing\n"); - + frame_size = block_size_left / (lace_num + 1); for (i = 0; i < lace_num; i++) { frame[i] = frame_size; @@ -1972,24 +1933,51 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, break; case MATROSKA_EBML_LACING: { - int64_t tmp; + uint64_t first_frame_size; lprintf("ebml lacing\n"); /* size of each frame */ - if (!(num_len = parse_ebml_uint(this, data, &tmp))) + if (!(num_len = parse_ebml_uint(this, data, &first_frame_size))) + return 0; + if (num_len > block_size_left) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: block too small\n"); return 0; + } + if (first_frame_size > INT_MAX) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: invalid first frame size (%" PRId64 ")\n", + first_frame_size); + return 0; + } data += num_len; block_size_left -= num_len; - frame[0] = (int) tmp; + frame[0] = (int) first_frame_size; lprintf("first frame len: %d\n", frame[0]); block_size_left -= frame[0]; for (i = 1; i < lace_num; i++) { - if (!(num_len = parse_ebml_sint(this, data, &tmp))) + int64_t frame_size_diff; + int64_t frame_size; + + if (!(num_len = parse_ebml_sint(this, data, &frame_size_diff))) return 0; + if (num_len > block_size_left) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: block too small\n"); + return 0; + } data += num_len; block_size_left -= num_len; - frame[i] = frame[i-1] + tmp; + + frame_size = frame[i-1] + frame_size_diff; + if (frame_size > INT_MAX || frame_size < 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: invalid frame size (%" PRId64 ")\n", + frame_size); + return 0; + } + frame[i] = frame_size; block_size_left -= frame[i]; } @@ -2023,6 +2011,31 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size, return 1; } +static int parse_simpleblock(demux_matroska_t *this, size_t block_len, uint64_t cluster_timecode, uint64_t block_duration) +{ + int has_block = 0; + off_t block_pos = 0; + off_t file_len = 0; + int normpos = 0; + int is_key = 1; + + lprintf("simpleblock\n"); + block_pos = this->input->get_current_pos(this->input); + file_len = this->input->get_length(this->input); + if( file_len ) + normpos = (int) ( (double) block_pos * 65535 / file_len ); + + if (!read_block_data(this, block_len)) + return 0; + + has_block = 1; + /* we have the duration, we can parse the block now */ + if (!parse_block(this, block_len, cluster_timecode, block_duration, + normpos, is_key)) + return 0; + return 1; +} + static int parse_block_group(demux_matroska_t *this, uint64_t cluster_timecode, uint64_t cluster_duration) { @@ -2033,7 +2046,7 @@ static int parse_block_group(demux_matroska_t *this, off_t block_pos = 0; off_t file_len = 0; int normpos = 0; - int block_len = 0; + size_t block_len = 0; int is_key = 1; while (next_level == 3) { @@ -2085,9 +2098,52 @@ static int parse_block_group(demux_matroska_t *this, return 1; } +static int demux_matroska_seek (demux_plugin_t*, off_t, int, int); + +static void handle_events(demux_matroska_t *this) { + xine_event_t* event; + + while ((event = xine_event_get(this->event_queue))) { + if (this->num_editions > 0) { + matroska_edition_t* ed = this->editions[0]; + int chapter_idx = matroska_get_chapter(this, this->last_timecode, &ed); + uint64_t next_time; + + if (chapter_idx < 0) { + xine_event_free(event); + continue; + } + + switch(event->type) { + case XINE_EVENT_INPUT_NEXT: + if (chapter_idx < ed->num_chapters-1) { + next_time = ed->chapters[chapter_idx+1]->time_start / 90; + demux_matroska_seek((demux_plugin_t*)this, 0, next_time, 1); + } + break; + + /* TODO: should this try to implement common "start of chapter" + * functionality? */ + case XINE_EVENT_INPUT_PREVIOUS: + if (chapter_idx > 0) { + next_time = ed->chapters[chapter_idx-1]->time_start / 90; + demux_matroska_seek((demux_plugin_t*)this, 0, next_time, 1); + } + break; + + default: + break; + } + } + + xine_event_free(event); + } +} + static int parse_cluster(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; - int next_level = 2; + int this_level = ebml->level; + int next_level = this_level; uint64_t timecode = 0; uint64_t duration = 0; @@ -2104,7 +2160,9 @@ static int parse_cluster(demux_matroska_t *this) { this->first_cluster_found = 1; } - while (next_level == 2) { + handle_events(this); + + while (next_level == this_level) { ebml_elem_t elem; if (!ebml_read_elem_head(ebml, &elem)) @@ -2128,6 +2186,11 @@ static int parse_cluster(demux_matroska_t *this) { if ((elem.len > 0) && !parse_block_group(this, timecode, duration)) return 0; break; + case MATROSKA_ID_CL_SIMPLEBLOCK: + lprintf("simpleblock\n"); + if (!parse_simpleblock(this, elem.len, timecode, duration)) + return 0; + break; case MATROSKA_ID_CL_BLOCK: lprintf("block\n"); if (!ebml_skip(ebml, &elem)) @@ -2140,6 +2203,49 @@ static int parse_cluster(demux_matroska_t *this) { } next_level = ebml_get_next_level(ebml, &elem); } + + /* at this point, we MUST have a timecode (according to format spec). + * Use that to find the chapter we are in, and adjust the title. + * + * TODO: this only looks at the chapters in the first edition. + */ + + this->last_timecode = timecode; + + if (this->num_editions <= 0) + return 1; + matroska_edition_t *ed = this->editions[0]; + + if (ed->num_chapters <= 0) + return 1; + + /* fix up a makeshift title if none has been set yet (e.g. filename) */ + if (NULL == this->title && NULL != _x_meta_info_get(this->stream, XINE_META_INFO_TITLE)) + this->title = strdup(_x_meta_info_get(this->stream, XINE_META_INFO_TITLE)); + + if (NULL == this->title) + this->title = strdup("(No title)"); + + if (NULL == this->title) { + lprintf("Failed to determine a valid stream title!\n"); + return 1; + } + + int chapter_idx = matroska_get_chapter(this, timecode, &ed); + if (chapter_idx < 0) { + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->title); + return 1; + } + + xine_ui_data_t uidata = { + .str = {0, }, + .str_len = 0, + }; + + uidata.str_len = snprintf(uidata.str, sizeof(uidata.str), "%s / (%d) %s", + this->title, chapter_idx+1, ed->chapters[chapter_idx]->title); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, uidata.str); + return 1; } @@ -2152,10 +2258,10 @@ static int parse_seek_entry(demux_matroska_t *this) { int has_position = 0; uint64_t id = 0; uint64_t pos; - + while (next_level == 3) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -2179,26 +2285,26 @@ static int parse_seek_entry(demux_matroska_t *this) { } next_level = ebml_get_next_level(ebml, &elem); } - + /* do not parse clusters */ if (id == MATROSKA_ID_CLUSTER) { lprintf("skip cluster\n"); return 1; } - - /* parse the referenced element */ + + /* parse the referenced element */ if (has_id && has_position) { off_t current_pos, seek_pos; - + seek_pos = this->segment.start + pos; - + if ((seek_pos > 0) && (seek_pos < this->input->get_length(this->input))) { ebml_parser_t ebml_bak; /* backup current state */ current_pos = this->input->get_current_pos(this->input); memcpy(&ebml_bak, this->ebml, sizeof(ebml_parser_t)); /* FIXME */ - + /* seek and parse the top_level element */ this->ebml->level = 1; if (this->input->seek(this->input, seek_pos, SEEK_SET) < 0) { @@ -2237,7 +2343,7 @@ static int parse_seekhead(demux_matroska_t *this) { while (next_level == 2) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -2274,18 +2380,19 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) { ebml_elem_t elem; int ret_value = 1; off_t current_pos; - + + current_pos = this->input->get_current_pos(this->input); lprintf("current_pos: %" PRIdMAX "\n", (intmax_t)current_pos); - + if (!ebml_read_elem_head(ebml, &elem)) return 0; - + if (!find_top_level_entry(this, current_pos)) { if (!add_top_level_entry(this, current_pos)) return 0; - + switch (elem.id) { case MATROSKA_ID_SEEKHEAD: lprintf("SeekHead\n"); @@ -2312,7 +2419,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) { lprintf("Chapters\n"); if (!ebml_read_master (ebml, &elem)) return 0; - if ((elem.len > 0) && !parse_chapters(this)) + if ((elem.len > 0) && !matroska_parse_chapters(this)) return 0; break; case MATROSKA_ID_CLUSTER: @@ -2352,7 +2459,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) { if (!ebml_skip(ebml, &elem)) return 0; } - + if (next_level) *next_level = ebml_get_next_level(ebml, &elem); @@ -2439,12 +2546,12 @@ static int parse_segment(demux_matroska_t *this) { if (this->segment.id == MATROSKA_ID_SEGMENT) { int res; int next_level; - + lprintf("Segment detected\n"); if (!ebml_read_master (ebml, &this->segment)) return 0; - + res = 1; next_level = 1; /* stop the loop on the first cluster */ @@ -2496,14 +2603,14 @@ static void demux_matroska_send_headers (demux_plugin_t *this_gen) { _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, (this->num_video_tracks != 0)); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, (this->num_audio_tracks != 0)); - + /* * send preview buffers */ /* enter in the segment */ ebml_read_master (this->ebml, &this->segment); - + /* seek back to the beginning of the segment */ next_level = 1; if (this->input->seek(this->input, this->segment.start, SEEK_SET) < 0) { @@ -2513,7 +2620,7 @@ static void demux_matroska_send_headers (demux_plugin_t *this_gen) { this->status = DEMUX_FINISHED; return; } - + this->preview_sent = 0; this->preview_mode = 1; @@ -2599,7 +2706,7 @@ static int demux_matroska_seek (demux_plugin_t *this_gen, matroska_index_t *index; matroska_track_t *track; int i, entry; - + start_pos = (off_t) ( (double) start_pos / 65535 * this->input->get_length (this->input) ); @@ -2655,10 +2762,10 @@ static int demux_matroska_seek (demux_plugin_t *this_gen, index->track_num, start_pos ? "pos" : "time", start_pos ? (intmax_t)start_pos : (intmax_t)start_time, index->track_num, index->timecode[entry], (intmax_t)index->pos[entry]); - + if (this->input->seek(this->input, index->pos[entry], SEEK_SET) < 0) this->status = DEMUX_FINISHED; - + /* we always seek to the ebml level 1 */ this->ebml->level = 1; @@ -2672,10 +2779,12 @@ static int demux_matroska_seek (demux_plugin_t *this_gen, static void demux_matroska_dispose (demux_plugin_t *this_gen) { - + demux_matroska_t *this = (demux_matroska_t *) this_gen; int i; + free(this->block_data); + /* free tracks */ for (i = 0; i < this->num_tracks; i++) { matroska_track_t *track; @@ -2693,7 +2802,7 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) { free (track->audio_track); if (track->sub_track) free (track->sub_track); - + free (track); } /* Free the cues. */ @@ -2705,12 +2814,17 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) { } if (this->indexes) free(this->indexes); - - /* Free the top_level elem list */ + + /* Free the top_level elem list */ if (this->top_level_list) free(this->top_level_list); + free(this->title); + + matroska_free_editions(this); + dispose_ebml_parser(this->ebml); + xine_event_dispose_queue(this->event_queue); free (this); } @@ -2724,7 +2838,13 @@ static int demux_matroska_get_stream_length (demux_plugin_t *this_gen) { static uint32_t demux_matroska_get_capabilities (demux_plugin_t *this_gen) { - return DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG; + demux_matroska_t* this = (demux_matroska_t*)this_gen; + uint32_t caps = DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG; + + if(this->num_editions > 0 && this->editions[0]->num_chapters > 0) + caps |= DEMUX_CAP_CHAPTERS; + + return caps; } @@ -2741,7 +2861,7 @@ static int demux_matroska_get_optional_data (demux_plugin_t *this_gen, if ((channel >= 0) && (channel < this->num_sub_tracks)) { for (track_num = 0; track_num < this->num_tracks; track_num++) { matroska_track_t *track = this->tracks[track_num]; - + if ((track->buf_type & 0xFF00001F) == (BUF_SPU_BASE + channel)) { if (track->language) { strncpy (str, track->language, XINE_LANG_MAX); @@ -2757,13 +2877,13 @@ static int demux_matroska_get_optional_data (demux_plugin_t *this_gen, } } return DEMUX_OPTIONAL_UNSUPPORTED; - + case DEMUX_OPTIONAL_DATA_AUDIOLANG: lprintf ("DEMUX_OPTIONAL_DATA_AUDIOLANG channel = %d\n",channel); if ((channel >= 0) && (channel < this->num_audio_tracks)) { for (track_num = 0; track_num < this->num_tracks; track_num++) { matroska_track_t *track = this->tracks[track_num]; - + if ((track->buf_type & 0xFF00001F) == (BUF_AUDIO_BASE + channel)) { if (track->language) { strncpy (str, track->language, XINE_LANG_MAX); @@ -2824,7 +2944,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_matroska_t)); + this = calloc(1, sizeof(demux_matroska_t)); this->demux_plugin.send_headers = demux_matroska_send_headers; this->demux_plugin.send_chunk = demux_matroska_send_chunk; @@ -2855,11 +2975,18 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str if (strcmp(ebml->doctype, "matroska")) goto error; + this->event_queue = xine_event_new_queue(this->stream); + return &this->demux_plugin; error: dispose_ebml_parser(ebml); - free(this); + + if (NULL != this) { + xine_event_dispose_queue(this->event_queue); + free(this); + } + return NULL; } @@ -2884,7 +3011,8 @@ static const char *get_extensions (demux_class_t *this_gen) { static const char *get_mimetypes (demux_class_t *this_gen) { - return "video/mkv: mkv: matroska;"; + return "video/mkv: mkv: matroska;" + "video/x-matroska: mkv: matroska;"; } @@ -2899,7 +3027,7 @@ static void *init_class (xine_t *xine, void *data) { demux_matroska_class_t *this; - this = xine_xmalloc (sizeof (demux_matroska_class_t)); + this = calloc(1, sizeof(demux_matroska_class_t)); this->xine = xine; this->demux_class.open_plugin = open_plugin; diff --git a/src/demuxers/demux_matroska.h b/src/demuxers/demux_matroska.h new file mode 100644 index 000000000..e1611f397 --- /dev/null +++ b/src/demuxers/demux_matroska.h @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2000-2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * demultiplexer for matroska streams: shared header + */ + +#ifndef _DEMUX_MATROSKA_H_ +#define _DEMUX_MATROSKA_H_ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <ctype.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <zlib.h> + +#include "xine_internal.h" +#include "demux.h" +#include "buffer.h" +#include "bswap.h" + +#include "ebml.h" +#include "matroska.h" + +#define NUM_PREVIEW_BUFFERS 10 + +#define MAX_STREAMS 128 +#define MAX_FRAMES 32 + +#define WRAP_THRESHOLD 90000 + +typedef struct { + int track_num; + off_t *pos; + uint64_t *timecode; + int num_entries; + +} matroska_index_t; + +typedef struct { + + demux_plugin_t demux_plugin; + + xine_stream_t *stream; + + input_plugin_t *input; + + int status; + + ebml_parser_t *ebml; + + /* segment element */ + ebml_elem_t segment; + uint64_t timecode_scale; + int duration; /* in millis */ + int preview_sent; + int preview_mode; + char *title; + + /* meta seek info */ + int has_seekhead; + int seekhead_handled; + + /* seek info */ + matroska_index_t *indexes; + int num_indexes; + int first_cluster_found; + int skip_to_timecode; + int skip_for_track; + + /* tracks */ + int num_tracks; + int num_video_tracks; + int num_audio_tracks; + int num_sub_tracks; + + matroska_track_t *tracks[MAX_STREAMS]; + + /* maintain editions, number and capacity */ + int num_editions, cap_editions; + matroska_edition_t **editions; + + /* block */ + uint8_t *block_data; + size_t block_data_size; + + /* current tracks */ + matroska_track_t *video_track; /* to remove */ + matroska_track_t *audio_track; /* to remove */ + matroska_track_t *sub_track; /* to remove */ + uint64_t last_timecode; + + int send_newpts; + int buf_flag_seek; + + /* seekhead parsing */ + int top_level_list_size; + int top_level_list_max_size; + off_t *top_level_list; + + /* event handling (chapter navigation) */ + xine_event_queue_t *event_queue; +} demux_matroska_t ; + +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + +} demux_matroska_class_t; + +/* "entry points" for chapter handling. + * The parser descends into "Chapters" elements at the _parse_ function, + * and editions care about cleanup internally. */ +int matroska_parse_chapters(demux_matroska_t*); +void matroska_free_editions(demux_matroska_t*); + +/* Search an edition for the chapter matching a given timecode. + * + * Return: chapter index, or -1 if none is found. + * + * TODO: does not handle chapter end times yet. + */ +int matroska_get_chapter(demux_matroska_t*, uint64_t, matroska_edition_t**); + +#endif /* _DEMUX_MATROSKA_H_ */ diff --git a/src/demuxers/demux_mng.c b/src/demuxers/demux_mng.c index 12da8ca86..2fccd0b9e 100644 --- a/src/demuxers/demux_mng.c +++ b/src/demuxers/demux_mng.c @@ -104,7 +104,12 @@ static mng_bool mymng_close_stream(mng_handle mngh){ static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread){ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh); - *bytesread = this->input->read(this->input, buffer, size); + off_t n = this->input->read(this->input, buffer, size); + if (n < 0) { + *bytesread = 0; + return MNG_FALSE; + } + *bytesread = n; return MNG_TRUE; } @@ -112,11 +117,16 @@ static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 si static mng_bool mymng_process_header(mng_handle mngh, mng_uint32 width, mng_uint32 height){ demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh); + if (width > 0x8000 || height > 0x8000) + return MNG_FALSE; + this->bih.biWidth = (width + 7) & ~7; this->bih.biHeight = height; this->left_edge = (this->bih.biWidth - width) / 2; - this->image = malloc(this->bih.biWidth * height * 3); + this->image = malloc((mng_size_t)this->bih.biWidth * (mng_size_t)height * 3); + if (!this->image) + return MNG_FALSE; mng_set_canvasstyle(mngh, MNG_CANVAS_RGB8); @@ -171,7 +181,7 @@ static int demux_mng_send_chunk(demux_mng_t *this){ buf->decoder_flags = BUF_FLAG_FRAMERATE; buf->decoder_info[0] = 90 * this->timer_count; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = this->tick_count; buf->pts = 90 * this->tick_count; @@ -260,7 +270,7 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre demux_mng_t *this; - this = xine_xmalloc (sizeof (demux_mng_t)); + this = calloc(1, sizeof(demux_mng_t)); this->stream = stream; this->input = input; @@ -360,7 +370,7 @@ static void class_dispose(demux_class_t *this){ static void *init_plugin(xine_t *xine, void *data){ demux_mng_class_t *this; - this = xine_xmalloc (sizeof (demux_mng_class_t)); + this = calloc(1, sizeof(demux_mng_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_mod.c b/src/demuxers/demux_mod.c index e7c6f86b3..0439be7ee 100644 --- a/src/demuxers/demux_mod.c +++ b/src/demuxers/demux_mod.c @@ -73,17 +73,17 @@ typedef struct { char *title; char *artist; char *copyright; - off_t filesize; - + size_t filesize; + char *buffer; int64_t current_pts; - + ModPlug_Settings settings; ModPlugFile *mpfile; int mod_length; int seek_flag; /* this is set when a seek just occurred */ - + } demux_mod_t; typedef struct { @@ -130,30 +130,41 @@ static int probe_mod_file(demux_mod_t *this) { /* returns 1 if the MOD file was opened successfully, 0 otherwise */ static int open_mod_file(demux_mod_t *this) { int total_read; - + off_t input_length; + /* Get size and create buffer */ - this->filesize = this->input->get_length(this->input); + input_length = this->input->get_length(this->input); + /* Avoid potential issues with signed variables and e.g. read() returning -1 */ + if (input_length > 0x7FFFFFFF || input_length < 0) { + xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - size overflow\n"); + return 0; + } + this->filesize = input_length; this->buffer = (char *)malloc(this->filesize); - + if(!this->buffer) { + xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - allocation failure\n"); + return 0; + } + /* Seek to beginning */ this->input->seek(this->input, 0, SEEK_SET); - + /* Read data */ total_read = this->input->read(this->input, this->buffer, this->filesize); - + if(total_read != this->filesize) { xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - filesize error\n"); free(this->buffer); return 0; } - + this->mpfile = ModPlug_Load(this->buffer, this->filesize); if (this->mpfile==NULL) { xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - load error\n"); free(this->buffer); return 0; } - + /* Set up modplug engine */ ModPlug_GetSettings(&this->settings); this->settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */ @@ -161,13 +172,15 @@ static int open_mod_file(demux_mod_t *this) { this->settings.mBits = MOD_BITS; this->settings.mFrequency = MOD_SAMPLERATE; ModPlug_SetSettings(&this->settings); - + this->title = strdup(ModPlug_GetName(this->mpfile)); this->artist = strdup(""); this->copyright = strdup(""); - + this->mod_length = ModPlug_GetLength(this->mpfile); - + if (this->mod_length < 1) + this->mod_length = 1; /* avoids -ve & div-by-0 */ + return 1; } @@ -188,20 +201,20 @@ static int demux_mod_send_chunk(demux_plugin_t *this_gen) { buf->size = mlen; buf->pts = this->current_pts; buf->extra_info->input_time = buf->pts / 90; - + buf->extra_info->input_normpos = buf->extra_info->input_time * 65535 / this->mod_length; buf->decoder_flags = BUF_FLAG_FRAME_END; - + if (this->seek_flag) { _x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK); this->seek_flag = 0; } this->audio_fifo->put (this->audio_fifo, buf); - + this->current_pts += 90000 * mlen / OUT_BYTES_PER_SECOND; } - + return this->status; } @@ -247,9 +260,9 @@ static int demux_mod_seek (demux_plugin_t *this_gen, demux_mod_t *this = (demux_mod_t *) this_gen; int64_t seek_millis; - + if (start_pos) { - seek_millis = this->mod_length; + seek_millis = this->mod_length; seek_millis *= start_pos; seek_millis /= 65535; } else { @@ -259,14 +272,14 @@ static int demux_mod_seek (demux_plugin_t *this_gen, _x_demux_flush_engine(this->stream); ModPlug_Seek(this->mpfile, seek_millis); this->current_pts = seek_millis * 90; - + this->seek_flag = 1; return this->status; } static void demux_mod_dispose (demux_plugin_t *this_gen) { demux_mod_t *this = (demux_mod_t *) this_gen; - + ModPlug_Unload(this->mpfile); free(this->buffer); free(this->title); @@ -305,7 +318,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_mod_t)); + this = calloc(1, sizeof(demux_mod_t)); this->stream = stream; this->input = input; @@ -322,7 +335,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->status = DEMUX_FINISHED; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "TEST mod decode\n"); - + switch (stream->content_detection_method) { case METHOD_EXPLICIT: @@ -368,7 +381,19 @@ static const char *get_extensions (demux_class_t *this_gen) { } static const char *get_mimetypes (demux_class_t *this_gen) { - return NULL; + return "audio/x-mod: mod: SoundTracker/NoiseTracker/ProTracker Module;" + "audio/mod: mod: SoundTracker/NoiseTracker/ProTracker Module;" + "audio/it: it: ImpulseTracker Module;" + "audio/x-it: it: ImpulseTracker Module;" + "audio/x-stm: stm: ScreamTracker 2 Module;" + "audio/x-s3m: s3m: ScreamTracker 3 Module;" + "audio/s3m: s3m: ScreamTracker 3 Module;" + "application/playerpro: 669: 669 Tracker Module;" + "application/adrift: amf: ADRIFT Module File;" + "audio/med: med: Amiga MED/OctaMED Tracker Module Sound File;" + "audio/x-amf: amf: ADRIFT Module File;" + "audio/x-xm: xm: FastTracker II Audio;" + "audio/xm: xm: FastTracker II Audio;"; } static void class_dispose (demux_class_t *this_gen) { @@ -380,7 +405,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_mod_init_plugin (xine_t *xine, void *data) { demux_mod_class_t *this; - this = xine_xmalloc (sizeof (demux_mod_class_t)); + this = calloc(1, sizeof(demux_mod_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_mpc.c b/src/demuxers/demux_mpc.c index 346f0c2e6..04b25eeb5 100644 --- a/src/demuxers/demux_mpc.c +++ b/src/demuxers/demux_mpc.c @@ -24,7 +24,7 @@ * APE tag reading * Seeking?? */ - + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -47,6 +47,7 @@ #include "buffer.h" #include "bswap.h" #include "group_audio.h" +#include "id3.h" /* Note that the header is actually 25 bytes long, so we'd only read 28 * (because of byte swapping we have to round up to nearest multiple of 4) @@ -65,7 +66,7 @@ typedef struct { unsigned int frames; double samplerate; unsigned int length; - + unsigned int current_frame; unsigned int next_frame_bits; } demux_mpc_t; @@ -81,7 +82,7 @@ typedef struct { static int open_mpc_file(demux_mpc_t *this) { unsigned int first_frame_size; unsigned int id3v2_size = 0; - + /* Read the file header */ if (_x_demux_read_header(this->input, this->header, HEADER_SIZE) != HEADER_SIZE) return 0; @@ -89,46 +90,40 @@ static int open_mpc_file(demux_mpc_t *this) { /* TODO: non-seeking version */ if (INPUT_IS_SEEKABLE(this->input)) { /* Check for id3v2 tag */ - if ((this->header[0] == 'I') || - (this->header[1] == 'D') || - (this->header[2] == '3')) { - + if (id3v2_istag(this->header)) { + lprintf("found id3v2 header\n"); - + /* Read tag size */ - id3v2_size = (this->header[6] << 21) + - (this->header[7] << 14) + - (this->header[8] << 7) + - this->header[9] + 10; - + + id3v2_size = _X_BE_32_synchsafe(&this->header[6]) + 10; + /* Add footer size if one is present */ if (this->header[5] & 0x10) id3v2_size += 10; - + lprintf("id3v2 size: %u\n", id3v2_size); - + /* Seek past tag */ if (this->input->seek(this->input, id3v2_size, SEEK_SET) < 0) return 0; - + /* Read musepack header */ if (this->input->read(this->input, this->header, HEADER_SIZE) != HEADER_SIZE) return 0; } } - + /* Validate signature - We only support SV 7.x at the moment */ - if ((this->header[0] != 'M') || - (this->header[1] != 'P') || - (this->header[2] != '+') || + if ( memcmp(this->header, "MP+", 3) != 0 || ((this->header[3]&0x0f) != 0x07)) return 0; - + /* Get frame count */ this->current_frame = 0; this->frames = _X_LE_32(&this->header[4]); lprintf("number of frames: %u\n", this->frames); - + /* Get sample rate */ switch ((_X_LE_32(&this->header[8]) >> 16) & 0x3) { case 0: @@ -147,7 +142,7 @@ static int open_mpc_file(demux_mpc_t *this) { break; } lprintf("samplerate: %f kHz\n", this->samplerate); - + /* Calculate stream length */ this->length = (int) ((double) this->frames * 1152 / this->samplerate); lprintf("stream length: %d ms\n", this->length); @@ -156,14 +151,14 @@ static int open_mpc_file(demux_mpc_t *this) { first_frame_size = (_X_LE_32(&this->header[24]) >> 4) & 0xFFFFF; this->next_frame_bits = first_frame_size - 4; lprintf("first frame size: %u\n", first_frame_size); - + /* Move input to start of data (to nearest multiple of 4) */ this->input->seek(this->input, 28+id3v2_size, SEEK_SET); - + /* Set stream info */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, _X_ME_32(this->header)); - + return 1; } @@ -173,30 +168,30 @@ static int demux_mpc_send_chunk(demux_plugin_t *this_gen) { off_t bytes_read; buf_element_t *buf = NULL; - + /* Check if we've finished */ if (this->current_frame++ == this->frames) { lprintf("all frames read\n"); this->status = DEMUX_FINISHED; - return this->status; + return this->status; } lprintf("current frame: %u\n", this->current_frame); - - /* Get a buffer */ + + /* Get a buffer */ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_MPC; buf->pts = 0; buf->extra_info->total_time = this->length; - + /* Set normalised position */ - buf->extra_info->input_normpos = - (int) ((double) this->input->get_current_pos(this->input) * 65535 / + buf->extra_info->input_normpos = + (int) ((double) this->input->get_current_pos(this->input) * 65535 / this->input->get_length(this->input)); - + /* Set time based on there being 1152 audio frames per frame */ - buf->extra_info->input_time = + buf->extra_info->input_time = (int) ((double) this->current_frame * 1152 / this->samplerate); - + /* Calculate the number of bits that need to be read to finish reading * the current frame and read the size of the next frame. This number * has to be rounded up to the nearest 4 bytes on account of the @@ -209,35 +204,35 @@ static int demux_mpc_send_chunk(demux_plugin_t *this_gen) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("demux_mpc: frame too big for buffer")); this->status = DEMUX_FINISHED; - return this->status; + return this->status; } - + /* Read data */ bytes_read = this->input->read(this->input, buf->content, bytes_to_read); - if(bytes_read == 0) { + if(bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; - } else + } else buf->size = bytes_read; - + /* Read the size of the next frame */ if (this->current_frame < this->frames) { - /* The number of bits of the next frame we've read */ + /* The number of bits of the next frame we've read */ extra_bits_read = bits_to_read - (this->next_frame_bits+20); - + if(extra_bits_read <= 12) next_frame_size = (_X_LE_32(&buf->content[bytes_to_read-4]) >> extra_bits_read) & 0xFFFFF; else next_frame_size = ((_X_LE_32(&buf->content[bytes_to_read-8]) << (32-extra_bits_read)) | (_X_LE_32(&buf->content[bytes_to_read-4]) >> extra_bits_read)) & 0xFFFFF; - + lprintf("next frame size: %u\n", next_frame_size); - + /* The number of bits of the next frame still to read */ - this->next_frame_bits = next_frame_size - extra_bits_read; + this->next_frame_bits = next_frame_size - extra_bits_read; } - + /* Each buffer contains at least one frame */ buf->decoder_flags |= BUF_FLAG_FRAME_END; @@ -260,14 +255,14 @@ static void demux_mpc_send_headers(demux_plugin_t *this_gen) { /* Send header to decoder */ if (this->audio_fifo) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - + buf->type = BUF_AUDIO_MPC; buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END; buf->decoder_info[0] = this->input->get_length(this->input); buf->decoder_info[1] = 0; buf->decoder_info[2] = 0; buf->decoder_info[3] = 0; - + /* Copy the header */ buf->size = HEADER_SIZE; memcpy(buf->content, this->header, buf->size); @@ -324,7 +319,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_mpc_t *this; - this = xine_xmalloc (sizeof (demux_mpc_t)); + this = calloc(1, sizeof(demux_mpc_t)); this->stream = stream; this->input = input; @@ -356,12 +351,12 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str case METHOD_BY_CONTENT: case METHOD_EXPLICIT: - + if (!open_mpc_file(this)) { free (this); return NULL; } - + break; default: @@ -381,11 +376,12 @@ static const char *get_identifier (demux_class_t *this_gen) { } static const char *get_extensions (demux_class_t *this_gen) { - return "mpc mp+"; + return "mpc mp+ mpp"; } static const char *get_mimetypes (demux_class_t *this_gen) { - return NULL; + return "audio/musepack: mpc, mp+, mpp: Musepack audio;" + "audio/x-musepack: mpc, mp+, mpp: Musepack audio;"; } static void class_dispose (demux_class_t *this_gen) { @@ -397,7 +393,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_mpc_init_plugin (xine_t *xine, void *data) { demux_mpc_class_t *this; - this = xine_xmalloc (sizeof (demux_mpc_class_t)); + this = calloc(1, sizeof(demux_mpc_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 4419f8404..dbaae108d 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -170,7 +170,7 @@ static void find_mdat_atom(input_plugin_t *input, off_t *mdat_offset, } else atom_size -= ATOM_PREAMBLE_SIZE; - + input->seek(input, atom_size, SEEK_CUR); } } @@ -279,6 +279,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) if((this->dummy_space[0] & 0xE0) == 0x20) { buf = this->input->read_block (this->input, this->video_fifo, len-1); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } track = (this->dummy_space[0] & 0x1f); @@ -298,17 +302,21 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) int spu_id = this->dummy_space[1] & 0x03; buf = this->input->read_block (this->input, this->video_fifo, len-1); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } buf->type = BUF_SPU_SVCD + spu_id; buf->pts = pts; - /* There is a bug in WinSubMux doesn't redo PACK headers in + /* There is a bug in WinSubMux doesn't redo PACK headers in the private stream 1. This might cause the below to mess up. if( !preview_mode ) check_newpts( this, this->pts, PTS_VIDEO ); */ this->video_fifo->put (this->video_fifo, buf); - lprintf ("SPU SVCD PACK (pts: %"PRId64", spu id: %d) put on FIFO\n", + lprintf ("SPU SVCD PACK (pts: %"PRId64", spu id: %d) put on FIFO\n", buf->pts, spu_id); return; @@ -318,6 +326,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) if((this->dummy_space[0] & 0xfc) == 0x00) { buf = this->input->read_block (this->input, this->video_fifo, len-1); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } buf->type = BUF_SPU_CVD + (this->dummy_space[0] & 0x03); buf->pts = pts; @@ -330,7 +342,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) if((this->dummy_space[0] & 0xf0) == 0x80) { /* read rest of header - AC3 */ - i = this->input->read (this->input, this->dummy_space+1, 3); + this->input->read (this->input, this->dummy_space+1, 3); /* contents */ for (i = len - 4; i > 0; i -= (this->audio_fifo) @@ -356,10 +368,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) buf->decoder_flags = BUF_FLAG_PREVIEW; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = - (int)( ((int64_t)this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * 65535) / this->input->get_length (this->input) ); - + if (this->rate) buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) * 1000 / (this->rate * 50)); @@ -376,6 +388,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) i = this->input->read (this->input, this->dummy_space+1, 6); buf = this->input->read_block (this->input, this->video_fifo, len-7); + if (! buf) { + this->status = DEMUX_FINISHED; + return; + } buf->type = BUF_AUDIO_LPCM_BE + track; buf->decoder_flags |= BUF_FLAG_SPECIAL; @@ -389,8 +405,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) buf->decoder_flags |= BUF_FLAG_PREVIEW; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = - (int)( ((int64_t)this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * 65535) / this->input->get_length (this->input) ); if (this->rate) buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -431,9 +447,9 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) header_len -= 5 ; } - i = this->input->read (this->input, this->dummy_space, header_len); + this->input->read (this->input, this->dummy_space, header_len); - for (i = len; i > 0; i -= (this->audio_fifo) + for (i = len; i > 0; i -= (this->audio_fifo) ? this->audio_fifo->buffer_pool_buf_size : this->video_fifo->buffer_pool_buf_size) { if(this->audio_fifo) { buf = this->input->read_block (this->input, this->audio_fifo, @@ -453,8 +469,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) buf->decoder_flags = BUF_FLAG_PREVIEW; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = - (int)( ((int64_t)this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * 65535) / this->input->get_length (this->input) ); if (this->rate) buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -489,21 +505,21 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) header_len -= 5 ; } - + if ((flags & 0x40) == 0x40) { - + w = read_bytes(this, 1); dts = (int64_t)(w & 0x0e) << 29 ; w = read_bytes(this, 2); dts |= (w & 0xFFFE) << 14; w = read_bytes(this, 2); dts |= (w & 0xFFFE) >> 1; - + header_len -= 5 ; - } + } /* read rest of header */ - i = this->input->read (this->input, this->dummy_space, header_len); + this->input->read (this->input, this->dummy_space, header_len); /* contents */ @@ -526,8 +542,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) buf->decoder_flags = BUF_FLAG_PREVIEW; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = - (int)( ((int64_t)this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * 65535) / this->input->get_length (this->input) ); if (this->rate) buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -538,7 +554,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } else { - for (i = len; i > 0; i -= 10000) + for (i = len; i > 0; i -= 10000) this->input->read (this->input, this->dummy_space, (i > 10000) ? 10000 : i); } @@ -606,7 +622,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) pts |= (w & 0xFFFE) << 14; w = read_bytes(this, 2); len -= 2; - + pts |= (w & 0xFFFE) >> 1; w = read_bytes(this, 1); len -= 1; @@ -633,11 +649,11 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) lprintf("use scr\n"); pts = scr; } - + if ((stream_id & 0xe0) == 0xc0) { int track = stream_id & 0x1f; - for (i = len; i > 0; i -= (this->audio_fifo) + for (i = len; i > 0; i -= (this->audio_fifo) ? this->audio_fifo->buffer_pool_buf_size : this->video_fifo->buffer_pool_buf_size) { if(this->audio_fifo) { buf = this->input->read_block (this->input, this->audio_fifo, @@ -657,8 +673,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) buf->decoder_flags = BUF_FLAG_PREVIEW; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = - (int)( ((int64_t)this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * 65535) / this->input->get_length (this->input) ); if (this->rate) buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -692,8 +708,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) buf->decoder_flags = BUF_FLAG_PREVIEW; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = - (int)( ((int64_t)this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = + (int)( ((int64_t)this->input->get_current_pos (this->input) * 65535) / this->input->get_length (this->input) ); if (this->rate) buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -704,12 +720,12 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } else if (stream_id == 0xbd) { - for (i = len; i > 0; i -= 10000) + for (i = len; i > 0; i -= 10000) this->input->read (this->input, this->dummy_space, (i > 10000) ? 10000 : i); } else { - for (i = len; i > 0; i -= 10000) + for (i = len; i > 0; i -= 10000) this->input->read (this->input, this->dummy_space, (i > 10000) ? 10000 : i); } } @@ -920,7 +936,7 @@ static void demux_mpeg_resync (demux_mpeg_t *this, uint32_t buf) { if (pos == len) { len = this->input->read(this->input, dummy_buf, sizeof(dummy_buf)); pos = 0; - if (len == 0) { + if (len <= 0) { this->status = DEMUX_FINISHED; break; } @@ -962,40 +978,40 @@ static void demux_mpeg_send_headers (demux_plugin_t *this_gen) { demux_mpeg_t *this = (demux_mpeg_t *) this_gen; uint32_t w; int num_buffers = NUM_PREVIEW_BUFFERS; - + this->video_fifo = this->stream->video_fifo; this->audio_fifo = this->stream->audio_fifo; this->rate = 0; /* fixme */ this->last_pts[0] = 0; this->last_pts[1] = 0; - + _x_demux_control_start(this->stream); /* * send preview buffers for stream/meta_info */ - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); this->preview_mode = 1; - + this->input->seek (this->input, 4, SEEK_SET); - + this->status = DEMUX_OK ; - + do { w = parse_pack_preview (this, &num_buffers); - + if (w != 0x000001ba) demux_mpeg_resync (this, w); - + num_buffers --; - + } while ( (this->status == DEMUX_OK) && (num_buffers > 0)); - + this->status = DEMUX_OK ; _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->rate * 50 * 8); @@ -1067,7 +1083,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str input_plugin_t *input) { demux_mpeg_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_t)); + this = calloc(1, sizeof(demux_mpeg_t)); this->stream = stream; this->input = input; @@ -1139,7 +1155,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str /* go through the same MPEG detection song and dance */ if (input->read(input, buf, 4) == 4) { - if (!buf[0] && !buf[1] && (buf[2] == 0x01) + if (!buf[0] && !buf[1] && (buf[2] == 0x01) && (buf[3] == 0xba)) /* if so, take it */ break; } @@ -1147,7 +1163,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str free (this); return NULL; } - + /* reset position for next check */ if (input->seek(input, 0, SEEK_SET) != 0) { free (this); @@ -1158,7 +1174,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str fourcc_tag = _X_BE_32(&buf[0]); if (fourcc_tag == RIFF_TAG) { uint8_t large_buf[1024]; - + if (input->read(input, large_buf, 12) != 12) { free(this); return NULL; @@ -1177,7 +1193,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str * MPEG video marker. No, it's not a very efficient approach, but * if execution has reached this special case, this is currently * the best chance for detecting the file automatically. Also, - * be extra lazy and do not bother skipping over the data + * be extra lazy and do not bother skipping over the data * header. */ for (i = 0; i < RIFF_CHECK_KILOBYTES && !ok; i++) { if (input->read(input, large_buf, 1024) != 1024) @@ -1246,7 +1262,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_mpeg_class_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_class_t)); + this = calloc(1, sizeof(demux_mpeg_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; @@ -1266,7 +1282,7 @@ static const demuxer_info_t demux_info_mpeg = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "mpeg", XINE_VERSION_CODE, &demux_info_mpeg, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 32638129d..aa5294e8b 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,7 +20,7 @@ * demultiplexer for mpeg 1/2 program streams * used with fixed blocksize devices (like dvd/vcd) */ - + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -44,7 +44,7 @@ #define NUM_PREVIEW_BUFFERS 250 #define DISC_TRESHOLD 90000 -#define WRAP_THRESHOLD 120000 +#define WRAP_THRESHOLD 120000 #define PTS_AUDIO 0 #define PTS_VIDEO 1 @@ -56,22 +56,19 @@ typedef struct demux_mpeg_block_s { demux_plugin_t demux_plugin; - xine_stream_t *stream; + xine_stream_t *stream; fifo_buffer_t *audio_fifo; fifo_buffer_t *video_fifo; input_plugin_t *input; int status; - + int blocksize; int rate; char cur_mrl[256]; - uint8_t *scratch; - void *scratch_base; - int64_t nav_last_end_pts; int64_t nav_last_start_pts; int64_t last_pts[2]; @@ -126,30 +123,30 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_ /* OK, i think demux_mpeg_block discontinuity handling demands some explanation: - + - The preferred discontinuity handling/detection for DVD is based on NAV packets information. Most of the time it will provide us very accurate and reliable information. - + - Has been shown that sometimes a DVD discontinuity may happen before a new NAV packet arrives (seeking?). To avoid sending wrong PTS to decoders we _used_ to check for SCR discontinuities. Unfortunately some VCDs have very broken SCR values causing false triggering. - + - To fix the above problem (also note that VCDs don't have NAV packets) we fallback to the same PTS-based wrap detection as used in demux_mpeg. The only trick is to not send discontinuity information if NAV packets have already done the job. - + [Miguel 02-05-2002] */ static void check_newpts( demux_mpeg_block_t *this, int64_t pts, int video ) { int64_t diff; - + diff = pts - this->last_pts[video]; - + if( pts && (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) { /* check if pts is outside nav pts range. any stream without nav must enter here. */ @@ -167,10 +164,10 @@ static void check_newpts( demux_mpeg_block_t *this, int64_t pts, int video ) } else { lprintf("no wrap detected\n" ); } - + this->last_pts[1-video] = 0; } - + if( pts ) this->last_pts[video] = pts; } @@ -223,9 +220,9 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m buf->decoder_flags = BUF_FLAG_PREVIEW; else buf->decoder_flags = 0; - + if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); while(p < (buf->content + this->blocksize)) { @@ -438,7 +435,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_ return 12; } else { /* mpeg2 */ - + int num_stuffing_bytes; /* system_clock_reference */ @@ -502,7 +499,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_ * the NAV packet for a much more accurate timing */ if (buf->extra_info->input_time) { int64_t cell_time, frames; - + cell_time = (p[7+0x18] >> 4 ) * 10 * 60 * 60 * 1000; cell_time += (p[7+0x18] & 0x0f) * 60 * 60 * 1000; cell_time += (p[7+0x19] >> 4 ) * 10 * 60 * 1000; @@ -511,7 +508,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_ cell_time += (p[7+0x1a] & 0x0f) * 1000; frames = ((p[7+0x1b] & 0x30) >> 4) * 10; frames += ((p[7+0x1b] & 0x0f) ) ; - + if (p[7+0x1b] & 0x80) cell_time += (frames * 1000)/25; else @@ -521,7 +518,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_ this->last_cell_pos = this->input->get_current_pos (this->input); this->last_begin_time = buf->extra_info->input_time; } - + lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n", start_pts, end_pts); @@ -572,14 +569,14 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme } if (this->rate && !buf->extra_info->input_time) - buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) + buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) * 1000 / (this->rate * 50)); if (this->mpeg1) { header_len = 6; p += 6; /* packet_len -= 6; */ while ((p[0] & 0x80) == 0x80) { - p++; + p++; header_len++; this->packet_len--; /* printf ("stuffing\n");*/ @@ -592,9 +589,9 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme this->packet_len -= 2; } - this->pts = 0; + this->pts = 0; this->dts = 0; - + if ((p[0] & 0xf0) == 0x20) { this->pts = (int64_t)(p[ 0] & 0x0E) << 29 ; this->pts |= p[ 1] << 22 ; @@ -611,19 +608,19 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme this->pts |= (p[ 2] & 0xFE) << 14 ; this->pts |= p[ 3] << 7 ; this->pts |= (p[ 4] & 0xFE) >> 1 ; - + this->dts = (int64_t)(p[ 5] & 0x0E) << 29 ; this->dts |= p[ 6] << 22 ; this->dts |= (p[ 7] & 0xFE) << 14 ; this->dts |= p[ 8] << 7 ; this->dts |= (p[ 9] & 0xFE) >> 1 ; - + p += 10; header_len += 10; this->packet_len -= 10; return header_len; } else { - p++; + p++; header_len++; this->packet_len--; return header_len; @@ -667,13 +664,13 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme this->pts = 0; if (p[7] & 0x40) { /* dts avail */ - + this->dts = (int64_t)(p[14] & 0x0E) << 29 ; this->dts |= p[15] << 22 ; this->dts |= (p[16] & 0xFE) << 14 ; this->dts |= p[17] << 7 ; this->dts |= (p[18] & 0xFE) >> 1 ; - + } else this->dts = 0; @@ -702,16 +699,16 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ buf->content = p+1; buf->size = this->packet_len-1; - + buf->type = BUF_SPU_DVD + spu_id; buf->decoder_flags |= BUF_FLAG_SPECIAL; buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE; buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE; buf->pts = this->pts; - - this->video_fifo->put (this->video_fifo, buf); + + this->video_fifo->put (this->video_fifo, buf); lprintf ("SPU PACK put on fifo\n"); - + return -1; } @@ -727,9 +724,9 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ if( !preview_mode ) check_newpts( this, this->pts, PTS_VIDEO ); */ - this->video_fifo->put (this->video_fifo, buf); + this->video_fifo->put (this->video_fifo, buf); lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); - + return -1; } @@ -744,29 +741,29 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ /* this is probably wrong: if( !preview_mode ) check_newpts( this, this->pts, PTS_VIDEO ); - */ - this->video_fifo->put (this->video_fifo, buf); + */ + this->video_fifo->put (this->video_fifo, buf); lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); - + return -1; } if ((p[0]&0xF0) == 0x80) { - + track = p[0] & 0x0F; /* hack : ac3 track */ - /* Number of frame headers + /* Number of frame headers * * Describes the number of a52 frame headers that start in this pack (One pack per DVD sector). * * Likely values: 1 or 2. */ buf->decoder_info[1] = p[1]; - /* First access unit pointer. + /* First access unit pointer. * * Describes the byte offset within this pack to the beginning of the first A52 frame header. * The PTS from this pack applies to the beginning of the first A52 frame that starts in this pack. - * Any bytes before this offset should be considered to belong to the previous A52 frame. + * Any bytes before this offset should be considered to belong to the previous A52 frame. * and therefore be tagged with a PTS value derived from the previous pack. * * Likely values: Anything from 1 to the size of an A52 frame. @@ -867,7 +864,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ buf->free_buffer(buf); return -1; } - + } else if ((p[0]&0xf0) == 0xa0) { int pcm_offset; @@ -914,7 +911,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ buf->decoder_flags |= BUF_FLAG_SPECIAL; buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG; buf->decoder_info[2] = p[5]; - + pcm_offset = 7; buf->content = p+pcm_offset; @@ -933,7 +930,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ buf->free_buffer(buf); return -1; } - + } /* Some new streams have been encountered. 1) DVD+RW disc recorded with a Philips DVD recorder: - new unknown sub-stream id of 0xff @@ -1006,10 +1003,10 @@ static int demux_mpeg_block_send_chunk (demux_plugin_t *this_gen) { } #ifdef ESTIMATE_RATE_FIXED -/*! - Estimate bitrate by looking inside the MPEG file for presentation - time stamps (PTS) and computing how far apart these are - in bytes and in time. +/*! + Estimate bitrate by looking inside the MPEG file for presentation + time stamps (PTS) and computing how far apart these are + in bytes and in time. On failure return 0. @@ -1040,23 +1037,23 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { int rate=0; /* The return rate value */ int stream_id; - /* We can't estimate by sampling if we don't thave the ability to + /* We can't estimate by sampling if we don't thave the ability to randomly access the and more importantly reset after accessessing. */ if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE)) return 0; mpeg_length= this->input->get_length (this->input); - step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize); + step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize); if (step <= 0) step = blocksize; /* avoid endless loop for tiny files */ pos = step; /* At this point "pos", and "step" are a multiple of blocksize and they should continue to be so throughout. */ - + this->input->seek (this->input, pos, SEEK_SET); - while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize)) + while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize)) && count < MAX_SAMPLES && reads++ < MAX_READS ) { p = buf->content; /* len = this->mnBlocksize; */ @@ -1065,9 +1062,9 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { is_mpeg1 = (p[4] & 0x40) == 0; - if (is_mpeg1) + if (is_mpeg1) p += 12; - else + else p += 14 + (p[0xD] & 0x07); } @@ -1084,7 +1081,7 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { } stream_id = p[3]; - pts = 0; + pts = 0; if ((stream_id < 0xbc) || ((stream_id & 0xf0) != 0xe0)) { pos += (off_t) blocksize; @@ -1114,18 +1111,18 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { pts |= (p[ 2] & 0xFE) << 14 ; pts |= p[ 3] << 7 ; pts |= (p[ 4] & 0xFE) >> 1 ; - } + } } } else { /* mpeg 2 */ - + if (p[7] & 0x80) { /* pts avail */ - + pts = (int64_t)(p[ 9] & 0x0E) << 29 ; pts |= p[10] << 22 ; pts |= (p[11] & 0xFE) << 14 ; pts |= p[12] << 7 ; pts |= (p[13] & 0xFE) >> 1 ; - + } else pts = 0; } @@ -1135,16 +1132,16 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { if ( (pos>last_pos) && (pts>last_pts) ) { int cur_rate; - + cur_rate = ((pos - last_pos)*90000) / ((pts - last_pts) * 50); - + rate = (count * rate + cur_rate) / (count+1); count ++; - + /* - printf ("demux_mpeg_block: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n", - stream_id, pos, pts, cur_rate, rate); + printf ("demux_mpeg_block: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n", + stream_id, pos, pts, cur_rate, rate); */ } @@ -1168,15 +1165,14 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { lprintf("est_rate=%d\n",rate); return rate; - + } #endif /*ESTIMATE_RATE_FIXED*/ static void demux_mpeg_block_dispose (demux_plugin_t *this_gen) { demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen; - - free (this->scratch_base); + free (this); } @@ -1186,23 +1182,24 @@ static int demux_mpeg_block_get_status (demux_plugin_t *this_gen) { return this->status; } -static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this, +static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this, input_plugin_t *input) { + uint8_t scratch[4]; input->seek(input, 2048, SEEK_SET); - if (!input->read(input, this->scratch, 4)) + if (input->read(input, scratch, 4) != 4) return 0; - if (this->scratch[0] || this->scratch[1] - || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) { + if (scratch[0] || scratch[1] + || (scratch[2] != 0x01) || (scratch[3] != 0xba)) { input->seek(input, 2324, SEEK_SET); - if (!input->read(input, this->scratch, 4)) + if (input->read(input, scratch, 4) != 4) return 0; - if (this->scratch[0] || this->scratch[1] - || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) + if (scratch[0] || scratch[1] + || (scratch[2] != 0x01) || (scratch[3] != 0xba)) return 0; - + return 2324; } else return 2048; @@ -1222,34 +1219,34 @@ static void demux_mpeg_block_send_headers (demux_plugin_t *this_gen) { if (!this->blocksize) return; } - - /* + + /* * send start buffer */ - + _x_demux_control_start(this->stream); - + #ifdef USE_ILL_ADVISED_ESTIMATE_RATE_INITIALLY - if (!this->rate) + if (!this->rate) this->rate = demux_mpeg_block_estimate_rate (this); -#else +#else /* Set to Use rate given in by stream initially. */ - this->rate = 0; + this->rate = 0; #endif - + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { - + int num_buffers = NUM_PREVIEW_BUFFERS; - + this->input->seek (this->input, 0, SEEK_SET); - + this->status = DEMUX_OK ; while ( (num_buffers>0) && (this->status == DEMUX_OK) ) { - + demux_mpeg_block_parse_pack(this, 1); num_buffers --; } - } + } /* else FIXME: implement preview generation from PREVIEW data */ this->status = DEMUX_OK; @@ -1268,19 +1265,19 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen, this->input->get_length (this->input) ); if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { - + if (start_pos) { start_pos /= (off_t) this->blocksize; start_pos *= (off_t) this->blocksize; - + this->input->seek (this->input, start_pos, SEEK_SET); } else if (start_time) { - + if( this->input->seek_time ) { this->input->seek_time (this->input, start_time, SEEK_SET); } else { start_time /= 1000; - + if (this->last_cell_time) { start_pos = start_time - (this->last_cell_time + this->last_begin_time)/1000; start_pos *= this->rate; @@ -1293,20 +1290,20 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen, } start_pos /= (off_t) this->blocksize; start_pos *= (off_t) this->blocksize; - + this->input->seek (this->input, start_pos, SEEK_SET); } } else this->input->seek (this->input, 0, SEEK_SET); } - + /* * now start demuxing */ this->last_cell_time = 0; this->send_newpts = 1; if( !playing ) { - + this->buf_flag_seek = 0; this->nav_last_end_pts = this->nav_last_start_pts = 0; this->status = DEMUX_OK ; @@ -1317,7 +1314,7 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen, this->nav_last_end_pts = this->nav_last_start_pts = 0; _x_demux_flush_engine(this->stream); } - + return this->status; } @@ -1335,7 +1332,7 @@ static void demux_mpeg_block_accept_input (demux_mpeg_block_t *this, lprintf ("mrl %s is new\n", this->cur_mrl); - } + } else { lprintf ("mrl %s is known, bitrate: %d\n", this->cur_mrl, this->rate * 50 * 8); @@ -1349,7 +1346,7 @@ static int demux_mpeg_block_get_stream_length (demux_plugin_t *this_gen) { * find input plugin */ - if (this->rate) + if (this->rate) return (int)((int64_t) 1000 * this->input->get_length (this->input) / (this->rate * 50)); else @@ -1371,10 +1368,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str input_plugin_t *input = (input_plugin_t *) input_gen; demux_mpeg_block_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_block_t)); + this = calloc(1, sizeof(demux_mpeg_block_t)); this->stream = stream; this->input = input; - + this->demux_plugin.send_headers = demux_mpeg_block_send_headers; this->demux_plugin.send_chunk = demux_mpeg_block_send_chunk; this->demux_plugin.seek = demux_mpeg_block_seek; @@ -1385,25 +1382,25 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_optional_data = demux_mpeg_block_get_optional_data; this->demux_plugin.demux_class = class_gen; - this->scratch = xine_xmalloc_aligned (512, 4096, &this->scratch_base); this->status = DEMUX_FINISHED; lprintf ("open_plugin:detection_method=%d\n", stream->content_detection_method); - + switch (stream->content_detection_method) { - + case METHOD_BY_CONTENT: { /* use demux_mpeg for non-block devices */ if (!(input->get_capabilities(input) & INPUT_CAP_BLOCK)) { - free (this->scratch_base); free (this); return NULL; } if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) { + uint8_t scratch[5] = {0xff, 0xff, 0xff, 0xff, 0xff}; /* result of input->read() won't matter */ + this->blocksize = input->get_blocksize(input); lprintf("open_plugin:blocksize=%d\n",this->blocksize); @@ -1411,28 +1408,25 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->blocksize = demux_mpeg_detect_blocksize( this, input ); if (!this->blocksize) { - free (this->scratch_base); free (this); return NULL; } input->seek(input, 0, SEEK_SET); - if (input->read(input, this->scratch, this->blocksize)) { + if (input->read(input, scratch, 5)) { lprintf("open_plugin:read worked\n"); - if (this->scratch[0] || this->scratch[1] - || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) { + if (scratch[0] || scratch[1] + || (scratch[2] != 0x01) || (scratch[3] != 0xba)) { lprintf("open_plugin:scratch failed\n"); - free (this->scratch_base); free (this); return NULL; } /* if it's a file then make sure it's mpeg-2 */ if ( !input->get_blocksize(input) - && ((this->scratch[4]>>4) != 4) ) { - free (this->scratch_base); + && ((scratch[4]>>4) != 4) ) { free (this); return NULL; } @@ -1446,7 +1440,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; } } - free (this->scratch_base); free (this); return NULL; } @@ -1467,7 +1460,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str ending = strrchr(mrl, '.'); if (!ending) { - free (this->scratch_base); free (this); return NULL; } @@ -1477,7 +1469,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->blocksize = 2048; demux_mpeg_block_accept_input(this, input); } else { - free (this->scratch_base); free (this); return NULL; } @@ -1495,7 +1486,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->blocksize = demux_mpeg_detect_blocksize( this, input ); if (!this->blocksize) { - free (this->scratch_base); free (this); return NULL; } @@ -1505,7 +1495,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; default: - free (this->scratch_base); free (this); return NULL; } @@ -1540,7 +1529,7 @@ static void *init_plugin (xine_t *xine, void *data) { demux_mpeg_block_class_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_block_class_t)); + this = calloc(1, sizeof(demux_mpeg_block_class_t)); this->config = xine->config; this->xine = xine; @@ -1562,7 +1551,7 @@ static const demuxer_info_t demux_info_mpeg_block = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "mpeg_block", XINE_VERSION_CODE, &demux_info_mpeg_block, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c index 423da5e24..0fe97fb93 100644 --- a/src/demuxers/demux_mpeg_pes.c +++ b/src/demuxers/demux_mpeg_pes.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2006 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -24,7 +24,7 @@ * (c) 2003 James Courtier-Dutton James@superbug.demon.co.uk * This code might also decode normal MPG files. */ - + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -48,7 +48,7 @@ #define NUM_PREVIEW_BUFFERS 250 #define DISC_TRESHOLD 90000 -#define WRAP_THRESHOLD 270000 +#define WRAP_THRESHOLD 270000 #define PTS_AUDIO 0 #define PTS_VIDEO 1 @@ -60,14 +60,14 @@ typedef struct demux_mpeg_pes_s { demux_plugin_t demux_plugin; - xine_stream_t *stream; + xine_stream_t *stream; fifo_buffer_t *audio_fifo; fifo_buffer_t *video_fifo; input_plugin_t *input; int status; - + int rate; char cur_mrl[256]; @@ -91,7 +91,7 @@ typedef struct demux_mpeg_pes_s { uint8_t mpeg1:1; uint8_t wait_for_program_stream_pack_header:1; uint8_t mpeg12_h264_detected:2; - + int last_begin_time; int64_t last_cell_time; off_t last_cell_pos; @@ -202,7 +202,7 @@ static int detect_pts_discontinuity( demux_mpeg_pes_t *this, int64_t pts, int vi /* no discontinuity detected */ return 0; } - + static void check_newpts( demux_mpeg_pes_t *this, int64_t pts, int video ) { if( pts && (this->send_newpts || detect_pts_discontinuity(this, pts, video) ) ) { @@ -226,7 +226,7 @@ static void check_newpts( demux_mpeg_pes_t *this, int64_t pts, int video ) /* clear pts on the other track to avoid detecting the same discontinuity again */ this->last_pts[1-video] = 0; } - + if( pts ) this->last_pts[video] = pts; } @@ -257,9 +257,8 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode) uint8_t *p; int32_t result; off_t i; - int32_t n; uint8_t buf6[ 6 ]; - + this->scr = 0; this->preview_mode = preview_mode; @@ -274,16 +273,16 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode) while ((p[2] != 1) || p[0] || p[1]) { /* resync code */ - for(n=0;n<5;n++) p[n]=p[n+1]; + memmove(p, p+1, 5); i = read_data(this, p+5, (off_t) 1); if (i != 1) { this->status = DEMUX_FINISHED; return; } } - + /* FIXME: buf must be allocated from somewhere before calling here. */ - + /* these streams should be allocated on the audio_fifo, if available. */ if ((0xC0 <= p[ 3 ] && p[ 3 ] <= 0xDF) /* audio_stream */ || 0xBD == p[ 3 ]) /* private_sream_1 */ @@ -302,20 +301,19 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode) return; } } - + p = buf->mem; /* copy local buffer to fifo element. */ - for (n = 0; n < sizeof (buf6); n++) - p[ n ] = buf6[ n ]; - + memcpy(p, buf6, sizeof(buf6)); + if (preview_mode) buf->decoder_flags = BUF_FLAG_PREVIEW; else buf->decoder_flags = 0; - + if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); this->stream_id = p[3]; @@ -414,7 +412,7 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode) xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("xine-lib:demux_mpeg_pes: Unrecognised stream_id 0x%02x. " "Please report this to xine developers.\n"), this->stream_id); - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: packet_len=%d\n", this->packet_len); buf->free_buffer (buf); return; @@ -437,11 +435,11 @@ static int32_t parse_padding_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elem { /* Handle Jumbo frames from VDR. */ int i; - + int size = buf->max_size; if ((todo - done) < size) size = todo - done; - + i = read_data(this, buf->mem, (off_t)size); if (i != size) break; @@ -458,98 +456,98 @@ static int32_t parse_padding_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elem static int32_t parse_program_stream_map(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x.\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_ecm_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_emm_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_dsmcc_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_iec_13522_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_h222_typeA_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_h222_typeB_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_h222_typeC_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_h222_typeD_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_h222_typeE_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_IEC14496_SL_packetized_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_IEC14496_FlexMux_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_program_stream_directory(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; } static int32_t parse_ancillary_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) { /* FIXME: Implement */ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id); buf->free_buffer (buf); return -1; @@ -590,7 +588,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_pes_t *this, uint8_t return 12; } else { /* mpeg2 */ - + int num_stuffing_bytes; /* system_clock_reference */ @@ -664,7 +662,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el * the NAV packet for a much more accurate timing */ if (buf->extra_info->input_time) { int64_t cell_time, frames; - + cell_time = (p[7+0x18] >> 4 ) * 10 * 60 * 60 * 1000; cell_time += (p[7+0x18] & 0x0f) * 60 * 60 * 1000; cell_time += (p[7+0x19] >> 4 ) * 10 * 60 * 1000; @@ -673,7 +671,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el cell_time += (p[7+0x1a] & 0x0f) * 1000; frames = ((p[7+0x1b] & 0x30) >> 4) * 10; frames += ((p[7+0x1b] & 0x0f) ) ; - + if (p[7+0x1b] & 0x80) cell_time += (frames * 1000)/25; else @@ -683,7 +681,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el this->last_cell_pos = this->input->get_current_pos (this->input); this->last_begin_time = buf->extra_info->input_time; } - + lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n", start_pts, end_pts); @@ -733,7 +731,7 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element } if (this->rate && !buf->extra_info->input_time) - buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) + buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) * 1000 / (this->rate * 50)); /* FIXME: This was determined by comparing a single MPEG1 and a single MPEG2 stream */ @@ -748,7 +746,7 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element p += 6; /* packet_len -= 6; */ while ((p[0] & 0x80) == 0x80) { - p++; + p++; header_len++; this->packet_len--; /* printf ("stuffing\n");*/ @@ -761,9 +759,9 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element this->packet_len -= 2; } - this->pts = 0; + this->pts = 0; this->dts = 0; - + if ((p[0] & 0xf0) == 0x20) { this->pts = (int64_t) (p[ 0] & 0x0E) << 29 ; this->pts |= (int64_t) p[ 1] << 22 ; @@ -780,19 +778,19 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element this->pts |= (int64_t) (p[ 2] & 0xFE) << 14 ; this->pts |= (int64_t) p[ 3] << 7 ; this->pts |= (int64_t) (p[ 4] & 0xFE) >> 1 ; - + this->dts = (int64_t) (p[ 5] & 0x0E) << 29 ; this->dts |= (int64_t) p[ 6] << 22 ; this->dts |= (int64_t) (p[ 7] & 0xFE) << 14 ; this->dts |= (int64_t) p[ 8] << 7 ; this->dts |= (int64_t) (p[ 9] & 0xFE) >> 1 ; - + p += 10; header_len += 10; this->packet_len -= 10; return header_len; } else { - p++; + p++; header_len++; this->packet_len--; return header_len; @@ -836,13 +834,13 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element this->pts = 0; if (p[7] & 0x40) { /* dts avail */ - + this->dts = (int64_t) (p[14] & 0x0E) << 29 ; this->dts |= (int64_t) p[15] << 22 ; this->dts |= (int64_t) (p[16] & 0xFE) << 14 ; this->dts |= (int64_t) p[17] << 7 ; this->dts |= (int64_t) (p[18] & 0xFE) >> 1 ; - + } else this->dts = 0; @@ -871,16 +869,16 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el buf->content = p+1; buf->size = this->packet_len-1; - + buf->type = BUF_SPU_DVD + spu_id; buf->decoder_flags |= BUF_FLAG_SPECIAL; buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE; buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE; buf->pts = this->pts; - - this->video_fifo->put (this->video_fifo, buf); + + this->video_fifo->put (this->video_fifo, buf); lprintf ("SPU PACK put on fifo\n"); - + return this->packet_len + result; } @@ -896,9 +894,9 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el if( !preview_mode ) check_newpts( this, this->pts, PTS_VIDEO ); */ - this->video_fifo->put (this->video_fifo, buf); + this->video_fifo->put (this->video_fifo, buf); lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); - + return this->packet_len + result; } @@ -913,15 +911,15 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el /* this is probably wrong: if( !preview_mode ) check_newpts( this, this->pts, PTS_VIDEO ); - */ - this->video_fifo->put (this->video_fifo, buf); + */ + this->video_fifo->put (this->video_fifo, buf); lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); - + return this->packet_len + result; } if ((p[0]&0xF0) == 0x80) { - + track = p[0] & 0x0F; /* hack : ac3 track */ buf->decoder_info[1] = p[1]; /* Number of frame headers */ buf->decoder_info[2] = p[2] << 8 | p[3]; /* First access unit pointer */ @@ -945,7 +943,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el buf->free_buffer(buf); } return this->packet_len + result; - + } else if ((p[0]&0xf0) == 0xa0) { int pcm_offset; @@ -985,7 +983,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el switch ((p[5]>>6) & 3) { case 3: /* illegal, use 16-bits? */ default: - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "illegal lpcm sample format (%d), assume 16-bit samples\n", (p[5]>>6) & 3 ); case 0: bits_per_sample = 16; break; @@ -998,7 +996,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el buf->decoder_flags |= BUF_FLAG_SPECIAL; buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG; buf->decoder_info[2] = p[5]; - + pcm_offset = 7; buf->content = p+pcm_offset; @@ -1022,7 +1020,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el int size; /* - * A52/AC3 streams in some DVB-S recordings made with VDR. + * A52/AC3 streams in some DVB-S recordings made with VDR. * It is broadcast by a german tv-station called PRO7. * PRO7 uses dolby 5.1 (A52 5.1) in some of the movies they broadcast, * (and they would switch it to stereo-sound(A52 2.0) during commercials.) @@ -1075,18 +1073,18 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el lprintf ("A52 PACK put on fifo\n"); } else { buf->free_buffer(buf); - } + } } return this->packet_len + result; } - + /* Some new streams have been encountered. 1) DVD+RW disc recorded with a Philips DVD recorder: - new unknown sub-stream id of 0xff */ - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("demux_mpeg_pes:Unrecognised private stream 1 0x%02x. Please report this to xine developers.\n"), p[0]); buf->free_buffer(buf); return this->packet_len + result; @@ -1168,14 +1166,14 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen if (this->mpeg12_h264_detected > 2) { int nal_type_code = -1; if (payload_size >= 4 && p[2] == 0x01 && p[1] == 0x00 && p[0] == 0x00) - nal_type_code = p[3] & 0x1f; + nal_type_code = p[3] & 0x1f; if (nal_type_code == 9) { /* access unit delimiter */ buf_element_t *b = this->video_fifo->buffer_pool_alloc (this->video_fifo); b->content = b->mem; b->size = 0; b->pts = 0; b->type = buf_type; - b->decoder_flags = BUF_FLAG_FRAME_END; + b->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0); this->video_fifo->put (this->video_fifo, b); } } @@ -1189,7 +1187,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen if (this->mpeg12_h264_detected & 1) { uint8_t *t = buf->content + buf->size; if (buf->size >=4 && t[-1] == 10 && t[-2] == 0x01 && t[-3] == 0x00 && t[-4] == 0x00) /* end of sequence */ - buf->decoder_flags = BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0); } } else { buf->size = buf->max_size - result; @@ -1227,7 +1225,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen if ((this->mpeg12_h264_detected & 1) && todo_length <= 0) { uint8_t *t = buf->content + buf->size; if (buf->size >= 4 && t[-1] == 10 && t[-2] == 0x01 && t[-3] == 0x00 && t[-4] == 0x00) /* end of sequence */ - buf->decoder_flags = BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0); } this->video_fifo->put (this->video_fifo, buf); @@ -1277,10 +1275,10 @@ static int demux_mpeg_pes_send_chunk (demux_plugin_t *this_gen) { } #ifdef ESTIMATE_RATE_FIXED -/*! - Estimate bitrate by looking inside the MPEG file for presentation - time stamps (PTS) and computing how far apart these are - in bytes and in time. +/*! + Estimate bitrate by looking inside the MPEG file for presentation + time stamps (PTS) and computing how far apart these are + in bytes and in time. On failure return 0. @@ -1310,23 +1308,23 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { int rate=0; /* The return rate value */ int stream_id; - /* We can't estimate by sampling if we don't thave the ability to + /* We can't estimate by sampling if we don't thave the ability to randomly access the and more importantly reset after accessessing. */ if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE)) return 0; mpeg_length= this->input->get_length (this->input); - step = TRUNC((mpeg_length/MAX_SAMPLES), 2048); + step = TRUNC((mpeg_length/MAX_SAMPLES), 2048); if (step <= 0) step = 2048; /* avoid endless loop for tiny files */ pos = step; /* At this point "pos", and "step" are a multiple of blocksize and they should continue to be so throughout. */ - + this->input->seek (this->input, pos, SEEK_SET); - while ( (buf = this->input->read_block (this->input, this->video_fifo, 2048)) + while ( (buf = this->input->read_block (this->input, this->video_fifo, 2048)) && count < MAX_SAMPLES && reads++ < MAX_READS ) { p = buf->content; /* len = this->mnBlocksize; */ @@ -1335,9 +1333,9 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { is_mpeg1 = (p[4] & 0x40) == 0; - if (is_mpeg1) + if (is_mpeg1) p += 12; - else + else p += 14 + (p[0xD] & 0x07); } @@ -1347,14 +1345,14 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { /* we should now have a PES packet here */ if (p[0] || p[1] || (p[2] != 1)) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_mpeg_pes: error %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]); buf->free_buffer (buf); return rate; } stream_id = p[3]; - pts = 0; + pts = 0; if ((stream_id < 0xbc) || ((stream_id & 0xf0) != 0xe0)) { pos += (off_t) 2048; @@ -1383,18 +1381,18 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { pts |= (p[ 2] & 0xFE) << 14 ; pts |= p[ 3] << 7 ; pts |= (p[ 4] & 0xFE) >> 1 ; - } + } } } else { /* mpeg 2 */ - + if (p[7] & 0x80) { /* pts avail */ - + pts = (int64_t)(p[ 9] & 0x0E) << 29 ; pts |= p[10] << 22 ; pts |= (p[11] & 0xFE) << 14 ; pts |= p[12] << 7 ; pts |= (p[13] & 0xFE) >> 1 ; - + } else pts = 0; } @@ -1404,16 +1402,16 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { if ( (pos>last_pos) && (pts>last_pts) ) { int cur_rate; - + cur_rate = ((pos - last_pos)*90000) / ((pts - last_pts) * 50); - + rate = (count * rate + cur_rate) / (count+1); count ++; - + /* - printf ("demux_mpeg_pes: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n", - stream_id, pos, pts, cur_rate, rate); + printf ("demux_mpeg_pes: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n", + stream_id, pos, pts, cur_rate, rate); */ } @@ -1433,14 +1431,14 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { lprintf("est_rate=%d\n",rate); return rate; - + } #endif /*ESTIMATE_RATE_FIXED*/ static void demux_mpeg_pes_dispose (demux_plugin_t *this_gen) { demux_mpeg_pes_t *this = (demux_mpeg_pes_t *) this_gen; - + free (this->scratch_base); free (this); } @@ -1458,35 +1456,35 @@ static void demux_mpeg_pes_send_headers (demux_plugin_t *this_gen) { this->video_fifo = this->stream->video_fifo; this->audio_fifo = this->stream->audio_fifo; - /* + /* * send start buffer */ - + _x_demux_control_start(this->stream); - + #ifdef USE_ILL_ADVISED_ESTIMATE_RATE_INITIALLY - if (!this->rate) + if (!this->rate) this->rate = demux_mpeg_pes_estimate_rate (this); -#else +#else /* Set to Use rate given in by stream initially. */ - this->rate = 0; + this->rate = 0; #endif - + if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { - + int num_buffers = NUM_PREVIEW_BUFFERS; - + this->input->seek (this->input, 0, SEEK_SET); - + this->status = DEMUX_OK ; while ( (num_buffers>0) && (this->status == DEMUX_OK) ) { - + demux_mpeg_pes_parse_pack(this, 1); num_buffers --; } - } + } else if((this->input->get_capabilities(this->input) & INPUT_CAP_PREVIEW) != 0) { - + this->preview_size = this->input->get_optional_data(this->input, &this->preview_data, INPUT_OPTIONAL_DATA_PREVIEW); this->preview_done = 0; @@ -1514,14 +1512,14 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen, this->input->get_length (this->input) ); if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) { - + if (start_pos) { start_pos /= (off_t) 2048; start_pos *= (off_t) 2048; - + this->input->seek (this->input, start_pos, SEEK_SET); } else if (start_time) { - + if (this->last_cell_time) { start_pos = start_time - (this->last_cell_time + this->last_begin_time)/1000; start_pos *= this->rate; @@ -1534,19 +1532,19 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen, } start_pos /= (off_t) 2048; start_pos *= (off_t) 2048; - + this->input->seek (this->input, start_pos, SEEK_SET); } else this->input->seek (this->input, 0, SEEK_SET); } - + /* * now start demuxing */ this->last_cell_time = 0; this->send_newpts = 1; if( !playing ) { - + this->buf_flag_seek = 0; this->nav_last_end_pts = this->nav_last_start_pts = 0; this->status = DEMUX_OK ; @@ -1559,7 +1557,7 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen, this->mpeg12_h264_detected = 0; _x_demux_flush_engine(this->stream); } - + return this->status; } @@ -1577,7 +1575,7 @@ static void demux_mpeg_pes_accept_input (demux_mpeg_pes_t *this, lprintf ("mrl %s is new\n", this->cur_mrl); - } + } else { lprintf ("mrl %s is known, bitrate: %d\n", this->cur_mrl, this->rate * 50 * 8); @@ -1591,7 +1589,7 @@ static int demux_mpeg_pes_get_stream_length (demux_plugin_t *this_gen) { * find input plugin */ - if (this->rate) + if (this->rate) return (int)((int64_t) 1000 * this->input->get_length (this->input) / (this->rate * 50)); else @@ -1613,10 +1611,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str input_plugin_t *input = (input_plugin_t *) input_gen; demux_mpeg_pes_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_pes_t)); + this = calloc(1, sizeof(demux_mpeg_pes_t)); this->stream = stream; this->input = input; - + this->demux_plugin.send_headers = demux_mpeg_pes_send_headers; this->demux_plugin.send_chunk = demux_mpeg_pes_send_chunk; this->demux_plugin.seek = demux_mpeg_pes_seek; @@ -1639,9 +1637,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str lprintf ("open_plugin:detection_method=%d\n", stream->content_detection_method); - + switch (stream->content_detection_method) { - + case METHOD_BY_CONTENT: { /* use demux_mpeg_block for block devices */ @@ -1688,7 +1686,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) { input->seek(input, 0, SEEK_SET); - if (input->read(input, (char *)this->scratch, 6)) { + if (input->read(input, (char *)this->scratch, 6) == 6) { lprintf("open_plugin:read worked\n"); if (this->scratch[0] || this->scratch[1] @@ -1786,7 +1784,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_mpeg_pes_class_t *this; - this = xine_xmalloc (sizeof (demux_mpeg_pes_class_t)); + this = calloc(1, sizeof(demux_mpeg_pes_class_t)); this->config = xine->config; this->xine = xine; @@ -1808,7 +1806,7 @@ static const demuxer_info_t demux_info_mpeg_pes = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "mpeg_pes", XINE_VERSION_CODE, &demux_info_mpeg_pes, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 17916f837..6205f9a08 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2007 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -33,7 +33,7 @@ #include <string.h> #include <stdlib.h> -#define LOG_MODULE "demux_mpeg_audio" +#define LOG_MODULE "demux_mpgaudio" #define LOG_VERBOSE /* #define LOG @@ -51,8 +51,8 @@ * the second mp3 frame is sent to the decoder */ #define NUM_PREVIEW_BUFFERS 2 +#define NUM_VALID_FRAMES 3 -#define WRAP_THRESHOLD 120000 #define FOURCC_TAG BE_FOURCC #define RIFF_CHECK_BYTES 1024 @@ -79,16 +79,16 @@ /* mp3 frame struct */ typedef struct { /* header */ - double duration; - uint32_t size; /* in bytes */ + double duration; /* in milliseconds */ + uint32_t size; /* in bytes; including padding */ uint32_t bitrate; /* in bit per second */ uint16_t freq; /* in Hz */ - uint8_t layer; - uint8_t version_idx:2; /* 0: mpeg1, 1: mpeg2, 2: mpeg2.5 */ uint8_t lsf_bit:1; uint8_t channel_mode:3; + uint8_t padding:3; /* in bytes */ + uint8_t is_free_bitrate:1; } mpg_audio_frame_t; /* Xing Vbr Header struct */ @@ -98,7 +98,7 @@ typedef struct { uint32_t stream_size; uint8_t toc[XING_TOC_LENGTH]; uint32_t vbr_scale; - + /* Lame extension */ uint16_t start_delay; uint16_t end_delay; @@ -131,7 +131,13 @@ typedef struct { int br; /* bitrate in bits/second */ uint32_t blocksize; + /* current mp3 frame */ mpg_audio_frame_t cur_frame; + + /* next mp3 frame, used when the frame size cannot be computed from the + * current frame header */ + mpg_audio_frame_t next_frame; + double cur_time; /* in milliseconds */ off_t mpg_frame_start; /* offset */ @@ -141,7 +147,15 @@ typedef struct { int check_vbr_header; xing_header_t *xing_header; vbri_header_t *vbri_header; - + + int found_next_frame:1; + int free_bitrate_count; + off_t free_bitrate_size; /* use this size if 3 free bitrate frames are encountered */ + uint8_t next_header[4]; + int mpg_version; + int mpg_layer; + int valid_frames; + } demux_mpgaudio_t ; /* demuxer class struct */ @@ -212,14 +226,14 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con const uint32_t head = _X_BE_32(buf); const uint16_t frame_sync = head >> 21; - lprintf("header: %08X\n", head); if (frame_sync != 0x7ff) { - lprintf("invalid frame sync\n"); + lprintf("invalid frame sync %08X\n", head); return 0; } + lprintf("header: %08X\n", head); frame_header.mpeg25_bit = (head >> 20) & 0x1; - frame->lsf_bit = (head >> 19) & 0x1; + frame->lsf_bit = (head >> 19) & 0x1; if (!frame_header.mpeg25_bit) { if (frame->lsf_bit) { lprintf("reserved mpeg25 lsf combination\n"); @@ -240,14 +254,14 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con } frame_header.bitrate_idx = (head >> 12) & 0xf; - if ((frame_header.bitrate_idx == 0) || (frame_header.bitrate_idx == 15)) { - lprintf("invalid bitrate index\n"); + if (frame_header.bitrate_idx == 15) { + lprintf("invalid bitrate index: %d\n", frame_header.bitrate_idx); return 0; } frame_header.freq_idx = (head >> 10) & 0x3; if (frame_header.freq_idx == 3) { - lprintf("invalid frequence index\n"); + lprintf("invalid frequence index: %d\n", frame_header.freq_idx); return 0; } @@ -275,24 +289,32 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con return 0; } #endif - + { const uint16_t samples = mp3_samples[frame->version_idx][frame->layer - 1]; frame->bitrate = mp3_bitrates[frame->version_idx][frame->layer - 1][frame_header.bitrate_idx] * 1000; frame->freq = mp3_freqs[frame->version_idx][frame_header.freq_idx]; - - frame->size = samples * (frame->bitrate / 8); - frame->size /= frame->freq; - /* Padding: only if padding_bit is set; 4 bytes for Layer 1 and 1 byte for others */ - frame->size += ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 ); - frame->duration = 1000.0f * (double)samples / (double)frame->freq; + frame->padding = ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 ); + frame->channel_mode = frame_header.channel_mode; + + if (frame->bitrate > 0) { + frame->size = samples * (frame->bitrate / 8); + frame->size /= frame->freq; + /* Padding: only if padding_bit is set; 4 bytes for Layer 1 and 1 byte for others */ + frame->size += frame->padding; + } else { + /* Free bitrate frame, the size of the frame cannot be computed from the header. */ + frame->is_free_bitrate = 1; + frame->size = 0; + } } - lprintf("mpeg %d, layer %d\n", frame->version_idx + 1, frame->layer); - lprintf("bitrate: %d bps, samplerate: %d Hz\n", frame->bitrate, frame->freq); + lprintf("mpeg %d, layer %d, channel_mode: %d\n", frame->version_idx + 1, + frame->layer, frame->channel_mode); + lprintf("bitrate: %d bps, output freq: %d Hz\n", frame->bitrate, frame->freq); lprintf("length: %d bytes, %f ms\n", frame->size, frame->duration); - lprintf("padding: %d bytes\n", ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 )); + lprintf("padding: %d bytes\n", frame->padding); return 1; } @@ -300,8 +322,8 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con * Parse a Xing header * return the Xing header or NULL on error */ -static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, - uint8_t *buf, int bufsize) { +static xing_header_t *XINE_MALLOC parse_xing_header(mpg_audio_frame_t *frame, + uint8_t *buf, int bufsize) { uint8_t *ptr = buf; xing_header_t *xing = NULL; @@ -317,21 +339,21 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, else ptr += (9 + 4); } - + if (ptr >= (buf + bufsize - 4)) goto exit_error; lprintf("checking %08X\n", *ptr); - + if (_X_BE_32(ptr) == XING_TAG) { int has_frames_flag = 0; int has_bytes_flag = 0; - - xing = xine_xmalloc (sizeof (xing_header_t)); + + xing = calloc(1, sizeof(xing_header_t)); if (!xing) goto exit_error; - - lprintf("Xing header found\n"); + + lprintf("found Xing header\n"); ptr += 4; - + if (ptr >= (buf + bufsize - 4)) goto exit_error; xing->flags = _X_BE_32(ptr); ptr += 4; @@ -347,7 +369,7 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, lprintf("stream size: %d\n", xing->stream_size); has_bytes_flag = 1; } - + /* check if it's a useful Xing header */ if (!has_frames_flag || !has_bytes_flag) { lprintf("Stupid Xing tag, cannot do anything with it !\n"); @@ -405,7 +427,7 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, lprintf("Xing header not found\n"); } return xing; - + exit_error: lprintf("Xing header parse error\n"); free(xing); @@ -416,25 +438,25 @@ exit_error: * Parse a Vbri header * return the Vbri header or NULL on error */ -static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame, - uint8_t *buf, int bufsize) { +static vbri_header_t *XINE_MALLOC parse_vbri_header(mpg_audio_frame_t *frame, + uint8_t *buf, int bufsize) { int i; uint8_t *ptr = buf; vbri_header_t *vbri; - vbri = xine_xmalloc (sizeof (vbri_header_t)); + vbri = calloc(1, sizeof(vbri_header_t)); if (!vbri) return NULL; ptr += (32 + 4); - + if ((ptr + 4) >= (buf + bufsize)) return 0; lprintf("Checking %08X\n", *ptr); if (_X_BE_32(ptr) == VBRI_TAG) { - lprintf("Vbri header found\n"); + lprintf("found Vbri header\n"); ptr += 4; - + if ((ptr + 22) >= (buf + bufsize)) return 0; vbri->version = _X_BE_16(ptr); ptr += 2; vbri->delai = _X_BE_16(ptr); ptr += 2; @@ -456,7 +478,7 @@ static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame, lprintf("entry_frames: %d\n", vbri->entry_frames); if ((ptr + (vbri->toc_entries + 1) * vbri->entry_size) >= (buf + bufsize)) return 0; - vbri->toc = xine_xmalloc (sizeof(int) * (vbri->toc_entries + 1)); + vbri->toc = calloc (vbri->toc_entries + 1, sizeof (int)); if (!vbri->toc) { free (vbri); return NULL; @@ -496,6 +518,7 @@ static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame, } } + /* * Parse a mp3 frame paylod * return 1 on success, 0 on error @@ -506,43 +529,97 @@ static int parse_frame_payload(demux_mpgaudio_t *this, buf_element_t *buf; off_t frame_pos, len; uint64_t pts = 0; + int payload_size = 0; frame_pos = this->input->get_current_pos(this->input) - 4; - lprintf("frame_pos = %"PRId64"\n", frame_pos); + lprintf("frame_pos = %"PRId64", header: %08X\n", frame_pos, _X_BE_32(frame_header)); buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); if (this->cur_frame.size > buf->max_size) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: frame size is greater than fifo buffer size\n"); + LOG_MODULE ": frame size is greater than fifo buffer size\n"); buf->free_buffer(buf); return 0; } - - /* the decoder needs the frame header */ - memcpy(buf->mem, frame_header, 4); - len = this->input->read(this->input, buf->mem + 4, this->cur_frame.size - 4); - if (len != (this->cur_frame.size - 4)) { - buf->free_buffer(buf); - return 0; + memcpy(buf->content, frame_header, 4); + + /* compute the payload size */ + if (this->cur_frame.size > 0) { + payload_size = this->cur_frame.size - 4; + this->free_bitrate_count = 0; + } else if (this->free_bitrate_count >= NUM_VALID_FRAMES) { + payload_size = this->free_bitrate_size + this->cur_frame.padding - 4; + this->cur_frame.size = payload_size + 4; + } else { + this->free_bitrate_count++; + payload_size = 0; + } + + /* Read the payload data. */ + if (payload_size > 0) { + off_t len; + + /* If we know the payload size, it's easy */ + this->found_next_frame = 0; + len = this->input->read(this->input, buf->content + 4, payload_size); + if (len != payload_size) { + buf->free_buffer(buf); + return 0; + } + } else { + /* Search for the beginning of the next frame and deduce the size of the + * current frame from the position of the next one. */ + int payload_size = 0; + int max_size = buf->max_size - 4; + + while (payload_size < max_size) { + len = this->input->read(this->input, &buf->content[4 + payload_size], 1); + if (len != 1) { + lprintf("EOF\n"); + buf->free_buffer(buf); + return 0; + } + payload_size += len; + + if (parse_frame_header(&this->next_frame, &buf->content[payload_size])) { + lprintf("found next frame header\n"); + + if (this->free_bitrate_size == 0) { + this->free_bitrate_size = payload_size - this->cur_frame.padding; + } + + /* don't read the frame header twice */ + this->found_next_frame = 1; + memcpy(&this->next_header[0], &buf->content[payload_size], 4); + payload_size -= 4; + break; + } + } + this->cur_frame.size = payload_size + 4; + this->cur_frame.bitrate = 8000 * this->cur_frame.size / this->cur_frame.duration; + lprintf("free bitrate: bitrate: %d, frame size: %d\n", this->br, this->cur_frame.size); } if (this->check_vbr_header) { this->check_vbr_header = 0; this->mpg_frame_start = frame_pos; - this->xing_header = parse_xing_header(&this->cur_frame, buf->mem, this->cur_frame.size); + this->xing_header = parse_xing_header(&this->cur_frame, buf->content, this->cur_frame.size); if (this->xing_header) { buf->free_buffer(buf); + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": found Xing header at offset %"PRId64"\n", frame_pos); return 1; } - this->vbri_header = parse_vbri_header(&this->cur_frame, buf->mem, this->cur_frame.size); + this->vbri_header = parse_vbri_header(&this->cur_frame, buf->content, this->cur_frame.size); if (this->vbri_header) { buf->free_buffer(buf); + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": found Vbri header at offset %"PRId64"\n", frame_pos); return 1; } } - pts = (int64_t)(this->cur_time * 90.0f); @@ -551,8 +628,7 @@ static int parse_frame_payload(demux_mpgaudio_t *this, buf->extra_info->input_time = this->cur_time; buf->pts = pts; - buf->size = len + 4; - buf->content = buf->mem; + buf->size = this->cur_frame.size; buf->type = BUF_AUDIO_MPEG; buf->decoder_info[0] = 1; buf->decoder_flags = decoder_flags | BUF_FLAG_FRAME_END; @@ -572,8 +648,8 @@ static int parse_frame_payload(demux_mpgaudio_t *this, } } + lprintf("send buffer: size=%d, pts=%"PRId64"\n", buf->size, pts); this->audio_fifo->put(this->audio_fifo, buf); - lprintf("send buffer: pts=%"PRId64"\n", pts); this->cur_time += this->cur_frame.duration; return 1; } @@ -583,11 +659,12 @@ static int parse_frame_payload(demux_mpgaudio_t *this, * 32-bit MP3 frame header. * return 1 if found, 0 if not found */ -static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen) +static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen, int *version, int *layer) { int offset; mpg_audio_frame_t frame; + *version = *layer = 0; if (buf == NULL) return 0; @@ -596,20 +673,21 @@ static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen) if (parse_frame_header(&frame, buf + offset)) { size_t size = frame.size; - /* Since one frame is available, is there another frame - * just to be sure this is more likely to be a real MP3 - * buffer? */ - offset += size; - - if (offset + 4 >= buflen) { - return 0; - } + if (size > 0) { + /* Since one frame is available, is there another frame + * just to be sure this is more likely to be a real MP3 + * buffer? */ + if (offset + size + 4 >= buflen) { + return 0; + } - if (parse_frame_header(&frame, buf + offset)) { - lprintf("mpeg audio frame detected\n"); - return 1; + if (parse_frame_header(&frame, buf + offset + size)) { + *version = frame.version_idx + 1; + *layer = frame.layer; + lprintf("frame detected, mpeg %d layer %d\n", *version, *layer); + return 1; + } } - break; } } return 0; @@ -621,7 +699,7 @@ static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen) static int read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) { off_t len; int i; - + for (i = 0; i < (4 - bytes); i++) { header_buf[i] = header_buf[i + bytes]; } @@ -637,40 +715,51 @@ static int read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int by * Parse next mp3 frame */ static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags, int send_header) { - uint8_t header_buf[4]; - int bytes = 4; - - for (;;) { - - if (read_frame_header(this, header_buf, bytes)) { - - if (parse_frame_header(&this->cur_frame, header_buf)) { - - /* send header buffer */ - if ( send_header ) { - buf_element_t *buf; - - buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); - - buf->type = BUF_AUDIO_MPEG; - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - - buf->decoder_info[0] = 0; - buf->decoder_info[1] = this->cur_frame.freq; - buf->decoder_info[2] = 0; /* bits_per_sample */ - - /* Only for channel_mode == 3 (mono) there is one channel, for any other case, there are 2 */ - buf->decoder_info[3] = ( this->cur_frame.channel_mode == 3 ) ? 1 : 2; - - buf->size = 0; /* No extra header data */ - - this->audio_fifo->put(this->audio_fifo, buf); + uint8_t buffer[4]; + uint8_t *header = buffer; + + if (this->found_next_frame) { + lprintf("skip header reading\n"); + header = this->next_header; + memcpy(&this->cur_frame, &this->next_frame, sizeof(mpg_audio_frame_t)); + } else { + int bytes = 4; + int loose_sync = 0; + + for (;;) { + if (!read_frame_header(this, header, bytes)) + return 0; + if (parse_frame_header(&this->cur_frame, header)) { + lprintf("frame found\n"); + + /* additionnal checks */ + if ((this->mpg_version == (this->cur_frame.version_idx + 1)) && + (this->mpg_layer == this->cur_frame.layer)) { + this->valid_frames++; + break; + } else { + if (this->valid_frames >= NUM_VALID_FRAMES) { + lprintf("invalid frame. expected mpeg %d, layer %d\n", this->mpg_version, this->mpg_layer); + } else { + this->mpg_version = this->cur_frame.version_idx + 1; + this->mpg_layer = this->cur_frame.layer; + this->valid_frames = 0; + break; + } } - - return parse_frame_payload(this, header_buf, decoder_flags); - - } else if ( id3v2_istag(header_buf) ) { - if (!id3v2_parse_tag(this->input, this->stream, header_buf)) { + } + + if (!loose_sync) { + off_t frame_pos = this->input->get_current_pos(this->input) - 4; + loose_sync = 1; + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE ": loose mp3 sync at offset %"PRId64"\n", frame_pos); + } + /* the stream is broken, don't keep info about previous frames */ + this->free_bitrate_size = 0; + + if ( id3v2_istag(header) ) { + if (!id3v2_parse_tag(this->input, this->stream, header)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": ID3V2 tag parsing error\n"); bytes = 1; /* resync */ @@ -681,12 +770,31 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags, int s /* skip */ bytes = 1; } - - } else { - lprintf("read error\n"); - return 0; } } + + /* send header buffer */ + if ( send_header ) { + buf_element_t *buf; + + buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); + + buf->type = BUF_AUDIO_MPEG; + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; + + buf->decoder_info[0] = 0; + buf->decoder_info[1] = this->cur_frame.freq; + buf->decoder_info[2] = 0; /* bits_per_sample */ + + /* Only for channel_mode == 3 (mono) there is one channel, for any other case, there are 2 */ + buf->decoder_info[3] = ( this->cur_frame.channel_mode == 3 ) ? 1 : 2; + + buf->size = 0; /* No extra header data */ + + this->audio_fifo->put(this->audio_fifo, buf); + } + + return parse_frame_payload(this, header, decoder_flags); } static int demux_mpgaudio_send_chunk (demux_plugin_t *this_gen) { @@ -742,12 +850,13 @@ static int demux_mpgaudio_read_head(input_plugin_t *input, uint8_t *buf) { * mp3 stream detection * return 1 if detected, 0 otherwise */ -static int detect_mpgaudio_file(input_plugin_t *input) { - mpg_audio_frame_t frame; +static int detect_mpgaudio_file(input_plugin_t *input, + int *version, int *layer) { uint8_t buf[MAX_PREVIEW_SIZE]; int preview_len; uint32_t head; + *version = *layer = 0; preview_len = demux_mpgaudio_read_head(input, buf); if (preview_len < 4) return 0; @@ -774,15 +883,15 @@ static int detect_mpgaudio_file(input_plugin_t *input) { lprintf("cannot read mp3 frame header\n"); return 0; } - if (!parse_frame_header(&frame, &buf[10 + tag_size])) { - lprintf ("invalid mp3 frame header\n"); + if (!sniff_buffer_looks_like_mp3(&buf[10 + tag_size], preview_len - 10 - tag_size, version, layer)) { + lprintf ("sniff_buffer_looks_like_mp3 failed\n"); return 0; } else { lprintf ("a valid mp3 frame follows the id3v2 tag\n"); } } else if (head == MPEG_MARKER) { return 0; - } else if (!sniff_buffer_looks_like_mp3(buf, preview_len)) { + } else if (!sniff_buffer_looks_like_mp3(buf, preview_len, version, layer)) { lprintf ("sniff_buffer_looks_like_mp3 failed\n"); return 0; } @@ -821,11 +930,12 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) { */ this->check_vbr_header = 1; for (i = 0; i < NUM_PREVIEW_BUFFERS; i++) { + lprintf("preview buffer number %d / %d\n", i + 1, NUM_PREVIEW_BUFFERS); if (!demux_mpgaudio_next (this, BUF_FLAG_PREVIEW, i == 0)) { break; } } - + if (this->xing_header) { xing_header_t *xing = this->xing_header; @@ -836,7 +946,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) { if (this->stream_length) { this->br = ((uint64_t)xing->stream_size * 8 * 1000) / this->stream_length; } - + } else if (this->vbri_header) { vbri_header_t *vbri = this->vbri_header; @@ -848,7 +958,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) { this->br = ((uint64_t)vbri->stream_size * 8 * 1000) / this->stream_length; } } - + /* Set to default if Vbr header is incomplete or not present */ if (!this->br) { /* assume CBR */ @@ -879,7 +989,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) { { char scratch_buf[256]; char *mpeg_ver[3] = {"1", "2", "2.5"}; - + snprintf(scratch_buf, 256, "MPEG %s Layer %1d%s", mpeg_ver[this->cur_frame.version_idx], this->cur_frame.layer, (this->xing_header)? " VBR" : " CBR" ); @@ -1007,7 +1117,8 @@ static int demux_mpgaudio_seek (demux_plugin_t *this_gen, /* assume seeking is always perfect... */ this->cur_time = start_time; this->input->seek (this->input, seek_pos, SEEK_SET); - + this->found_next_frame = 0; + if (playing) { _x_demux_flush_engine(this->stream); } @@ -1039,21 +1150,23 @@ static uint32_t demux_mpgaudio_get_capabilities(demux_plugin_t *this_gen) { } static int demux_mpgaudio_get_optional_data(demux_plugin_t *this_gen, - void *data, int data_type) { + void *data, int data_type) { return DEMUX_OPTIONAL_UNSUPPORTED; -} +} static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { demux_mpgaudio_t *this; + int version = 0; + int layer = 0; lprintf("trying to open %s...\n", input->get_mrl(input)); switch (stream->content_detection_method) { case METHOD_BY_CONTENT: { - if (!detect_mpgaudio_file(input)) + if (!detect_mpgaudio_file(input, &version, &layer)) return NULL; } break; @@ -1061,23 +1174,23 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str case METHOD_BY_EXTENSION: { const char *const mrl = input->get_mrl(input); const char *const extensions = class_gen->get_extensions (class_gen); - + lprintf ("stage by extension %s\n", mrl); - + if (!_x_demux_check_extension (mrl, extensions)) return NULL; - + } break; case METHOD_EXPLICIT: break; - + default: return NULL; } - - this = xine_xmalloc (sizeof (demux_mpgaudio_t)); + + this = calloc(1, sizeof(demux_mpgaudio_t)); this->demux_plugin.send_headers = demux_mpgaudio_send_headers; this->demux_plugin.send_chunk = demux_mpgaudio_send_chunk; @@ -1088,12 +1201,17 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->demux_plugin.get_capabilities = demux_mpgaudio_get_capabilities; this->demux_plugin.get_optional_data = demux_mpgaudio_get_optional_data; this->demux_plugin.demux_class = class_gen; - - this->input = input; - this->audio_fifo = stream->audio_fifo; - this->status = DEMUX_FINISHED; - this->stream = stream; - + + this->input = input; + this->audio_fifo = stream->audio_fifo; + this->status = DEMUX_FINISHED; + this->stream = stream; + + this->mpg_version = version; + this->mpg_layer = layer; + if (version || layer) { + this->valid_frames = NUM_VALID_FRAMES; + } return &this->demux_plugin; } @@ -1111,7 +1229,7 @@ static const char *get_identifier (demux_class_t *this_gen) { static const char *get_extensions (demux_class_t *this_gen) { demux_mpgaudio_class_t *this = (demux_mpgaudio_class_t *) this_gen; - + if( _x_decoder_available(this->xine, BUF_AUDIO_MPEG) ) return "mp3 mp2 mpa mpega"; else @@ -1144,10 +1262,10 @@ static void class_dispose (demux_class_t *this_gen) { } void *demux_mpgaudio_init_class (xine_t *xine, void *data) { - + demux_mpgaudio_class_t *this; - - this = xine_xmalloc (sizeof (demux_mpgaudio_class_t)); + + this = calloc(1, sizeof(demux_mpgaudio_class_t)); this->xine = xine; this->demux_class.open_plugin = open_plugin; diff --git a/src/demuxers/demux_nsf.c b/src/demuxers/demux_nsf.c index 81f42044f..40aeae9da 100644 --- a/src/demuxers/demux_nsf.c +++ b/src/demuxers/demux_nsf.c @@ -22,7 +22,7 @@ * NSF File "Demuxer" by Mike Melanson (melanson@pcisys.net) * This is really just a loader for NES Music File Format (extension NSF) * which loads an entire NSF file and passes it over to the NSF audio - * decoder. + * decoder. * * After the file is sent over, the demuxer controls the playback by * sending empty buffers with incrementing pts values. @@ -97,18 +97,14 @@ static int open_nsf_file(demux_nsf_t *this) { return 0; /* check for the signature */ - if ((header[0] != 'N') || - (header[1] != 'E') || - (header[2] != 'S') || - (header[3] != 'M') || - (header[4] != 0x1A)) + if (memcmp(header, "NESM\x1A", 5) != 0) return 0; this->total_songs = header[6]; this->current_song = header[7]; - this->title = strdup(&header[0x0E]); - this->artist = strdup(&header[0x2E]); - this->copyright = strdup(&header[0x4E]); + this->title = strndup((char*)&header[0x0E], 0x20); + this->artist = strndup((char*)&header[0x2E], 0x20); + this->copyright = strndup((char*)&header[0x4E], 0x20); this->filesize = this->input->get_length(this->input); @@ -128,7 +124,7 @@ static int demux_nsf_send_chunk(demux_plugin_t *this_gen) { buf->type = BUF_AUDIO_NSF; bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { /* the file has been completely loaded, free the buffer and start * sending control buffers */ buf->free_buffer(buf); @@ -170,7 +166,7 @@ static int demux_nsf_send_chunk(demux_plugin_t *this_gen) { buf->decoder_info[1] = 0; buf->type = BUF_AUDIO_NSF; - if(this->total_songs) + if(this->total_songs) buf->extra_info->input_normpos = (this->current_song - 1) * 65535 / this->total_songs; buf->extra_info->input_time = this->current_pts / 90; buf->pts = this->current_pts; @@ -303,7 +299,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_nsf_t)); + this = calloc(1, sizeof(demux_nsf_t)); this->stream = stream; this->input = input; @@ -377,7 +373,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_nsf_init_plugin (xine_t *xine, void *data) { demux_nsf_class_t *this; - this = xine_xmalloc (sizeof (demux_nsf_class_t)); + this = calloc(1, sizeof(demux_nsf_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_nsv.c b/src/demuxers/demux_nsv.c index 44bb18c79..8017d3d3f 100644 --- a/src/demuxers/demux_nsv.c +++ b/src/demuxers/demux_nsv.c @@ -50,7 +50,6 @@ #define FOURCC_TAG BE_FOURCC #define NSVf_TAG FOURCC_TAG('N', 'S', 'V', 'f') #define NSVs_TAG FOURCC_TAG('N', 'S', 'V', 's') -#define NONE_TAG FOURCC_TAG('N', 'O', 'N', 'E') #define BEEF 0xEFBE @@ -107,17 +106,17 @@ static void nsv_parse_framerate(demux_nsv_t *this, uint8_t framerate) /* 29.97 fps */ this->frame_pts_inc = 3003; break; - + case 3: /* 23.976 fps */ this->frame_pts_inc = 3753; break; - + case 5: /* 14.98 fps */ this->frame_pts_inc = 6006; break; - + default: lprintf("unknown framerate: 0x%02X\n", this->fps); this->frame_pts_inc = 90000; @@ -125,7 +124,7 @@ static void nsv_parse_framerate(demux_nsv_t *this, uint8_t framerate) } } else this->frame_pts_inc = 90000 / this->fps; - + lprintf("frame_pts_inc=%d\n", this->frame_pts_inc); } @@ -139,7 +138,7 @@ static off_t nsv_read(demux_nsv_t *this, uint8_t *buffer, off_t len) { int ultravox_rest; int buffer_pos = 0; - + /* ultravox stuff */ while (len) { ultravox_rest = this->ultravox_size - this->ultravox_pos; @@ -195,7 +194,7 @@ static off_t nsv_seek(demux_nsv_t *this, off_t offset, int origin) { /* ultravox stuff */ if (origin == SEEK_CUR) { uint8_t buffer[1024]; - + while (offset) { if (offset > sizeof(buffer)) { if (nsv_read(this, buffer, sizeof(buffer)) != sizeof(buffer)) @@ -222,7 +221,7 @@ static int nsv_resync(demux_nsv_t *this) { for (i = 0; i < NSV_MAX_RESYNC; i++) { uint8_t byte; - + if (nsv_read(this, &byte, 1) != 1) return NSV_RESYNC_ERROR; @@ -256,17 +255,11 @@ static int open_nsv_file(demux_nsv_t *this) { return 0; /* check for a 'NSV' signature */ - if ((preview[0] != 'N') || - (preview[1] != 'S') || - (preview[2] != 'V')) - { - if ((preview[0] != 'Z') || - (preview[1] != 0) || - (preview[2] != '9')) - return 0; + if ( memcmp(preview, "Z\09", 3) == 0) { this->is_ultravox = preview[3]; this->ultravox_first = 1; - } + } else if ( memcmp(preview, "NSV", 3) != 0 ) + return 0; lprintf("NSV file detected, ultravox=%d\n", this->is_ultravox); @@ -274,11 +267,11 @@ static int open_nsv_file(demux_nsv_t *this) { while (!NSVs_found) { switch (nsv_resync(this)) { - + case NSV_RESYNC_NSVf: { uint32_t chunk_size; - + /* if there is a NSVs tag, load 24 more header bytes; load starting at * offset 4 in buffer to keep header data in line with document */ if (nsv_read(this, &preview[4], 24) != 24) @@ -287,41 +280,41 @@ static int open_nsv_file(demux_nsv_t *this) { lprintf("found NSVf chunk\n"); /* this->data_size = _X_LE_32(&preview[8]);*/ /*lprintf("data_size: %lld\n", this->data_size);*/ - + /* skip the rest of the data */ chunk_size = _X_LE_32(&preview[4]); nsv_seek(this, chunk_size - 28, SEEK_CUR); } break; - + case NSV_RESYNC_NSVs: - - /* fetch the remaining 15 header bytes of the first chunk to get the + + /* fetch the remaining 15 header bytes of the first chunk to get the * relevant information */ if (nsv_read(this, &preview[4], 15) != 15) return 0; - + this->video_fourcc = _X_ME_32(&preview[4]); - if (_X_BE_32(&preview[4]) == NONE_TAG) + if (_x_is_fourcc(&preview[4], "NONE")) this->video_type = 0; else this->video_type = _x_fourcc_to_buf_video(this->video_fourcc); - + this->audio_fourcc = _X_ME_32(&preview[8]); - if (_X_BE_32(&preview[8]) == NONE_TAG) + if (_x_is_fourcc(&preview[8], "NONE")) this->audio_type = 0; else this->audio_type = _x_formattag_to_buf_audio(this->audio_fourcc); - + this->bih.biSize = sizeof(this->bih); this->bih.biWidth = _X_LE_16(&preview[12]); this->bih.biHeight = _X_LE_16(&preview[14]); this->bih.biCompression = this->video_fourcc; this->video_pts = 0; - + /* may not be true, but set it for the time being */ this->frame_pts_inc = 3003; - + lprintf("video: %c%c%c%c, buffer type %08X, %dx%d\n", preview[4], preview[5], @@ -340,10 +333,10 @@ static int open_nsv_file(demux_nsv_t *this) { nsv_parse_framerate(this, preview[16]); NSVs_found = 1; break; - + case NSV_RESYNC_ERROR: return 0; - + } } @@ -465,27 +458,27 @@ static int demux_nsv_send_chunk(demux_plugin_t *this_gen) { current_file_pos = this->input->get_current_pos(this->input); lprintf("dispatching video & audio chunks...\n"); - + if (this->is_first_chunk) { chunk_type = NSV_RESYNC_BEEF; this->is_first_chunk = 0; } else { chunk_type = nsv_resync(this); } - + switch (chunk_type) { case NSV_RESYNC_NSVf: /* do nothing */ break; - + case NSV_RESYNC_NSVs: /* skip header */ if (nsv_read(this, buffer, 15) != 15) return 0; nsv_parse_framerate(this, buffer[12]); - + /* fall thru */ - + case NSV_RESYNC_BEEF: if (nsv_read(this, buffer, 5) != 5) { this->status = DEMUX_FINISHED; @@ -495,15 +488,15 @@ static int demux_nsv_send_chunk(demux_plugin_t *this_gen) { video_size >>= 4; video_size &= 0xFFFFF; audio_size = _X_LE_16(&buffer[3]); - + nsv_parse_payload(this, video_size, audio_size); break; - + case NSV_RESYNC_ERROR: this->status = DEMUX_FINISHED; break; } - + return this->status; } @@ -594,7 +587,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_nsv_t *this; - this = xine_xmalloc (sizeof (demux_nsv_t)); + this = calloc(1, sizeof(demux_nsv_t)); this->stream = stream; this->input = input; @@ -668,7 +661,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *demux_nsv_init_plugin (xine_t *xine, void *data) { demux_nsv_class_t *this; - this = xine_xmalloc (sizeof (demux_nsv_class_t)); + this = calloc(1, sizeof(demux_nsv_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 9ed39f12d..3fc5ec9e1 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -194,7 +194,7 @@ static int get_stream (demux_ogg_t *this, int serno) { static int new_stream_info (demux_ogg_t *this, const int cur_serno) { int stream_num; - this->si[this->num_streams] = (stream_info_t *)xine_xmalloc(sizeof(stream_info_t)); + this->si[this->num_streams] = (stream_info_t *)calloc(1, sizeof(stream_info_t)); ogg_stream_init(&this->si[this->num_streams]->oss, cur_serno); stream_num = this->num_streams; this->si[stream_num]->buf_types = 0; @@ -237,7 +237,7 @@ static int read_ogg_packet (demux_ogg_t *this) { while (ogg_sync_pageout(&this->oy,&this->og)!=1) { buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE); bytes = this->input->read(this->input, buffer, CHUNKSIZE); - if (bytes == 0) { + if (bytes <= 0) { if (total == 0) { lprintf("read_ogg_packet read nothing\n"); return 0; @@ -304,10 +304,10 @@ static void send_ogg_packet (demux_ogg_t *this, buf_element_t *buf; int done=0,todo=op->bytes; - int op_size = sizeof(ogg_packet); + const size_t op_size = sizeof(ogg_packet); while (done<todo) { - int offset=0; + size_t offset=0; buf = fifo->buffer_pool_alloc (fifo); buf->decoder_flags = decoder_flags; if (done==0) { @@ -329,7 +329,7 @@ static void send_ogg_packet (demux_ogg_t *this, buf->pts = pts; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = buf->pts / 90 ; buf->type = this->si[stream_num]->buf_types; @@ -498,7 +498,7 @@ static void read_chapter_comment (demux_ogg_t *this, ogg_packet *op) { lprintf("time: %d %d %d %d\n", hour, min,sec,msec); if (!this->chapter_info) { - this->chapter_info = (chapter_info_t *)xine_xmalloc(sizeof(chapter_info_t)); + this->chapter_info = (chapter_info_t *)calloc(1, sizeof(chapter_info_t)); this->chapter_info->current_chapter = -1; } this->chapter_info->max_chapter = chapter_no; @@ -531,34 +531,34 @@ static void update_chapter_display (demux_ogg_t *this, int stream_num, ogg_packe chapter--; if (chapter != this->chapter_info->current_chapter){ - xine_event_t uevent; - xine_ui_data_t data; - int title_len; - char *title; + xine_ui_data_t data = { + .str = { 0, }, + .str_len = 0 + }; + xine_event_t uevent = { + .type = XINE_EVENT_UI_SET_TITLE, + .stream = this->stream, + .data = &data, + .data_length = sizeof(data) + }; this->chapter_info->current_chapter = chapter; - if (chapter >= 0) { - char t_title[256]; + if (chapter >= 0) { if (this->title) { - snprintf(t_title, sizeof (t_title), "%s / %s", this->title, this->chapter_info->entries[chapter].name); + data.str_len = snprintf(data.str, sizeof(data.str), "%s / %s", this->title, this->chapter_info->entries[chapter].name); } else { - snprintf(t_title, sizeof (t_title), "%s", this->chapter_info->entries[chapter].name); + strncpy(data.str, this->chapter_info->entries[chapter].name, sizeof(data.str)-1); } - title = t_title; } else { - title = this->title; + strncpy(data.str, this->title, sizeof(data.str)); } - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, title); - lprintf("new TITLE: %s\n", title); - - uevent.type = XINE_EVENT_UI_SET_TITLE; - uevent.stream = this->stream; - uevent.data = &data; - uevent.data_length = sizeof(data); - title_len = strlen(title) + 1; - memcpy(data.str, title, title_len); - data.str_len = title_len; + if ( data.str_len == 0 ) + data.str_len = strlen(data.str); + + _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, data.str); + lprintf("new TITLE: %s\n", data.str); + xine_event_send(this->stream, &uevent); } } @@ -578,10 +578,10 @@ static void send_ogg_buf (demux_ogg_t *this, int normpos = 0; if( this->input->get_length (this->input) ) - normpos = (int)( (double) this->input->get_current_pos (this->input) * + normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); - + hdrlen = (*op->packet & PACKET_LEN_BITS01) >> 6; hdrlen |= (*op->packet & PACKET_LEN_BITS2) << 1; @@ -686,7 +686,7 @@ static void send_ogg_buf (demux_ogg_t *this, check_newpts( this, pts, PTS_VIDEO, decoder_flags ); } else pts = 0; - + llprintf(DEBUG_VIDEO_PACKETS, "videostream %d op-gpos %" PRId64 " hdr-gpos %" PRId64 " pts %" PRId64 " \n", stream_num, @@ -1020,7 +1020,7 @@ static void decode_dshow_header (demux_ogg_t *this, const int stream_num, ogg_pa this->si[stream_num]->headers = 0; /* header is sent below */ - if ( (_X_LE_32(&op->packet[96]) == 0x05589f80) && (op->bytes >= 184)) { + if ( _x_is_fourcc(&op->packet[96], "\x05\x58\x9f\x80") && (op->bytes >= 184)) { buf_element_t *buf; xine_bmiheader bih; @@ -1079,7 +1079,7 @@ static void decode_dshow_header (demux_ogg_t *this, const int stream_num, ogg_pa this->ignore_keyframes = 1; - } else if (_X_LE_32(&op->packet[96]) == 0x05589F81) { + } else if (_x_is_fourcc(&op->packet[96], "\x05\x58\x9f\x81")) { #if 0 /* FIXME: no test streams */ @@ -1194,27 +1194,27 @@ static void decode_theora_header (demux_ogg_t *this, const int stream_num, ogg_p static void decode_flac_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { xine_flac_metadata_header header; - xine_flac_streaminfo_block streaminfo; + xine_flac_streaminfo_block streaminfo = {}; buf_element_t *buf; xine_waveformatex wave; - /* Packet type */ - _x_assert(op->packet[0] == 0x7F); - - /* OggFLAC signature */ - _x_assert(op->packet[1] == 'F'); _x_assert(op->packet[2] == 'L'); - _x_assert(op->packet[3] == 'A'); _x_assert(op->packet[4] == 'C'); + static const uint8_t flac_signature_1[] = + { + /* Packet type */ + 0x7F, + /* OggFLAC signature */ + 'F', 'L', 'A', 'C', + /* Version: only 1.0 supported */ + 1, 0 + }; + static const uint8_t flac_signature_2[] = "fLaC"; - /* Version: supported only 1.0 */ - _x_assert(op->packet[5] == 1); _x_assert(op->packet[6] == 0); + _x_assert(memcmp(&op->packet[0], flac_signature_1, sizeof(flac_signature_1)) == 0); + _x_assert(memcmp(&op->packet[9], flac_signature_2, sizeof(flac_signature_2)) == 0); /* Header count */ this->si[stream_num]->headers = 0/*_X_BE_16(&op->packet[7]) +1*/; - /* fLaC signature */ - _x_assert(op->packet[9] == 'f'); _x_assert(op->packet[10] == 'L'); - _x_assert(op->packet[11] == 'a'); _x_assert(op->packet[12] == 'C'); - _x_parse_flac_metadata_header(&op->packet[13], &header); switch ( header.blocktype ) { @@ -1267,8 +1267,8 @@ static void decode_annodex_header (demux_ogg_t *this, const int stream_num, ogg_ static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { int64_t granule_rate_n, granule_rate_d; uint32_t secondary_headers; - char content_type[1024]; - int content_type_length; + const char *content_type = ""; + size_t content_type_length = 0; lprintf("AnxData stream detected\n"); @@ -1280,11 +1280,16 @@ static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_ lprintf("granule_rate %" PRId64 "/%" PRId64 ", %d secondary headers\n", granule_rate_n, granule_rate_d, secondary_headers); - /* read "Content-Tyoe" MIME header */ - sscanf(&op->packet[28], "Content-Type: %1023s\r\n", content_type); - content_type_length = strlen(content_type); + /* read "Content-Type" MIME header */ + const char *startline = &op->packet[28]; + const char *endline; + if ( strcmp(&op->packet[28], "Content-Type: ") == 0 && + (endline = strstr(startline, "\r\n")) ) { + content_type = startline + sizeof("Content-Type: "); + content_type_length = startline - endline; + } - lprintf("Content-Type: %s (length:%d)\n", content_type, content_type_length); + lprintf("Content-Type: %s (length:%td)\n", content_type, content_type_length); /* how many header packets in the AnxData stream? */ this->si[stream_num]->headers = secondary_headers + 1; @@ -1323,7 +1328,7 @@ static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_ } else { this->si[stream_num]->buf_types = BUF_CONTROL_NOP; } - + } static void decode_cmml_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) { @@ -1352,7 +1357,7 @@ static void send_header (demux_ogg_t *this) { this->ignore_keyframes = 0; while (!done) { - if (!read_ogg_packet(this)) { + if (!read_ogg_packet(this) || !this->og.header || !this->og.body) { return; } /* now we've got at least one new page */ @@ -1478,6 +1483,12 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) { return this->status; } + if (!this->og.header || !this->og.body) { + this->status = DEMUX_FINISHED; + lprintf ("EOF\n"); + return this->status; + } + /* now we've got one new page */ cur_serno = ogg_page_serialno (&this->og); @@ -1592,10 +1603,10 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) { if (ogg_page_eos(&this->og)) { int i; int finished_streams = 0; - + lprintf("end of stream, serialnumber %d\n", cur_serno); this->si[stream_num]->delivered_eos = 1; - + /* check if all logical streams are finished */ for (i = 0; i < this->num_streams; i++) { finished_streams += this->si[i]->delivered_eos; @@ -1617,12 +1628,12 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) { this->unhandled_video_streams = 0; this->num_spu_streams = 0; this->avg_bitrate = 1; - + /* try to read a chained stream */ this->send_newpts = 1; this->last_pts[0] = 0; this->last_pts[1] = 0; - + /* send control buffer to avoid buffer leak */ _x_demux_control_end(this->stream, 0); _x_demux_control_start(this->stream); @@ -1751,7 +1762,7 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, hasn` changed its length, otherwise no seek to "new" data is possible*/ lprintf ("seek to time %d called\n",start_time); - lprintf ("current time is %d\n",current_time); + lprintf ("current time is %d\n",current_time); if (current_time > start_time) { /*seek between beginning and current_pos*/ @@ -1771,7 +1782,7 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, } lprintf ("current_pos is %" PRId64 "\n",current_pos); - lprintf ("new_pos is %" PRId64 "\n",start_pos); + lprintf ("new_pos is %" PRId64 "\n",start_pos); } else { /*seek using avg_bitrate*/ @@ -1790,9 +1801,9 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, ogg_stream_reset(&this->si[i]->oss); } - /*some strange streams have no syncpoint flag set at the beginning*/ - if (start_pos == 0) - this->keyframe_needed = 0; + /*some strange streams have no syncpoint flag set at the beginning*/ + if (start_pos == 0) + this->keyframe_needed = 0; lprintf ("seek to %" PRId64 " called\n",start_pos); @@ -1803,7 +1814,7 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, /* fixme - this would be a nice position to do the following tasks 1. adjust an ogg videostream to a keyframe 2. compare the keyframe_pts with start_time. if the difference is to - high (e.g. larger than max keyframe_intervall, do a new seek or + high (e.g. larger than max keyframe_intervall, do a new seek or continue reading 3. adjust the audiostreams in such a way, that the difference is not to high. @@ -1811,12 +1822,12 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, In short words, do all the cleanups necessary to continue playback without further actions */ - + this->send_newpts = 1; this->status = DEMUX_OK; - + if( !playing ) { - + this->buf_flag_seek = 0; } else { @@ -1833,13 +1844,13 @@ static int demux_ogg_seek (demux_plugin_t *this_gen, _x_demux_flush_engine(this->stream); } - + return this->status; } static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; + demux_ogg_t *this = (demux_ogg_t *) this_gen; if (this->time_length==-1){ if (this->avg_bitrate) { @@ -1854,7 +1865,7 @@ static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) { } static uint32_t demux_ogg_get_capabilities(demux_plugin_t *this_gen) { - demux_ogg_t *this = (demux_ogg_t *) this_gen; + demux_ogg_t *this = (demux_ogg_t *) this_gen; int cap_chapter = 0; if (this->chapter_info) @@ -1884,8 +1895,8 @@ static int format_lang_string (demux_ogg_t * this, uint32_t buf_mask, uint32_t b static int demux_ogg_get_optional_data(demux_plugin_t *this_gen, void *data, int data_type) { - - demux_ogg_t *this = (demux_ogg_t *) this_gen; + + demux_ogg_t *this = (demux_ogg_t *) this_gen; char *str=(char *) data; int channel = *((int *)data); @@ -1924,11 +1935,7 @@ static int detect_ogg_content (int detection_method, demux_class_t *class_gen, if (_x_demux_read_header(input, buf, 4) != 4) return 0; - if ((buf[0] == 'O') && (buf[1] == 'g') && (buf[2] == 'g') && - (buf[3] == 'S')) - return 1; - else - return 0; + return _x_is_fourcc(buf, "OggS"); } case METHOD_BY_EXTENSION: { @@ -2014,7 +2021,7 @@ static int detect_anx_content (int detection_method, demux_class_t *class_gen, } static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen, - xine_stream_t *stream, + xine_stream_t *stream, input_plugin_t *input) { demux_ogg_t *this; @@ -2026,8 +2033,7 @@ static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen, * if we reach this point, the input has been accepted. */ - this = xine_xmalloc (sizeof (demux_ogg_t)); - memset (this, 0, sizeof(demux_ogg_t)); + this = calloc(1, sizeof(demux_ogg_t)); this->stream = stream; this->input = input; @@ -2044,13 +2050,13 @@ static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen, this->demux_plugin.get_capabilities = demux_ogg_get_capabilities; this->demux_plugin.get_optional_data = demux_ogg_get_optional_data; this->demux_plugin.demux_class = class_gen; - + this->status = DEMUX_FINISHED; #ifdef HAVE_THEORA theora_info_init (&this->t_info); theora_comment_init (&this->t_comment); -#endif +#endif this->chapter_info = 0; this->title = 0; @@ -2060,7 +2066,7 @@ static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen, } static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen, - xine_stream_t *stream, + xine_stream_t *stream, input_plugin_t *input) { demux_ogg_t *this; @@ -2072,8 +2078,7 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen, * if we reach this point, the input has been accepted. */ - this = xine_xmalloc (sizeof (demux_ogg_t)); - memset (this, 0, sizeof(demux_ogg_t)); + this = calloc(1, sizeof(demux_ogg_t)); this->stream = stream; this->input = input; @@ -2086,13 +2091,13 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen, this->demux_plugin.get_capabilities = demux_ogg_get_capabilities; this->demux_plugin.get_optional_data = demux_ogg_get_optional_data; this->demux_plugin.demux_class = class_gen; - + this->status = DEMUX_FINISHED; #ifdef HAVE_THEORA theora_info_init (&this->t_info); theora_comment_init (&this->t_comment); -#endif +#endif this->chapter_info = 0; this->title = 0; @@ -2108,7 +2113,7 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen, static const char *anx_get_description (demux_class_t *this_gen) { return "Annodex demux plugin"; } - + static const char *anx_get_identifier (demux_class_t *this_gen) { return "Annodex"; } @@ -2118,7 +2123,12 @@ static const char *anx_get_extensions (demux_class_t *this_gen) { } static const char *anx_get_mimetypes (demux_class_t *this_gen) { - return "application/x-annodex: ogg: Annodex media;"; + return "application/annodex: anx: Annodex media;" + "application/x-annodex: anx: Annodex media;" + "audio/annodex: axa: Annodex audio;" + "audio/x-annodex: axa: Annodex audio;" + "video/annodex: axv: Annodex video;" + "video/x-annodex: axv: Annodex video;"; } static void anx_class_dispose (demux_class_t *this_gen) { @@ -2130,7 +2140,7 @@ static void anx_class_dispose (demux_class_t *this_gen) { static void *anx_init_class (xine_t *xine, void *data) { demux_anx_class_t *this; - this = xine_xmalloc (sizeof (demux_anx_class_t)); + this = calloc(1, sizeof(demux_anx_class_t)); this->demux_class.open_plugin = anx_open_plugin; this->demux_class.get_description = anx_get_description; @@ -2149,20 +2159,25 @@ static void *anx_init_class (xine_t *xine, void *data) { static const char *ogg_get_description (demux_class_t *this_gen) { return "OGG demux plugin"; } - + static const char *ogg_get_identifier (demux_class_t *this_gen) { return "OGG"; } static const char *ogg_get_extensions (demux_class_t *this_gen) { - return "ogg ogm spx"; + return "ogx ogv oga ogg spx ogm"; } static const char *ogg_get_mimetypes (demux_class_t *this_gen) { - return "audio/x-ogg: ogg: OggVorbis Audio;" - "audio/x-speex: ogg: Speex Audio;" - "application/x-ogg: ogg: Ogg Stream;" - "application/ogg: ogg: Ogg Stream;"; + return "application/ogg: ogx: Ogg Stream;" + "application/x-ogg: ogx: Ogg Stream;" + "application/x-ogm: ogx: Ogg Stream;" + "application/x-ogm-audio: oga: Ogg Audio;" + "application/x-ogm-video: ogv: Ogg Video;" + "audio/ogg: oga: Ogg Audio;" + "audio/x-ogg: oga: Ogg Audio;" + "video/ogg: ogv: Ogg Video;" + "video/x-ogg: ogv: Ogg Video;"; } static void ogg_class_dispose (demux_class_t *this_gen) { @@ -2174,7 +2189,7 @@ static void ogg_class_dispose (demux_class_t *this_gen) { static void *ogg_init_class (xine_t *xine, void *data) { demux_ogg_class_t *this; - this = xine_xmalloc (sizeof (demux_ogg_class_t)); + this = calloc(1, sizeof(demux_ogg_class_t)); this->demux_class.open_plugin = ogg_open_plugin; this->demux_class.get_description = ogg_get_description; @@ -2198,7 +2213,7 @@ static const demuxer_info_t demux_info_ogg = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "ogg", XINE_VERSION_CODE, &demux_info_ogg, ogg_init_class }, { PLUGIN_DEMUX, 26, "anx", XINE_VERSION_CODE, &demux_info_anx, anx_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/demuxers/demux_pva.c b/src/demuxers/demux_pva.c index 298d936b5..e2b61dcf0 100644 --- a/src/demuxers/demux_pva.c +++ b/src/demuxers/demux_pva.c @@ -148,7 +148,7 @@ static int demux_pva_send_chunk(demux_plugin_t *this_gen) { current_file_pos = this->input->get_current_pos(this->input); if (preamble[2] == 1) { - + /* video */ /* load the pts if it is the first thing in the chunk */ @@ -253,7 +253,7 @@ static int demux_pva_send_chunk(demux_plugin_t *this_gen) { buf->pts = pts; if( this->data_size ) - buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) * + buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) * 65535 / this->data_size); this->audio_fifo->put (this->audio_fifo, buf); @@ -302,7 +302,7 @@ static void demux_pva_send_headers(demux_plugin_t *this_gen) { buf->pts = 0; if( this->data_size ) - buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) * + buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) * 65535 / this->data_size); buf->type = BUF_VIDEO_MPEG; @@ -329,7 +329,7 @@ static void demux_pva_send_headers(demux_plugin_t *this_gen) { buf->pts = 0; if( this->data_size ) - buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) * + buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) * 65535 / this->data_size); buf->type = BUF_AUDIO_MPEG; @@ -347,7 +347,7 @@ static int demux_pva_seek (demux_plugin_t *this_gen, unsigned char seek_buffer[SEEK_BUFFER_SIZE]; int found = 0; int i; - + start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); @@ -430,7 +430,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_pva_t)); + this = calloc(1, sizeof(demux_pva_t)); this->stream = stream; this->input = input; @@ -503,7 +503,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_pva_class_t *this; - this = xine_xmalloc (sizeof (demux_pva_class_t)); + this = calloc(1, sizeof(demux_pva_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index a55a0aef3..8e00d73a4 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -134,7 +134,7 @@ typedef unsigned int qt_atom; #define MAX_PTS_DIFF 100000 /* network bandwidth, cribbed from src/input/input_mms.c */ -const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600, +static const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600, 115200,262200,393216,524300,1544000,10485800}; /* these are things that can go wrong */ @@ -262,10 +262,10 @@ typedef struct { /* flags that indicate how a trak is supposed to be used */ unsigned int flags; - + /* formattag-like field that specifies codec in mp4 files */ unsigned int object_type_id; - + /* decoder data pass information to the decoder */ void *decoder_config; int decoder_config_len; @@ -307,7 +307,7 @@ typedef struct { unsigned int modification_time; unsigned int timescale; /* base clock frequency is Hz */ unsigned int duration; - + int64_t moov_first_offset; int trak_count; @@ -381,7 +381,7 @@ typedef struct { * lazyqt special debugging functions **********************************************************************/ -/* define DEBUG_ATOM_LOAD as 1 to get a verbose parsing of the relevant +/* define DEBUG_ATOM_LOAD as 1 to get a verbose parsing of the relevant * atoms */ #define DEBUG_ATOM_LOAD 0 @@ -403,7 +403,7 @@ typedef struct { /* Define DEBUG_DUMP_MOOV as 1 to dump the raw moov atom to disk. This is * particularly useful in debugging a file with a compressed moov (cmov) - * atom. The atom will be dumped to the filename specified as + * atom. The atom will be dumped to the filename specified as * RAW_MOOV_FILENAME. */ #define DEBUG_DUMP_MOOV 0 #define RAW_MOOV_FILENAME "moovatom.raw" @@ -502,7 +502,7 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset, atom = _X_BE_32(&atom_preamble[4]); /* Special case alert: 'free' atoms sometimes masquerade as 'moov' - * atoms. If this is a free atom, check for 'cmov' or 'mvhd' immediately + * atoms. If this is a free atom, check for 'cmov' or 'mvhd' immediately * following. QT Player can handle it, so xine should too. */ if (atom == FREE_ATOM) { @@ -533,7 +533,7 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset, /* if this atom is not the moov atom, make sure that it is at least one * of the other top-level QT atom. - * However, allow a configurable amount ( currently 1 ) atom be a + * However, allow a configurable amount ( currently 1 ) atom be a * non known atom, in hopes a known atom will be found */ if ((atom != FREE_ATOM) && (atom != JUNK_ATOM) && @@ -581,7 +581,7 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset, static qt_info *create_qt_info(void) { qt_info *info; - info = (qt_info *)xine_xmalloc(sizeof(qt_info)); + info = (qt_info *)calloc(1, sizeof(qt_info)); if (!info) return NULL; @@ -712,7 +712,7 @@ static int is_qt_file(input_plugin_t *qt_file) { return 0; } else { /* check that the next atom in the chunk contains alphanumeric - * characters in the atom type field; if not, disqualify the file + * characters in the atom type field; if not, disqualify the file * as a QT file */ qt_file->seek(qt_file, moov_atom_offset + ATOM_PREAMBLE_SIZE, SEEK_SET); if (qt_file->read(qt_file, atom_preamble, ATOM_PREAMBLE_SIZE) != @@ -738,39 +738,67 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) { if (current_atom == ART_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->artist = xine_xmalloc(string_size); - strncpy(info->artist, &meta_atom[i + 20], string_size - 1); - info->artist[string_size - 1] = 0; + if (info->artist) { + strncpy(info->artist, &meta_atom[i + 20], string_size - 1); + info->artist[string_size - 1] = 0; + } } else if (current_atom == NAM_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->name = xine_xmalloc(string_size); - strncpy(info->name, &meta_atom[i + 20], string_size - 1); - info->name[string_size - 1] = 0; + if (info->name) { + strncpy(info->name, &meta_atom[i + 20], string_size - 1); + info->name[string_size - 1] = 0; + } } else if (current_atom == ALB_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->album = xine_xmalloc(string_size); - strncpy(info->album, &meta_atom[i + 20], string_size - 1); - info->album[string_size - 1] = 0; + if (info->album) { + strncpy(info->album, &meta_atom[i + 20], string_size - 1); + info->album[string_size - 1] = 0; + } } else if (current_atom == GEN_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->genre = xine_xmalloc(string_size); - strncpy(info->genre, &meta_atom[i + 20], string_size - 1); - info->genre[string_size - 1] = 0; + if (info->genre) { + strncpy(info->genre, &meta_atom[i + 20], string_size - 1); + info->genre[string_size - 1] = 0; + } } else if (current_atom == TOO_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->comment = xine_xmalloc(string_size); - strncpy(info->comment, &meta_atom[i + 20], string_size - 1); - info->comment[string_size - 1] = 0; + if (info->comment) { + strncpy(info->comment, &meta_atom[i + 20], string_size - 1); + info->comment[string_size - 1] = 0; + } } else if (current_atom == WRT_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->composer = xine_xmalloc(string_size); - strncpy(info->composer, &meta_atom[i + 20], string_size - 1); - info->composer[string_size - 1] = 0; + if (info->composer) { + strncpy(info->composer, &meta_atom[i + 20], string_size - 1); + info->composer[string_size - 1] = 0; + } } else if (current_atom == DAY_ATOM) { string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1; + if (string_size <= 0) + continue; info->year = xine_xmalloc(string_size); - strncpy(info->year, &meta_atom[i + 20], string_size - 1); - info->year[string_size - 1] = 0; + if (info->year) { + strncpy(info->year, &meta_atom[i + 20], string_size - 1); + info->year[string_size - 1] = 0; + } } } @@ -793,7 +821,7 @@ static void parse_mvhd_atom(qt_info *info, unsigned char *mvhd_atom) { static int mp4_read_descr_len(unsigned char *s, uint32_t *length) { uint8_t b; uint8_t numBytes = 0; - + *length = 0; do { @@ -872,14 +900,14 @@ static qt_error parse_trak_atom (qt_trak *trak, break; } } - + debug_atom_load(" qt: parsing %s trak atom\n", (trak->type == MEDIA_VIDEO) ? "video" : (trak->type == MEDIA_AUDIO) ? "audio" : "other"); /* search for the useful atoms */ for (i = ATOM_PREAMBLE_SIZE; i < trak_atom_size - 4; i++) { - current_atom_size = _X_BE_32(&trak_atom[i - 4]); + current_atom_size = _X_BE_32(&trak_atom[i - 4]); current_atom = _X_BE_32(&trak_atom[i]); if (current_atom == TKHD_ATOM) { @@ -897,8 +925,8 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt elst atom (edit list atom): %d entries\n", trak->edit_list_count); - trak->edit_list_table = (edit_list_table_t *)xine_xmalloc( - trak->edit_list_count * sizeof(edit_list_table_t)); + trak->edit_list_table = (edit_list_table_t *)calloc( + trak->edit_list_count, sizeof(edit_list_table_t)); if (!trak->edit_list_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -919,7 +947,7 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (current_atom == MDHD_ATOM) { int version; debug_atom_load ("demux_qt: mdhd atom\n"); - + version = trak_atom[i+4]; if ( version > 1 ) continue; /* unsupported, undocumented */ @@ -933,18 +961,25 @@ static qt_error parse_trak_atom (qt_trak *trak, /* allocate space for each of the properties unions */ trak->stsd_atoms_count = _X_BE_32(&trak_atom[i + 8]); - trak->stsd_atoms = xine_xmalloc(trak->stsd_atoms_count * sizeof(properties_t)); + if (trak->stsd_atoms_count <= 0) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } + trak->stsd_atoms = calloc(trak->stsd_atoms_count, sizeof(properties_t)); if (!trak->stsd_atoms) { last_error = QT_NO_MEMORY; goto free_trak; } - memset(trak->stsd_atoms, 0, trak->stsd_atoms_count * sizeof(properties_t)); atom_pos = i + 0x10; properties_offset = 0x0C; for (k = 0; k < trak->stsd_atoms_count; k++) { - current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]); + current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]); + if (current_stsd_atom_size < 4) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } if (trak->type == MEDIA_VIDEO) { @@ -953,8 +988,12 @@ static qt_error parse_trak_atom (qt_trak *trak, /* copy the properties atom */ trak->stsd_atoms[k].video.properties_atom_size = current_stsd_atom_size - 4; - trak->stsd_atoms[k].video.properties_atom = + trak->stsd_atoms[k].video.properties_atom = xine_xmalloc(trak->stsd_atoms[k].video.properties_atom_size); + if (!trak->stsd_atoms[k].video.properties_atom) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].video.properties_atom, &trak_atom[atom_pos], trak->stsd_atoms[k].video.properties_atom_size); @@ -967,7 +1006,7 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].video.palette_count = 0; /* fetch video parameters */ - if( _X_BE_16(&trak_atom[atom_pos + 0x1C]) && + if( _X_BE_16(&trak_atom[atom_pos + 0x1C]) && _X_BE_16(&trak_atom[atom_pos + 0x1E]) ) { trak->stsd_atoms[k].video.width = _X_BE_16(&trak_atom[atom_pos + 0x1C]); @@ -995,9 +1034,9 @@ static qt_error parse_trak_atom (qt_trak *trak, /* compute the greyscale palette */ color_index = 255; - color_dec = 256 / + color_dec = 256 / (trak->stsd_atoms[k].video.palette_count - 1); - for (j = 0; + for (j = 0; j < trak->stsd_atoms[k].video.palette_count; j++) { @@ -1022,7 +1061,7 @@ static qt_error parse_trak_atom (qt_trak *trak, else color_table = qt_default_palette_256; - for (j = 0; + for (j = 0; j < trak->stsd_atoms[k].video.palette_count; j++) { @@ -1049,7 +1088,7 @@ static qt_error parse_trak_atom (qt_trak *trak, color_index = _X_BE_16(&trak_atom[atom_pos + 0x5A + j * 8]); if (color_count & 0x8000) color_index = j; - if (color_index < + if (color_index < trak->stsd_atoms[k].video.palette_count) { trak->stsd_atoms[k].video.palette[color_index].r = trak_atom[atom_pos + 0x5A + j * 8 + 2]; @@ -1092,8 +1131,12 @@ static qt_error parse_trak_atom (qt_trak *trak, /* copy the properties atom */ trak->stsd_atoms[k].audio.properties_atom_size = current_stsd_atom_size - 4; - trak->stsd_atoms[k].audio.properties_atom = + trak->stsd_atoms[k].audio.properties_atom = xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size); + if (!trak->stsd_atoms[k].audio.properties_atom) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].audio.properties_atom, &trak_atom[atom_pos], trak->stsd_atoms[k].audio.properties_atom_size); @@ -1110,12 +1153,12 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].audio.bits / 8; trak->stsd_atoms[k].audio.samples_per_frame = trak->stsd_atoms[k].audio.channels; - trak->stsd_atoms[k].audio.bytes_per_frame = - trak->stsd_atoms[k].audio.bytes_per_sample * + trak->stsd_atoms[k].audio.bytes_per_frame = + trak->stsd_atoms[k].audio.bytes_per_sample * trak->stsd_atoms[k].audio.samples_per_frame; - trak->stsd_atoms[k].audio.samples_per_packet = + trak->stsd_atoms[k].audio.samples_per_packet = trak->stsd_atoms[k].audio.samples_per_frame; - trak->stsd_atoms[k].audio.bytes_per_packet = + trak->stsd_atoms[k].audio.bytes_per_packet = trak->stsd_atoms[k].audio.bytes_per_sample; /* special case time: A lot of CBR audio codecs stored in the @@ -1123,7 +1166,7 @@ static qt_error parse_trak_atom (qt_trak *trak, if (trak->stsd_atoms[k].audio.codec_fourcc == IMA4_FOURCC) { trak->stsd_atoms[k].audio.samples_per_packet = 64; trak->stsd_atoms[k].audio.bytes_per_packet = 34; - trak->stsd_atoms[k].audio.bytes_per_frame = 34 * + trak->stsd_atoms[k].audio.bytes_per_frame = 34 * trak->stsd_atoms[k].audio.channels; trak->stsd_atoms[k].audio.bytes_per_sample = 2; trak->stsd_atoms[k].audio.samples_per_frame = 64 * @@ -1139,7 +1182,7 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (trak->stsd_atoms[k].audio.codec_fourcc == MAC6_FOURCC) { trak->stsd_atoms[k].audio.samples_per_packet = 6; trak->stsd_atoms[k].audio.bytes_per_packet = 1; - trak->stsd_atoms[k].audio.bytes_per_frame = 1 * + trak->stsd_atoms[k].audio.bytes_per_frame = 1 * trak->stsd_atoms[k].audio.channels; trak->stsd_atoms[k].audio.bytes_per_sample = 1; trak->stsd_atoms[k].audio.samples_per_frame = 6 * @@ -1147,7 +1190,7 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (trak->stsd_atoms[k].audio.codec_fourcc == ALAW_FOURCC) { trak->stsd_atoms[k].audio.samples_per_packet = 1; trak->stsd_atoms[k].audio.bytes_per_packet = 1; - trak->stsd_atoms[k].audio.bytes_per_frame = 1 * + trak->stsd_atoms[k].audio.bytes_per_frame = 1 * trak->stsd_atoms[k].audio.channels; trak->stsd_atoms[k].audio.bytes_per_sample = 2; trak->stsd_atoms[k].audio.samples_per_frame = 2 * @@ -1155,7 +1198,7 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (trak->stsd_atoms[k].audio.codec_fourcc == ULAW_FOURCC) { trak->stsd_atoms[k].audio.samples_per_packet = 1; trak->stsd_atoms[k].audio.bytes_per_packet = 1; - trak->stsd_atoms[k].audio.bytes_per_frame = 1 * + trak->stsd_atoms[k].audio.bytes_per_frame = 1 * trak->stsd_atoms[k].audio.channels; trak->stsd_atoms[k].audio.bytes_per_sample = 2; trak->stsd_atoms[k].audio.samples_per_frame = 2 * @@ -1174,21 +1217,22 @@ static qt_error parse_trak_atom (qt_trak *trak, (trak->stsd_atoms[k].audio.codec_fourcc != RAW_FOURCC)) { if (_X_BE_32(&trak_atom[atom_pos + 0x20])) - trak->stsd_atoms[k].audio.samples_per_packet = + trak->stsd_atoms[k].audio.samples_per_packet = _X_BE_32(&trak_atom[atom_pos + 0x20]); if (_X_BE_32(&trak_atom[atom_pos + 0x24])) - trak->stsd_atoms[k].audio.bytes_per_packet = + trak->stsd_atoms[k].audio.bytes_per_packet = _X_BE_32(&trak_atom[atom_pos + 0x24]); if (_X_BE_32(&trak_atom[atom_pos + 0x28])) - trak->stsd_atoms[k].audio.bytes_per_frame = + trak->stsd_atoms[k].audio.bytes_per_frame = _X_BE_32(&trak_atom[atom_pos + 0x28]); if (_X_BE_32(&trak_atom[atom_pos + 0x2C])) - trak->stsd_atoms[k].audio.bytes_per_sample = + trak->stsd_atoms[k].audio.bytes_per_sample = _X_BE_32(&trak_atom[atom_pos + 0x2C]); - trak->stsd_atoms[k].audio.samples_per_frame = - (trak->stsd_atoms[k].audio.bytes_per_frame / - trak->stsd_atoms[k].audio.bytes_per_packet) * - trak->stsd_atoms[k].audio.samples_per_packet; + if (trak->stsd_atoms[k].audio.bytes_per_packet) + trak->stsd_atoms[k].audio.samples_per_frame = + (trak->stsd_atoms[k].audio.bytes_per_frame / + trak->stsd_atoms[k].audio.bytes_per_packet) * + trak->stsd_atoms[k].audio.samples_per_packet; } /* see if the trak deserves a promotion to VBR */ @@ -1208,9 +1252,13 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].audio.vbr = 1; /* further, FFmpeg's ALAC decoder requires 36 out-of-band bytes */ trak->stsd_atoms[k].audio.properties_atom_size = 36; - trak->stsd_atoms[k].audio.properties_atom = + trak->stsd_atoms[k].audio.properties_atom = xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size); - memcpy(trak->stsd_atoms[k].audio.properties_atom, + if (!trak->stsd_atoms[k].audio.properties_atom) { + last_error = QT_NO_MEMORY; + goto free_trak; + } + memcpy(trak->stsd_atoms[k].audio.properties_atom, &trak_atom[atom_pos + 0x20], trak->stsd_atoms[k].audio.properties_atom_size); } @@ -1226,11 +1274,15 @@ static qt_error parse_trak_atom (qt_trak *trak, (_X_BE_32(&trak_atom[atom_pos + 0x3C]) == FRMA_ATOM) && (_X_ME_32(&trak_atom[atom_pos + 0x48]) == trak->stsd_atoms[k].audio.codec_fourcc)) { int wave_size = _X_BE_32(&trak_atom[atom_pos + 0x44]) - 8; - + if ((wave_size >= sizeof(xine_waveformatex)) && (current_atom_size >= (0x4C + wave_size))) { trak->stsd_atoms[k].audio.wave_size = wave_size; trak->stsd_atoms[k].audio.wave = xine_xmalloc(wave_size); + if (!trak->stsd_atoms[k].audio.wave) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->stsd_atoms[k].audio.wave, &trak_atom[atom_pos + 0x4C], wave_size); _x_waveformatex_le2me(trak->stsd_atoms[k].audio.wave); @@ -1279,12 +1331,12 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (current_atom == ESDS_ATOM) { uint32_t len; - + debug_atom_load(" qt/mpeg-4 esds atom\n"); - if ((trak->type == MEDIA_VIDEO) || + if ((trak->type == MEDIA_VIDEO) || (trak->type == MEDIA_AUDIO)) { - + j = i + 8; if( trak_atom[j++] == 0x03 ) { j += mp4_read_descr_len( &trak_atom[j], &len ); @@ -1300,21 +1352,29 @@ static qt_error parse_trak_atom (qt_trak *trak, j += mp4_read_descr_len( &trak_atom[j], &len ); debug_atom_load(" decoder config is %d (0x%X) bytes long\n", len, len); + if (len > current_atom_size - (j - i)) { + last_error = QT_NOT_A_VALID_FILE; + goto free_trak; + } trak->decoder_config = realloc(trak->decoder_config, len); trak->decoder_config_len = len; + if (!trak->decoder_config) { + last_error = QT_NO_MEMORY; + goto free_trak; + } memcpy(trak->decoder_config,&trak_atom[j],len); } } } } else if (current_atom == AVCC_ATOM) { - + debug_atom_load(" avcC atom\n"); - + trak->decoder_config_len = current_atom_size - 8; trak->decoder_config = realloc(trak->decoder_config, trak->decoder_config_len); memcpy(trak->decoder_config, &trak_atom[i + 4], trak->decoder_config_len); - + } else if (current_atom == STSZ_ATOM) { /* there should only be one of these atoms */ @@ -1331,8 +1391,8 @@ static qt_error parse_trak_atom (qt_trak *trak, /* allocate space and load table only if sample size is 0 */ if (trak->sample_size == 0) { - trak->sample_size_table = (unsigned int *)malloc( - trak->sample_size_count * sizeof(unsigned int)); + trak->sample_size_table = (unsigned int *)calloc( + trak->sample_size_count, sizeof(unsigned int)); if (!trak->sample_size_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -1362,8 +1422,8 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt stss atom (sample sync atom): %d sync samples\n", trak->sync_sample_count); - trak->sync_sample_table = (unsigned int *)malloc( - trak->sync_sample_count * sizeof(unsigned int)); + trak->sync_sample_table = (unsigned int *)calloc( + trak->sync_sample_count, sizeof(unsigned int)); if (!trak->sync_sample_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -1391,8 +1451,8 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt stco atom (32-bit chunk offset atom): %d chunk offsets\n", trak->chunk_offset_count); - trak->chunk_offset_table = (int64_t *)malloc( - trak->chunk_offset_count * sizeof(int64_t)); + trak->chunk_offset_table = (int64_t *)calloc( + trak->chunk_offset_count, sizeof(int64_t)); if (!trak->chunk_offset_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -1419,8 +1479,8 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt co64 atom (64-bit chunk offset atom): %d chunk offsets\n", trak->chunk_offset_count); - trak->chunk_offset_table = (int64_t *)malloc( - trak->chunk_offset_count * sizeof(int64_t)); + trak->chunk_offset_table = (int64_t *)calloc( + trak->chunk_offset_count, sizeof(int64_t)); if (!trak->chunk_offset_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -1450,8 +1510,8 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt stsc atom (sample-to-chunk atom): %d entries\n", trak->sample_to_chunk_count); - trak->sample_to_chunk_table = (sample_to_chunk_table_t *)malloc( - trak->sample_to_chunk_count * sizeof(sample_to_chunk_table_t)); + trak->sample_to_chunk_table = (sample_to_chunk_table_t *)calloc( + trak->sample_to_chunk_count, sizeof(sample_to_chunk_table_t)); if (!trak->sample_to_chunk_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -1475,7 +1535,8 @@ static qt_error parse_trak_atom (qt_trak *trak, } else if (current_atom == STTS_ATOM) { /* there should only be one of these atoms */ - if (trak->time_to_sample_table) { + if (trak->time_to_sample_table + || current_atom_size < 12 || current_atom_size >= UINT_MAX) { last_error = QT_HEADER_TROUBLE; goto free_trak; } @@ -1485,8 +1546,13 @@ static qt_error parse_trak_atom (qt_trak *trak, debug_atom_load(" qt stts atom (time-to-sample atom): %d entries\n", trak->time_to_sample_count); - trak->time_to_sample_table = (time_to_sample_table_t *)malloc( - (trak->time_to_sample_count+1) * sizeof(time_to_sample_table_t)); + if (trak->time_to_sample_count > (current_atom_size - 12) / 8) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } + + trak->time_to_sample_table = (time_to_sample_table_t *)calloc( + trak->time_to_sample_count+1, sizeof(time_to_sample_table_t)); if (!trak->time_to_sample_table) { last_error = QT_NO_MEMORY; goto free_trak; @@ -1537,44 +1603,51 @@ static qt_error parse_reference_atom (reference_t *ref, qt_atom current_atom; unsigned int current_atom_size; + if (ref_atom_size >= 0x80000000) + return QT_NOT_A_VALID_FILE; + /* initialize reference atom */ ref->url = NULL; ref->data_rate = 0; ref->qtim_version = 0; /* traverse through the atom looking for the key atoms */ - for (i = ATOM_PREAMBLE_SIZE; i < ref_atom_size - 4; i++) { + for (i = ATOM_PREAMBLE_SIZE; i + 4 < ref_atom_size; i++) { current_atom_size = _X_BE_32(&ref_atom[i - 4]); current_atom = _X_BE_32(&ref_atom[i]); if (current_atom == RDRF_ATOM) { + size_t string_size = _X_BE_32(&ref_atom[i + 12]); + size_t url_offset = 0; + int http = 0; + + if (string_size >= current_atom_size || string_size >= ref_atom_size - i) + return QT_NOT_A_VALID_FILE; /* if the URL starts with "http://", copy it */ - if (strncmp(&ref_atom[i + 16], "http://", 7) == 0 - || strncmp(&ref_atom[i + 16], "rtsp://", 7) == 0) { + if ( memcmp(&ref_atom[i + 16], "http://", 7) && + memcmp(&ref_atom[i + 16], "rtsp://", 7) && + base_mrl ) + { + /* We need a "qt" prefix hack for Apple trailers */ + http = !strncasecmp (base_mrl, "http://", 7); + url_offset = strlen(base_mrl) + 2 * http; + } + if (url_offset >= 0x80000000) + return QT_NOT_A_VALID_FILE; - /* URL is spec'd to terminate with a NULL; don't trust it */ - ref->url = xine_xmalloc(_X_BE_32(&ref_atom[i + 12]) + 1); - strncpy(ref->url, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12])); - ref->url[_X_BE_32(&ref_atom[i + 12]) - 1] = '\0'; + /* otherwise, append relative URL to base MRL */ + string_size += url_offset; - } else { + ref->url = xine_xmalloc(string_size + 1); - int string_size; + if ( url_offset ) + sprintf (ref->url, "%s%s", http ? "qt" : "", base_mrl); - if (base_mrl) - string_size = strlen(base_mrl) + _X_BE_32(&ref_atom[i + 12]) + 1; - else - string_size = _X_BE_32(&ref_atom[i + 12]) + 1; + memcpy(ref->url + url_offset, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12])); - /* otherwise, append relative URL to base MRL */ - ref->url = xine_xmalloc(string_size); - if (base_mrl) - strcpy(ref->url, base_mrl); - strncat(ref->url, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12])); - ref->url[string_size - 1] = '\0'; - } + ref->url[string_size] = '\0'; debug_atom_load(" qt rdrf URL reference:\n %s\n", ref->url); @@ -1609,9 +1682,9 @@ static qt_error parse_reference_atom (reference_t *ref, /* This is a little support function used to process the edit list when * building a frame table. */ #define MAX_DURATION 0x7FFFFFFFFFFFFFFFLL -static void get_next_edit_list_entry(qt_trak *trak, +static void get_next_edit_list_entry(qt_trak *trak, int *edit_list_index, - unsigned int *edit_list_media_time, + unsigned int *edit_list_media_time, int64_t *edit_list_duration, unsigned int global_timescale) { @@ -1628,9 +1701,9 @@ static void get_next_edit_list_entry(qt_trak *trak, /* otherwise, find an edit list entries whose media time != -1 */ if (trak->edit_list_table[*edit_list_index].media_time != -1) { - *edit_list_media_time = + *edit_list_media_time = trak->edit_list_table[*edit_list_index].media_time; - *edit_list_duration = + *edit_list_duration = trak->edit_list_table[*edit_list_index].track_duration; /* duration is in global timescale units; convert to trak timescale */ @@ -1644,8 +1717,8 @@ static void get_next_edit_list_entry(qt_trak *trak, *edit_list_index = *edit_list_index + 1; } - /* on the way out, check if this is the last edit list entry; if so, - * don't let the duration expire (so set it to an absurdly large value) + /* on the way out, check if this is the last edit list entry; if so, + * don't let the duration expire (so set it to an absurdly large value) */ if (*edit_list_index == trak->edit_list_count) *edit_list_duration = MAX_DURATION; @@ -1680,14 +1753,13 @@ static qt_error build_frame_table(qt_trak *trak, /* AUDIO and OTHER frame types follow the same rules; VIDEO and vbr audio * frame types follow a different set */ - if ((trak->type == MEDIA_VIDEO) || + if ((trak->type == MEDIA_VIDEO) || (trak->properties->audio.vbr)) { /* in this case, the total number of frames is equal to the number of * entries in the sample size table */ trak->frame_count = trak->sample_size_count; - trak->frames = (qt_frame *)malloc( - trak->frame_count * sizeof(qt_frame)); + trak->frames = (qt_frame *)calloc(trak->frame_count, sizeof(qt_frame)); if (!trak->frames) return QT_NO_MEMORY; trak->current_frame = 0; @@ -1699,10 +1771,9 @@ static qt_error build_frame_table(qt_trak *trak, pts_index_countdown = trak->time_to_sample_table[pts_index].count; - media_id_counts = xine_xmalloc(trak->stsd_atoms_count * sizeof(int)); + media_id_counts = calloc(trak->stsd_atoms_count, sizeof(int)); if (!media_id_counts) return QT_NO_MEMORY; - memset(media_id_counts, 0, trak->stsd_atoms_count * sizeof(int)); /* iterate through each start chunk in the stsc table */ for (i = 0; i < trak->sample_to_chunk_count; i++) { @@ -1732,7 +1803,7 @@ static qt_error build_frame_table(qt_trak *trak, trak->stsd_atoms_count); trak->frames[frame_counter].media_id = 0; } else { - trak->frames[frame_counter].media_id = + trak->frames[frame_counter].media_id = trak->sample_to_chunk_table[i].media_id; media_id_counts[trak->sample_to_chunk_table[i].media_id - 1]++; } @@ -1792,11 +1863,11 @@ static qt_error build_frame_table(qt_trak *trak, debug_edit_list(" %d: (before) pts = %"PRId64"...", i, trak->frames[i].pts); - if (trak->frames[i].pts < edit_list_media_time) + if (trak->frames[i].pts < edit_list_media_time) trak->frames[i].pts = edit_list_pts_counter; else { if (i < trak->frame_count - 1) - frame_duration = + frame_duration = (trak->frames[i + 1].pts - trak->frames[i].pts); debug_edit_list("duration = %"PRId64"...", frame_duration); @@ -1837,8 +1908,7 @@ static qt_error build_frame_table(qt_trak *trak, /* in this case, the total number of frames is equal to the number of * chunks */ trak->frame_count = trak->chunk_offset_count; - trak->frames = (qt_frame *)malloc( - trak->frame_count * sizeof(qt_frame)); + trak->frames = (qt_frame *)calloc(trak->frame_count, sizeof(qt_frame)); if (!trak->frames) return QT_NO_MEMORY; @@ -1876,7 +1946,7 @@ static qt_error build_frame_table(qt_trak *trak, trak->stsd_atoms_count); trak->frames[j].media_id = 0; } else { - trak->frames[j].media_id = + trak->frames[j].media_id = trak->sample_to_chunk_table[i].media_id; } @@ -1941,10 +2011,10 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom, /* create a new trak structure */ info->trak_count++; - info->traks = (qt_trak *)realloc(info->traks, + info->traks = (qt_trak *)realloc(info->traks, info->trak_count * sizeof(qt_trak)); - info->last_error = parse_trak_atom (&info->traks[info->trak_count - 1], + info->last_error = parse_trak_atom (&info->traks[info->trak_count - 1], &moov_atom[i - 4]); if (info->last_error != QT_OK) { info->trak_count--; @@ -1993,8 +2063,12 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom, info->references = (reference_t *)realloc(info->references, info->reference_count * sizeof(reference_t)); - parse_reference_atom(&info->references[info->reference_count - 1], - &moov_atom[i - 4], info->base_mrl); + error = parse_reference_atom(&info->references[info->reference_count - 1], + &moov_atom[i - 4], info->base_mrl); + if (error != QT_OK) { + info->last_error = error; + return; + } } else { debug_atom_load(" qt: unknown atom into the moov atom (0x%08X)\n", current_atom); @@ -2049,11 +2123,11 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom, /* iterate through 1..n-1 reference entries and decide on the right one */ for (i = 1; i < info->reference_count; i++) { - if (info->references[i].qtim_version > + if (info->references[i].qtim_version > info->references[info->chosen_reference].qtim_version) info->chosen_reference = i; else if ((info->references[i].data_rate <= bandwidth) && - (info->references[i].data_rate > + (info->references[i].data_rate > info->references[info->chosen_reference].data_rate)) info->chosen_reference = i; } @@ -2137,7 +2211,7 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input, info->last_error = QT_FILE_READ_ERROR; return info->last_error; } - if (input->read(input, moov_atom, moov_atom_size) != + if (input->read(input, moov_atom, moov_atom_size) != moov_atom_size) { free(moov_atom); info->last_error = QT_FILE_READ_ERROR; @@ -2145,7 +2219,7 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input, } /* check if moov is compressed */ - if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM) { + if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM && moov_atom_size >= 0x28) { info->compressed_header = 1; @@ -2268,12 +2342,12 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) { /* if audio is present, send pts of current audio frame, otherwise * send current video frame pts */ if (audio_trak) - _x_demux_control_newpts(this->stream, - audio_trak->frames[audio_trak->current_frame].pts, + _x_demux_control_newpts(this->stream, + audio_trak->frames[audio_trak->current_frame].pts, BUF_FLAG_SEEK); else - _x_demux_control_newpts(this->stream, - video_trak->frames[video_trak->current_frame].pts, + _x_demux_control_newpts(this->stream, + video_trak->frames[video_trak->current_frame].pts, BUF_FLAG_SEEK); } @@ -2380,7 +2454,7 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) { frame_duration); debug_video_demux(" qt: sending off video frame %d from offset 0x%"PRIX64", %d bytes, media id %d, %"PRId64" pts\n", - i, + i, video_trak->frames[i].offset, video_trak->frames[i].size, video_trak->frames[i].media_id, @@ -2438,7 +2512,7 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) { SEEK_SET); debug_audio_demux(" qt: sending off audio frame %d from offset 0x%"PRIX64", %d bytes, media id %d, %"PRId64" pts\n", - i, + i, audio_trak->frames[i].offset, audio_trak->frames[i].size, audio_trak->frames[i].media_id, @@ -2457,8 +2531,8 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) { * turns around and sends out audio buffers as soon as they are * received. If 2 or more consecutive audio buffers are dispatched to * the audio out unit, the engine will compensate with pops. */ - if ((buf->type == BUF_AUDIO_LPCM_BE) || - (buf->type == BUF_AUDIO_LPCM_LE)) { + if ((buf->type == BUF_AUDIO_LPCM_BE) || + (buf->type == BUF_AUDIO_LPCM_LE)) { if (first_buf) { buf->extra_info->input_time = audio_trak->frames[i].pts / 90; buf->pts = audio_trak->frames[i].pts; @@ -2487,7 +2561,7 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) { /* Special case alert: If this is signed, 8-bit data, transform * the data to unsigned. */ - if ((audio_trak->properties->audio.bits == 8) && + if ((audio_trak->properties->audio.bits == 8) && ((audio_trak->properties->audio.codec_fourcc == TWOS_FOURCC) || (audio_trak->properties->audio.codec_fourcc == SOWT_FOURCC))) for (j = 0; j < buf->size; j++) @@ -2556,7 +2630,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { this->bih.biBitCount = video_trak->properties->video.depth; this->bih.biCompression = video_trak->properties->video.codec_fourcc; - video_trak->properties->video.codec_buftype = + video_trak->properties->video.codec_buftype = _x_fourcc_to_buf_video(this->bih.biCompression); /* hack: workaround a fourcc clash! 'mpg4' is used by MS and Sorenson @@ -2564,13 +2638,13 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { */ if( video_trak->properties->video.codec_buftype == BUF_VIDEO_MSMPEG4_V1 ) video_trak->properties->video.codec_buftype = BUF_VIDEO_MPEG4; - - if( !video_trak->properties->video.codec_buftype && + + if( !video_trak->properties->video.codec_buftype && video_trak->properties->video.codec_fourcc ) video_trak->properties->video.codec_buftype = BUF_VIDEO_UNKNOWN; _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->bih.biWidth); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->bih.biHeight); @@ -2603,7 +2677,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { break; } } else { - audio_trak->properties->audio.codec_buftype = + audio_trak->properties->audio.codec_buftype = _x_formattag_to_buf_audio(audio_trak->properties->audio.codec_fourcc); } @@ -2618,7 +2692,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { audio_trak->properties->audio.sample_rate); _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, audio_trak->properties->audio.bits); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, audio_trak->properties->audio.codec_fourcc); } else { @@ -2659,17 +2733,17 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { (video_trak->properties->video.codec_buftype)) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - + memcpy(buf->content, &this->bih, sizeof(this->bih)); buf->size = sizeof(this->bih); buf->type = video_trak->properties->video.codec_buftype; this->video_fifo->put (this->video_fifo, buf); - + /* send header info to decoder. some mpeg4 streams need this */ if( video_trak->decoder_config ) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = video_trak->properties->video.codec_buftype; - + if (video_trak->properties->video.codec_fourcc == AVC1_FOURCC) { buf->size = 0; buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER; @@ -2713,9 +2787,9 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { /* set the audio bitrate field (only for CBR audio) */ if (!audio_trak->properties->audio.vbr) { - audio_bitrate = + audio_bitrate = audio_trak->properties->audio.sample_rate / - audio_trak->properties->audio.samples_per_frame * + audio_trak->properties->audio.samples_per_frame * audio_trak->properties->audio.bytes_per_frame * audio_trak->properties->audio.channels * 8; @@ -2730,7 +2804,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { buf->decoder_info[1] = audio_trak->properties->audio.sample_rate; buf->decoder_info[2] = audio_trak->properties->audio.bits; buf->decoder_info[3] = audio_trak->properties->audio.channels; - + if( audio_trak->properties->audio.wave_size ) { if( audio_trak->properties->audio.wave_size > buf->max_size ) buf->size = buf->max_size; @@ -2741,9 +2815,9 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) { buf->size = 0; buf->content = NULL; } - + this->audio_fifo->put (this->audio_fifo, buf); - + if( audio_trak->decoder_config ) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = audio_trak->properties->audio.codec_buftype; @@ -2836,7 +2910,7 @@ static int demux_qt_seek (demux_plugin_t *this_gen, qt_trak *video_trak = NULL; qt_trak *audio_trak = NULL; int64_t keyframe_pts; - + start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); @@ -2944,7 +3018,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_qt_t)); + this = calloc(1, sizeof(demux_qt_t)); this->stream = stream; this->input = input; @@ -3059,7 +3133,9 @@ static const char *get_mimetypes (demux_class_t *this_gen) { return "video/quicktime: mov,qt: Quicktime animation;" "video/x-quicktime: mov,qt: Quicktime animation;" "audio/x-m4a: m4a,m4b: MPEG-4 audio;" - "application/x-quicktimeplayer: qtl: Quicktime list;"; + "application/x-quicktimeplayer: qtl: Quicktime list;" + "video/mp4: mp4,mpg4: MPEG-4 video;" + "audio/mp4: mp4,mpg4: MPEG-4 audio;"; } static void class_dispose (demux_class_t *this_gen) { @@ -3073,7 +3149,7 @@ static void *init_plugin (xine_t *xine, void *data) { demux_qt_class_t *this; - this = xine_xmalloc (sizeof (demux_qt_class_t)); + this = calloc(1, sizeof(demux_qt_class_t)); this->config = xine->config; this->xine = xine; @@ -3095,7 +3171,7 @@ static const demuxer_info_t demux_info_qt = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "quicktime", XINE_VERSION_CODE, &demux_info_qt, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_rawdv.c b/src/demuxers/demux_rawdv.c index 2d21f080d..968542057 100644 --- a/src/demuxers/demux_rawdv.c +++ b/src/demuxers/demux_rawdv.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -89,17 +89,17 @@ static int demux_raw_dv_next (demux_raw_dv_t *this) { /* TODO: duplicate data and send to audio fifo. * however we don't have dvaudio decoder yet. */ - + buf->pts = this->pts; buf->extra_info->input_time = this->pts/90; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->extra_info->frame_number = this->cur_frame; buf->type = BUF_VIDEO_DV; - + this->video_fifo->put(this->video_fifo, buf); - + if (this->audio_fifo) { abuf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); abuf->content = abuf->mem; @@ -213,11 +213,11 @@ static void demux_raw_dv_send_headers (demux_plugin_t *this_gen) { bih->biSizeImage = bih->biWidth*bih->biHeight; this->video_fifo->put(this->video_fifo, buf); - + this->pts = 0; this->cur_frame = 0; this->bytes_left = this->frame_size; - + this->status = DEMUX_OK; _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); @@ -302,20 +302,21 @@ static int demux_raw_dv_seek (demux_plugin_t *this_gen, } if( !start_pos && start_time ) { - start_pos = (start_time * 90 / this->duration) * this->frame_size; + /* Upcast start_time in case sizeof(off_t) > sizeof(int) */ + start_pos = ((off_t) start_time * 90 / this->duration) * this->frame_size; } - - start_pos = start_pos - (start_pos % this->frame_size); + + start_pos = start_pos - (start_pos % this->frame_size); this->input->seek(this->input, start_pos, SEEK_SET); this->cur_frame = start_pos / this->frame_size; this->pts = this->cur_frame * this->duration; this->bytes_left = this->frame_size; - + _x_demux_flush_engine (this->stream); _x_demux_control_newpts (this->stream, this->pts, BUF_FLAG_SEEK); - + this->status = DEMUX_OK; return this->status; } @@ -347,7 +348,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_raw_dv_t *this; - this = xine_xmalloc (sizeof (demux_raw_dv_t)); + this = calloc(1, sizeof(demux_raw_dv_t)); this->stream = stream; this->input = input; @@ -367,15 +368,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str case METHOD_BY_CONTENT: { uint8_t buf[8]; - + if (_x_demux_read_header(input, buf, 8) != 8) { free (this); return NULL; } /* DIF (DV) movie file */ - if (!((buf[0] == 0x1f) && (buf[1] == 0x07) && (buf[2] == 00) && - (buf[4] ^ 0x01))) { + if (memcmp(buf, "\x1F\x07\x00", 3) != 0 || !(buf[4] ^ 0x01)) { free (this); return NULL; } @@ -436,7 +436,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_raw_dv_class_t *this; - this = xine_xmalloc (sizeof (demux_raw_dv_class_t)); + this = calloc(1, sizeof(demux_raw_dv_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index 85d7dc5a3..340083221 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2005 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -26,9 +26,9 @@ * * video packet sub-demuxer ported from mplayer code (www.mplayerhq.hu): * Real parser & demuxer - * + * * (C) Alex Beregszaszi <alex@naxine.org> - * + * * Based on FFmpeg's libav/rm.c. */ @@ -42,6 +42,9 @@ #include <string.h> #include <stdlib.h> #include <ctype.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif #define LOG_MODULE "demux_real" #define LOG_VERBOSE @@ -55,13 +58,13 @@ #include "demux.h" #include "bswap.h" +#include "real_common.h" + #define FOURCC_TAG BE_FOURCC -#define RMF_TAG FOURCC_TAG('.', 'R', 'M', 'F') #define PROP_TAG FOURCC_TAG('P', 'R', 'O', 'P') #define MDPR_TAG FOURCC_TAG('M', 'D', 'P', 'R') #define CONT_TAG FOURCC_TAG('C', 'O', 'N', 'T') #define DATA_TAG FOURCC_TAG('D', 'A', 'T', 'A') -#define INDX_TAG FOURCC_TAG('I', 'N', 'D', 'X') #define RA_TAG FOURCC_TAG('.', 'r', 'a', 0xfd) #define VIDO_TAG FOURCC_TAG('V', 'I', 'D', 'O') @@ -90,11 +93,11 @@ typedef struct { uint32_t start_time; uint32_t preroll; uint32_t duration; - char stream_name_size; + size_t stream_name_size; char *stream_name; - char mime_type_size; + size_t mime_type_size; char *mime_type; - uint32_t type_specific_len; + size_t type_specific_len; char *type_specific_data; } mdpr_t; @@ -108,11 +111,17 @@ typedef struct { uint32_t fourcc; uint32_t buf_type; uint32_t format; - + real_index_entry_t *index; int index_entries; - + mdpr_t *mdpr; + int sps, cfs, w, h; + int block_align; + size_t frame_size; + uint8_t *frame_buffer; + uint32_t frame_num_bytes; + uint32_t sub_packet_cnt; } real_stream_t; typedef struct { @@ -150,7 +159,7 @@ typedef struct { int64_t last_pts[2]; int send_newpts; int buf_flag_seek; - + uint32_t last_ts; uint32_t next_ts; int last_seq; @@ -168,16 +177,14 @@ typedef struct { demux_class_t demux_class; } demux_real_class_t; - static void real_parse_index(demux_real_t *this) { off_t next_index_chunk = this->index_start; off_t original_pos = this->input->get_current_pos(this->input); unsigned char index_chunk_header[INDEX_CHUNK_HEADER_SIZE]; unsigned char index_record[INDEX_RECORD_SIZE]; - int i, entries, stream_num; - real_index_entry_t **index; - + int i; + while(next_index_chunk) { lprintf("reading index chunk at %"PRIX64"\n", next_index_chunk); @@ -192,69 +199,68 @@ static void real_parse_index(demux_real_t *this) { } /* Check chunk is actually an index chunk */ - if(_X_BE_32(&index_chunk_header[0]) == INDX_TAG) { - unsigned short version; + if(!_x_is_fourcc(&index_chunk_header[0], "INDX")) { + lprintf("expected index chunk found chunk type: %.4s\n", &index_chunk_header[0]); + break; + } - /* Check version */ - version = _X_BE_16(&index_chunk_header[8]); - if(version != 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_real: unknown object version in INDX: 0x%04x\n", version); - break; - } + /* Check version */ + const uint16_t version = _X_BE_16(&index_chunk_header[8]); + if(version != 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: unknown object version in INDX: 0x%04x\n", version); + break; + } - /* Read data from header */ - entries = _X_BE_32(&index_chunk_header[10]); - stream_num = _X_BE_16(&index_chunk_header[14]); - next_index_chunk = _X_BE_32(&index_chunk_header[16]); - - /* Find which stream this index is for */ - index = NULL; - for(i = 0; i < this->num_video_streams; i++) { - if(stream_num == this->video_streams[i].mdpr->stream_number) { - index = &this->video_streams[i].index; - this->video_streams[i].index_entries = entries; - lprintf("found index chunk for video stream with num %d\n", stream_num); - break; - } + /* Read data from header */ + const uint32_t entries = _X_BE_32(&index_chunk_header[10]); + const uint16_t stream_num = _X_BE_16(&index_chunk_header[14]); + next_index_chunk = _X_BE_32(&index_chunk_header[16]); + + /* Find which stream this index is for */ + real_index_entry_t **index = NULL; + for(i = 0; i < this->num_video_streams; i++) { + if(stream_num == this->video_streams[i].mdpr->stream_number) { + index = &this->video_streams[i].index; + this->video_streams[i].index_entries = entries; + lprintf("found index chunk for video stream with num %d\n", stream_num); + break; } + } - if(!index) { - for(i = 0; i < this->num_audio_streams; i++) { - if(stream_num == this->audio_streams[i].mdpr->stream_number) { - index = &this->audio_streams[i].index; - this->audio_streams[i].index_entries = entries; - lprintf("found index chunk for audio stream with num %d\n", stream_num); - break; - } - } + if(!index) { + for(i = 0; i < this->num_audio_streams; i++) { + if(stream_num == this->audio_streams[i].mdpr->stream_number) { + index = &this->audio_streams[i].index; + this->audio_streams[i].index_entries = entries; + lprintf("found index chunk for audio stream with num %d\n", stream_num); + break; + } } + } - if(index && entries) { - /* Allocate memory for index */ - *index = xine_xmalloc(entries * sizeof(real_index_entry_t)); - - /* Read index */ - for(i = 0; i < entries; i++) { - if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE) - != INDEX_RECORD_SIZE) { - lprintf("index record not read\n"); - free(*index); - *index = NULL; - break; - } - - (*index)[i].timestamp = _X_BE_32(&index_record[2]); - (*index)[i].offset = _X_BE_32(&index_record[6]); - (*index)[i].packetno = _X_BE_32(&index_record[10]); - } - } else { - lprintf("unused index chunk with %d entries for stream num %d\n", - entries, stream_num); + if(index && entries) + /* Allocate memory for index */ + *index = calloc(entries, sizeof(real_index_entry_t)); + + if(index && entries && *index) { + /* Read index */ + for(i = 0; i < entries; i++) { + if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE) + != INDEX_RECORD_SIZE) { + lprintf("index record not read\n"); + free(*index); + *index = NULL; + break; + } + + (*index)[i].timestamp = _X_BE_32(&index_record[2]); + (*index)[i].offset = _X_BE_32(&index_record[6]); + (*index)[i].packetno = _X_BE_32(&index_record[10]); } } else { - lprintf("expected index chunk found chunk type: %.4s\n", &index_chunk_header[0]); - break; + lprintf("unused index chunk with %d entries for stream num %d\n", + entries, stream_num); } } @@ -262,8 +268,12 @@ static void real_parse_index(demux_real_t *this) { this->input->seek(this->input, original_pos, SEEK_SET); } -static mdpr_t *real_parse_mdpr(const char *data) { - mdpr_t *mdpr=malloc(sizeof(mdpr_t)); +static mdpr_t *real_parse_mdpr(const char *data, const unsigned int size) +{ + if (size < 38) + return NULL; + + mdpr_t *mdpr=calloc(sizeof(mdpr_t), 1); mdpr->stream_number=_X_BE_16(&data[2]); mdpr->max_bit_rate=_X_BE_32(&data[4]); @@ -275,17 +285,29 @@ static mdpr_t *real_parse_mdpr(const char *data) { mdpr->duration=_X_BE_32(&data[28]); mdpr->stream_name_size=data[32]; - mdpr->stream_name=malloc(sizeof(char)*(mdpr->stream_name_size+1)); + if (size < 38 + mdpr->stream_name_size) + goto fail; + mdpr->stream_name=malloc(mdpr->stream_name_size+1); + if (!mdpr->stream_name) + goto fail; memcpy(mdpr->stream_name, &data[33], mdpr->stream_name_size); mdpr->stream_name[(int)mdpr->stream_name_size]=0; mdpr->mime_type_size=data[33+mdpr->stream_name_size]; - mdpr->mime_type=malloc(sizeof(char)*(mdpr->mime_type_size+1)); + if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size) + goto fail; + mdpr->mime_type=malloc(mdpr->mime_type_size+1); + if (!mdpr->mime_type) + goto fail; memcpy(mdpr->mime_type, &data[34+mdpr->stream_name_size], mdpr->mime_type_size); mdpr->mime_type[(int)mdpr->mime_type_size]=0; mdpr->type_specific_len=_X_BE_32(&data[34+mdpr->stream_name_size+mdpr->mime_type_size]); - mdpr->type_specific_data=malloc(sizeof(char)*(mdpr->type_specific_len)); + if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size + mdpr->type_specific_data) + goto fail; + mdpr->type_specific_data=malloc(mdpr->type_specific_len); + if (!mdpr->type_specific_data) + goto fail; memcpy(mdpr->type_specific_data, &data[38+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); @@ -305,6 +327,13 @@ static mdpr_t *real_parse_mdpr(const char *data) { #endif return mdpr; + +fail: + free (mdpr->stream_name); + free (mdpr->mime_type); + free (mdpr->type_specific_data); + free (mdpr); + return NULL; } static void real_free_mdpr (mdpr_t *mdpr) { @@ -314,43 +343,109 @@ static void real_free_mdpr (mdpr_t *mdpr) { free (mdpr); } +static void real_parse_audio_specific_data (demux_real_t *this, + real_stream_t * stream) +{ + if (stream->mdpr->type_specific_len < 46) { + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + "demux_real: audio data size smaller than header length!\n"); + return; + } + + uint8_t * data = stream->mdpr->type_specific_data; + const uint32_t coded_frame_size = _X_BE_32 (data+24); + const uint16_t codec_data_length = _X_BE_16 (data+40); + const uint16_t coded_frame_size2 = _X_BE_16 (data+42); + const uint16_t subpacket_size = _X_BE_16 (data+44); + + stream->sps = subpacket_size; + stream->w = coded_frame_size2; + stream->h = codec_data_length; + stream->block_align = coded_frame_size2; + stream->cfs = coded_frame_size; + + switch (stream->buf_type) { + case BUF_AUDIO_COOK: + case BUF_AUDIO_ATRK: + stream->block_align = subpacket_size; + break; + + case BUF_AUDIO_14_4: + break; + + case BUF_AUDIO_28_8: + stream->block_align = stream->cfs; + break; + + case BUF_AUDIO_SIPRO: + /* this->block_align = 19; */ + break; + + default: + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: error, i don't handle buf type 0x%08x\n", stream->buf_type); + } + + /* + * when stream->sps is set it used to do this: + * stream->frame_size = stream->w / stream->sps * stream->h * stream->sps; + * but it looks pointless? the compiler will probably optimise it away, I suppose? + */ + if (stream->w < 32768 && stream->h < 32768) { + stream->frame_size = stream->w * stream->h; + stream->frame_buffer = calloc(stream->frame_size, 1); + } else { + stream->frame_size = 0; + stream->frame_buffer = NULL; + } + + stream->frame_num_bytes = 0; + stream->sub_packet_cnt = 0; + + if (!stream->frame_buffer) + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + "demux_real: failed to allocate the audio frame buffer!\n"); + + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + "demux_real: buf type 0x%08x frame size %zu block align %d\n", stream->buf_type, + stream->frame_size, stream->block_align); + +} static void real_parse_headers (demux_real_t *this) { char preamble[PREAMBLE_SIZE]; unsigned int chunk_type = 0; unsigned int chunk_size; - unsigned short version; - unsigned char *chunk_buffer; - int field_size; - int stream_ptr; - unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE]; - unsigned char signature[REAL_SIGNATURE_SIZE]; - - this->data_start = 0; - this->data_size = 0; - this->num_video_streams = 0; - this->num_audio_streams = 0; if (INPUT_IS_SEEKABLE(this->input)) this->input->seek (this->input, 0, SEEK_SET); - if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) != - REAL_SIGNATURE_SIZE) { + { + uint8_t signature[REAL_SIGNATURE_SIZE]; + if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) != + REAL_SIGNATURE_SIZE) { - lprintf ("signature not read\n"); - this->status = DEMUX_FINISHED; - return; - } + lprintf ("signature not read\n"); + this->status = DEMUX_FINISHED; + return; + } - if (_X_BE_32(signature) != RMF_TAG) { - this->status = DEMUX_FINISHED; - lprintf ("signature not found '%.4s'\n", signature); - return; + if ( !_x_is_fourcc(signature, ".RMF") ) { + this->status = DEMUX_FINISHED; + lprintf ("signature not found '%.4s'\n", signature); + return; + } + + /* skip to the start of the first chunk and start traversing */ + chunk_size = _X_BE_32(&signature[4]); } - /* skip to the start of the first chunk and start traversing */ - chunk_size = _X_BE_32(&signature[4]); + this->data_start = 0; + this->data_size = 0; + this->num_video_streams = 0; + this->num_audio_streams = 0; + this->input->seek(this->input, chunk_size-8, SEEK_CUR); /* iterate through chunks and gather information until the first DATA @@ -371,179 +466,198 @@ static void real_parse_headers (demux_real_t *this) { case PROP_TAG: case MDPR_TAG: case CONT_TAG: + { + if (chunk_size < PREAMBLE_SIZE+1) { + this->status = DEMUX_FINISHED; + return; + } + chunk_size -= PREAMBLE_SIZE; + uint8_t *const chunk_buffer = malloc(chunk_size); + if (! chunk_buffer || + this->input->read(this->input, chunk_buffer, chunk_size) != + chunk_size) { + free (chunk_buffer); + this->status = DEMUX_FINISHED; + return; + } - chunk_size -= PREAMBLE_SIZE; - chunk_buffer = xine_xmalloc(chunk_size); - if (this->input->read(this->input, chunk_buffer, chunk_size) != - chunk_size) { - free (chunk_buffer); - this->status = DEMUX_FINISHED; - return; - } - - version = _X_BE_16(&chunk_buffer[0]); - - if (chunk_type == PROP_TAG) { - - if(version != 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demuxe_real: unknown object version in PROP: 0x%04x\n", version); - free(chunk_buffer); - this->status = DEMUX_FINISHED; - return; - } - - this->duration = _X_BE_32(&chunk_buffer[22]); - this->index_start = _X_BE_32(&chunk_buffer[30]); - this->data_start = _X_BE_32(&chunk_buffer[34]); - this->avg_bitrate = _X_BE_32(&chunk_buffer[6]); - - lprintf("PROP: duration: %d ms\n", this->duration); - lprintf("PROP: index start: %"PRIX64"\n", this->index_start); - lprintf("PROP: data start: %"PRIX64"\n", this->data_start); - lprintf("PROP: average bit rate: %"PRId64"\n", this->avg_bitrate); - - if (this->avg_bitrate<1) - this->avg_bitrate = 1; - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, - this->avg_bitrate); - - } else if (chunk_type == MDPR_TAG) { + uint16_t version = _X_BE_16(&chunk_buffer[0]); - mdpr_t *mdpr; - uint32_t fourcc; + if (chunk_type == PROP_TAG) { - if (version != 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_real: unknown object version in MDPR: 0x%04x\n", version); - free(chunk_buffer); - continue; - } - - mdpr = real_parse_mdpr (chunk_buffer); + if(version != 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demuxe_real: unknown object version in PROP: 0x%04x\n", version); + free(chunk_buffer); + this->status = DEMUX_FINISHED; + return; + } - lprintf ("parsing type specific data...\n"); + this->duration = _X_BE_32(&chunk_buffer[22]); + this->index_start = _X_BE_32(&chunk_buffer[30]); + this->data_start = _X_BE_32(&chunk_buffer[34]); + this->avg_bitrate = _X_BE_32(&chunk_buffer[6]); - if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) { - int version, len; + lprintf("PROP: duration: %d ms\n", this->duration); + lprintf("PROP: index start: %"PRIX64"\n", this->index_start); + lprintf("PROP: data start: %"PRIX64"\n", this->data_start); + lprintf("PROP: average bit rate: %"PRId64"\n", this->avg_bitrate); - if(this->num_audio_streams == MAX_AUDIO_STREAMS) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_real: maximum number of audio stream exceeded\n"); - goto unknown; - } - - version = _X_BE_16(mdpr->type_specific_data + 4); + if (this->avg_bitrate<1) + this->avg_bitrate = 1; - lprintf("audio version %d detected\n", version); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, + this->avg_bitrate); - switch(version) { + } else if (chunk_type == MDPR_TAG) { + if (version != 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: unknown object version in MDPR: 0x%04x\n", version); + free(chunk_buffer); + continue; + } + + mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer, chunk_size); + + lprintf ("parsing type specific data...\n"); + if (!mdpr) { + free (chunk_buffer); + this->status = DEMUX_FINISHED; + return; + } + if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) { + lprintf ("mpeg layer 3 audio detected...\n"); + + static const uint32_t fourcc = ME_FOURCC('a', 'd', 'u', 0x55); + this->audio_streams[this->num_audio_streams].fourcc = fourcc; + this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc); + this->audio_streams[this->num_audio_streams].index = NULL; + this->audio_streams[this->num_audio_streams].mdpr = mdpr; + this->num_audio_streams++; + } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG && + mdpr->type_specific_len >= 6) { + if(this->num_audio_streams == MAX_AUDIO_STREAMS) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: maximum number of audio stream exceeded\n"); + goto unknown; + } + + const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4); + + lprintf("audio version %d detected\n", version); + + char *fourcc_ptr = "\0\0\0"; + switch(version) { case 3: - /* Version 3 header stores fourcc after meta info - cheat by reading backwards from the + /* Version 3 header stores fourcc after meta info - cheat by reading backwards from the * end of the header instead of having to parse it all */ - fourcc = _X_ME_32(mdpr->type_specific_data + mdpr->type_specific_len - 5); + if (mdpr->type_specific_len >= 5) + fourcc_ptr = mdpr->type_specific_data + mdpr->type_specific_len - 5; break; - case 4: - len = *(mdpr->type_specific_data + 56); - fourcc = _X_ME_32(mdpr->type_specific_data + 58 + len); + case 4: { + if (mdpr->type_specific_len >= 57) { + const uint8_t len = *(mdpr->type_specific_data + 56); + if (mdpr->type_specific_len >= 62 + len) + fourcc_ptr = mdpr->type_specific_data + 58 + len; + } + } break; case 5: - fourcc = _X_ME_32(mdpr->type_specific_data + 66); + if (mdpr->type_specific_len >= 70) + fourcc_ptr = mdpr->type_specific_data + 66; break; default: lprintf("unsupported audio header version %d\n", version); goto unknown; - } - - lprintf("fourcc = %.4s\n", (char *) &fourcc); - - this->audio_streams[this->num_audio_streams].fourcc = fourcc; - this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc); - this->audio_streams[this->num_audio_streams].index = NULL; - this->audio_streams[this->num_audio_streams].mdpr = mdpr; - - this->num_audio_streams++; - - } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG) { - - if(this->num_video_streams == MAX_VIDEO_STREAMS) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_real: maximum number of video stream exceeded\n"); - goto unknown; - } - - lprintf ("video detected\n"); - fourcc = _X_ME_32(mdpr->type_specific_data + 8); - lprintf("fourcc = %.4s\n", (char *) &fourcc); - - this->video_streams[this->num_video_streams].fourcc = fourcc; - this->video_streams[this->num_video_streams].buf_type = _x_fourcc_to_buf_video(fourcc); - this->video_streams[this->num_video_streams].format = _X_BE_32(mdpr->type_specific_data + 30); - this->video_streams[this->num_video_streams].index = NULL; - this->video_streams[this->num_video_streams].mdpr = mdpr; - - this->num_video_streams++; - - } else { - lprintf("unrecognised type specific data\n"); - -unknown: - real_free_mdpr(mdpr); - } - - } else if (chunk_type == CONT_TAG) { - - if(version != 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_real: unknown object version in CONT: 0x%04x\n", version); - free(chunk_buffer); - continue; - } + } + lprintf("fourcc = %.4s\n", fourcc_ptr); + + const uint32_t fourcc = _X_ME_32(fourcc_ptr); + + this->audio_streams[this->num_audio_streams].fourcc = fourcc; + this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc); + this->audio_streams[this->num_audio_streams].index = NULL; + this->audio_streams[this->num_audio_streams].mdpr = mdpr; + + real_parse_audio_specific_data (this, + &this->audio_streams[this->num_audio_streams]); + this->num_audio_streams++; + + } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG && + mdpr->type_specific_len >= 34) { + + if(this->num_video_streams == MAX_VIDEO_STREAMS) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: maximum number of video stream exceeded\n"); + goto unknown; + } + + lprintf ("video detected\n"); + const uint32_t fourcc = _X_ME_32(mdpr->type_specific_data + 8); + lprintf("fourcc = %.4s\n", (char *) &fourcc); + + this->video_streams[this->num_video_streams].fourcc = fourcc; + this->video_streams[this->num_video_streams].buf_type = _x_fourcc_to_buf_video(fourcc); + this->video_streams[this->num_video_streams].format = _X_BE_32(mdpr->type_specific_data + 30); + this->video_streams[this->num_video_streams].index = NULL; + this->video_streams[this->num_video_streams].mdpr = mdpr; + + this->num_video_streams++; + + } else { + lprintf("unrecognised type specific data\n"); + + unknown: + real_free_mdpr(mdpr); + } + + } else if (chunk_type == CONT_TAG) { + + if(version != 0) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: unknown object version in CONT: 0x%04x\n", version); + free(chunk_buffer); + continue; + } + + int stream_ptr = 2; +#define SET_METADATA_STRING(type) \ + do { \ + const uint16_t field_size = _X_BE_16(&chunk_buffer[stream_ptr]); \ + stream_ptr += 2; \ + _x_meta_info_n_set(this->stream, type, \ + &chunk_buffer[stream_ptr], field_size); \ + stream_ptr += field_size; \ + } while(0) + + /* load the title string */ + SET_METADATA_STRING(XINE_META_INFO_TITLE); + + /* load the author string */ + SET_METADATA_STRING(XINE_META_INFO_ARTIST); + + /* load the copyright string as the year */ + SET_METADATA_STRING(XINE_META_INFO_YEAR); + + /* load the comment string */ + SET_METADATA_STRING(XINE_META_INFO_COMMENT); + } - stream_ptr = 2; - - /* load the title string */ - field_size = _X_BE_16(&chunk_buffer[stream_ptr]); - stream_ptr += 2; - _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE, - &chunk_buffer[stream_ptr], field_size); - stream_ptr += field_size; - - /* load the author string */ - field_size = _X_BE_16(&chunk_buffer[stream_ptr]); - stream_ptr += 2; - _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST, - &chunk_buffer[stream_ptr], field_size); - stream_ptr += field_size; - - /* load the copyright string as the year */ - field_size = _X_BE_16(&chunk_buffer[stream_ptr]); - stream_ptr += 2; - _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR, - &chunk_buffer[stream_ptr], field_size); - stream_ptr += field_size; - - /* load the comment string */ - field_size = _X_BE_16(&chunk_buffer[stream_ptr]); - stream_ptr += 2; - _x_meta_info_n_set(this->stream, XINE_META_INFO_COMMENT, - &chunk_buffer[stream_ptr], field_size); - stream_ptr += field_size; + free(chunk_buffer); } - - free(chunk_buffer); break; - case DATA_TAG: - if (this->input->read(this->input, data_chunk_header, + case DATA_TAG: { + uint8_t data_chunk_header[DATA_CHUNK_HEADER_SIZE]; + + if (this->input->read(this->input, data_chunk_header, DATA_CHUNK_HEADER_SIZE) != DATA_CHUNK_HEADER_SIZE) { this->status = DEMUX_FINISHED; return ; } - + /* check version */ - version = _X_BE_16(&data_chunk_header[0]); + const uint16_t version = _X_BE_16(&data_chunk_header[0]); if(version != 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: unknown object version in DATA: 0x%04x\n", version); @@ -554,7 +668,8 @@ unknown: this->current_data_chunk_packet_count = _X_BE_32(&data_chunk_header[2]); this->next_data_chunk_offset = _X_BE_32(&data_chunk_header[6]); this->data_chunk_size = chunk_size; - break; + } + break; default: /* this should not occur, but in case it does, skip the chunk */ @@ -568,17 +683,10 @@ unknown: /* Read index tables */ if(INPUT_IS_SEEKABLE(this->input)) real_parse_index(this); - + /* Simple stream selection case - 0/1 audio/video streams */ - if(this->num_video_streams == 1) - this->video_stream = &this->video_streams[0]; - else - this->video_stream = NULL; - - if(this->num_audio_streams == 1) - this->audio_stream = &this->audio_streams[0]; - else - this->audio_stream = NULL; + this->video_stream = (this->num_video_streams == 1) ? &this->video_streams[0] : NULL; + this->audio_stream = (this->num_audio_streams == 1) ? &this->audio_streams[0] : NULL; /* In the case of multiple audio/video streams select the first streams found in the file */ @@ -590,23 +698,23 @@ unknown: /* Get data to search through for stream chunks */ if(INPUT_IS_SEEKABLE(this->input)) { original_pos = this->input->get_current_pos(this->input); - + if((len = this->input->read(this->input, search_buffer, MAX_PREVIEW_SIZE)) <= 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: failed to read header\n"); this->status = DEMUX_FINISHED; return; } - + offset = 0; } else if((this->input->get_capabilities(this->input) & INPUT_CAP_PREVIEW) != 0) { if((len = this->input->get_optional_data(this->input, search_buffer, INPUT_OPTIONAL_DATA_PREVIEW)) <= 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: failed to read header\n"); this->status = DEMUX_FINISHED; return; } - + /* Preview data starts at the beginning of the file */ offset = this->data_start + 18; } else { @@ -615,19 +723,17 @@ unknown: this->status = DEMUX_FINISHED; return; } - + while((offset < len) && ((!this->video_stream && (this->num_video_streams > 0)) || (!this->audio_stream && (this->num_audio_streams > 0)))) { - uint32_t id; - int i, stream; - + int i; + /* Check for end of the data chunk */ - if(((id = _X_BE_32(&search_buffer[offset])) == DATA_TAG) || - (id == INDX_TAG)) - break; - - stream = _X_BE_16(&search_buffer[offset + 4]); + if (_x_is_fourcc(&search_buffer[offset], "INDX") || _x_is_fourcc(&search_buffer[offset], "DATA")) + break; + + const int stream = _X_BE_16(&search_buffer[offset + 4]); for(i = 0; !this->video_stream && (i < this->num_video_streams); i++) { if(stream == this->video_streams[i].mdpr->stream_number) { @@ -635,7 +741,7 @@ unknown: lprintf("selecting video stream: %d\n", stream); } } - + for(i = 0; !this->audio_stream && (i < this->num_audio_streams); i++) { if(stream == this->audio_streams[i].mdpr->stream_number) { this->audio_stream = &this->audio_streams[i]; @@ -645,11 +751,11 @@ unknown: offset += _X_BE_16(&search_buffer[offset + 2]); } - + if(INPUT_IS_SEEKABLE(this->input)) this->input->seek(this->input, original_pos, SEEK_SET); } - + /* Let the user know if we haven't managed to detect what streams to play */ if((!this->video_stream && this->num_video_streams) || (!this->audio_stream && this->num_audio_streams)) { @@ -658,19 +764,17 @@ unknown: this->status = DEMUX_FINISHED; return; } - + /* Send headers and set meta info */ if(this->video_stream) { - buf_element_t *buf; - /* Check for recognised codec*/ if(!this->video_stream->buf_type) this->video_stream->buf_type = BUF_VIDEO_UNKNOWN; - + /* Send header */ - buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + buf_element_t *const buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); buf->content = buf->mem; - + memcpy(buf->content, this->video_stream->mdpr->type_specific_data, this->video_stream->mdpr->type_specific_len); @@ -688,9 +792,9 @@ unknown: this->video_stream->fourcc); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_BITRATE, this->video_stream->mdpr->avg_bit_rate); - + /* Allocate fragment offset table */ - this->fragment_tab = xine_xmalloc(FRAGMENT_TAB_SIZE*sizeof(uint32_t)); + this->fragment_tab = calloc(FRAGMENT_TAB_SIZE, sizeof(uint32_t)); this->fragment_tab_max = FRAGMENT_TAB_SIZE; } @@ -698,31 +802,30 @@ unknown: /* Check for recognised codec */ if(!this->audio_stream->buf_type) this->audio_stream->buf_type = BUF_AUDIO_UNKNOWN; - + /* Send headers */ if(this->audio_fifo) { - mdpr_t *mdpr = this->audio_stream->mdpr; - buf_element_t *buf; + mdpr_t *const mdpr = this->audio_stream->mdpr; - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf_element_t *buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = this->audio_stream->buf_type; buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END; - + /* For AAC we send two header buffers, the first is a standard audio * header giving bits per sample, sample rate and number of channels. * The second is the codec initialisation data found at the end of * the type specific data for the audio stream */ if(buf->type == BUF_AUDIO_AAC) { - int version = _X_BE_16(mdpr->type_specific_data + 4); - + const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4); + if(version != 5) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: unsupported audio header version for AAC: %d\n", version); buf->free_buffer(buf); goto unsupported; } - + buf->decoder_info[1] = _X_BE_16(mdpr->type_specific_data + 54); buf->decoder_info[2] = _X_BE_16(mdpr->type_specific_data + 58); buf->decoder_info[3] = _X_BE_16(mdpr->type_specific_data + 60); @@ -730,21 +833,28 @@ unknown: buf->decoder_flags |= BUF_FLAG_STDHEADER; buf->content = NULL; buf->size = 0; - + this->audio_fifo->put (this->audio_fifo, buf); - + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - + buf->type = this->audio_stream->buf_type; buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END|BUF_FLAG_SPECIAL; buf->decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG; buf->decoder_info[2] = _X_BE_32(mdpr->type_specific_data + 74) - 1; buf->decoder_info_ptr[2] = buf->content; buf->size = 0; - + memcpy(buf->content, mdpr->type_specific_data + 79, buf->decoder_info[2]); + } else if(buf->type == BUF_AUDIO_MP3ADU) { + buf->decoder_flags |= BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END; + buf->size = 0; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = 0; + buf->decoder_info[2] = 0; + buf->decoder_info[3] = 0; } else { memcpy(buf->content, mdpr->type_specific_data, mdpr->type_specific_len); @@ -782,7 +892,7 @@ static int demux_real_parse_references( demux_real_t *this) { lprintf("parsing references\n"); - + /* read file to memory. * warning: dumb code, but hopefuly ok since reference file is small */ do { @@ -801,17 +911,27 @@ static int demux_real_parse_references( demux_real_t *this) { if(buf_used) buf[buf_used] = '\0'; - + lprintf("received %d bytes [%s]\n", buf_used, buf); if (!strncmp(buf,"http://",7)) { - for (i = 0; buf[i] && !isspace(buf[i]); ++i) - /**/; - buf[i] = 0; - lprintf("reference [%s] found\n", buf); - - _x_demux_send_mrl_reference (this->stream, 0, buf, NULL, 0, 0); + i = 0; + while (buf[i]) + { + j = i; + while (buf[i] && !isspace(buf[i])) + ++i; /* skip non-space */ + len = buf[i]; + buf[i] = 0; + if (strncmp (buf + j, "http://", 7) || (i - j) < 8) + break; /* stop at the first non-http reference */ + lprintf("reference [%s] found\n", buf + j); + _x_demux_send_mrl_reference (this->stream, 0, buf + j, NULL, 0, 0); + buf[i] = (char) len; + while (buf[i] && isspace(buf[i])) + ++i; /* skip spaces */ + } } else for (i = 0; i < buf_used; ++i) { @@ -825,10 +945,10 @@ static int demux_real_parse_references( demux_real_t *this) { /* rpm files can contain comments which should be skipped */ if( !strncmp(&buf[i],"<!--",4) ) comment = 1; - + if( !strncmp(&buf[i],"-->",3) ) comment = 0; - + if( (!strncmp(&buf[i],"pnm://",6) || !strncmp(&buf[i],"rtsp://",7)) && !comment ) { for(j=i; buf[j] && buf[j] != '"' && !isspace(buf[j]); j++ ) @@ -841,14 +961,14 @@ static int demux_real_parse_references( demux_real_t *this) { i = j; } - } - + } + free(buf); - + this->status = DEMUX_FINISHED; return this->status; } - + /* redefine abs as macro to handle 64-bit diffs. i guess llabs may not be available everywhere */ #define abs(x) ( ((x)<0) ? -(x) : (x) ) @@ -858,9 +978,7 @@ static int demux_real_parse_references( demux_real_t *this) { #define PTS_VIDEO 1 static void check_newpts (demux_real_t *this, int64_t pts, int video, int preview) { - int64_t diff; - - diff = pts - this->last_pts[video]; + const int64_t diff = pts - this->last_pts[video]; lprintf ("check_newpts %"PRId64"\n", pts); if (!preview && pts && @@ -886,7 +1004,7 @@ static uint32_t real_fix_timestamp (demux_real_t *this, uint8_t *hdr, uint32_t t int pict_type; int seq; uint32_t ts_out; - + switch(this->video_stream->buf_type) { case BUF_VIDEO_RV20: pict_type = (hdr[0] & 0xC0) >> 6; @@ -901,35 +1019,35 @@ static uint32_t real_fix_timestamp (demux_real_t *this, uint8_t *hdr, uint32_t t seq = ((hdr[1] & 0x07) << 10) + (hdr[2] << 2) + ((hdr[3] & 0xC0) >> 6); break; default: - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_real: can't fix timestamp for buf type 0x%08x\n", + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: can't fix timestamp for buf type 0x%08x\n", this->video_stream->buf_type); return ts_in; break; } - + switch (pict_type) { case 0: - case 1: + case 1: /* I frame */ ts_out = this->next_ts; - + this->last_ts = this->next_ts; this->next_ts = ts_in; - + this->last_seq = this->next_seq; this->next_seq = seq; break; case 2: /* P frame */ ts_out = this->next_ts; - + this->last_ts = this->next_ts; if (seq < this->next_seq) this->next_ts += seq + 8192 - this->next_seq; else this->next_ts += seq - this->next_seq; - + this->last_seq = this->next_seq; this->next_seq = seq; break; @@ -946,8 +1064,8 @@ static uint32_t real_fix_timestamp (demux_real_t *this, uint8_t *hdr, uint32_t t ts_out = 0; break; } - - return ts_out; + + return ts_out; } static int stream_read_char (demux_real_t *this) { @@ -966,18 +1084,14 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { demux_real_t *this = (demux_real_t *) this_gen; char header[DATA_PACKET_HEADER_SIZE]; - int stream, size, keyframe, input_time = 0; - unsigned short version; - uint32_t id, timestamp; - int64_t pts; - off_t offset, input_length = 0; + int keyframe, input_time = 0; int normpos = 0; if(this->reference_mode) return demux_real_parse_references(this); - + /* load a header from wherever the stream happens to be pointing */ - if ( (size=this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE)) != + if ( this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE) != DATA_PACKET_HEADER_SIZE) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, @@ -988,29 +1102,28 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { } /* Check to see if we've gone past the end of the data chunk */ - if(((id = _X_BE_32(&header[0])) == DATA_TAG) || - (id == INDX_TAG)) { + if (_x_is_fourcc(&header[0], "INDX") || _x_is_fourcc(&header[0], "DATA")) { lprintf("finished reading data chunk\n"); this->status = DEMUX_FINISHED; return this->status; } /* check version */ - version = _X_BE_16(&header[0]); + const uint16_t version = _X_BE_16(&header[0]); if(version > 1) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: unknown object version in data packet: 0x%04x\n", version); this->status = DEMUX_FINISHED; return this->status; } - + /* read the packet information */ - stream = _X_BE_16(&header[4]); - offset = this->input->get_current_pos(this->input); - size = _X_BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE; - timestamp= _X_BE_32(&header[6]); - pts = (int64_t) timestamp * 90; - + const uint16_t stream = _X_BE_16(&header[4]); + const off_t offset __attr_unused = this->input->get_current_pos(this->input); + uint16_t size = _X_BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE; + const uint32_t timestamp= _X_BE_32(&header[6]); + int64_t pts = (int64_t) timestamp * 90; + /* Data packet header with version 1 contains 1 extra byte */ if(version == 0) keyframe = header[11] & PN_KEYFRAME_FLAG; @@ -1024,11 +1137,9 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { if (this->video_stream && (stream == this->video_stream->mdpr->stream_number)) { - int vpkg_header, vpkg_length, vpkg_offset; int vpkg_seqnum = -1; int vpkg_subseq = 0; buf_element_t *buf; - int n, fragment_size; uint32_t decoder_flags; lprintf ("video chunk detected.\n"); @@ -1043,21 +1154,20 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { * bit 6: 1=short header (only one block?) */ - vpkg_header = stream_read_char (this); size--; + const int vpkg_header = stream_read_char (this); size--; lprintf ("vpkg_hdr: %02x (size=%d)\n", vpkg_header, size); + int vpkg_length, vpkg_offset; if (0x40==(vpkg_header&0xc0)) { /* * seems to be a very short header * 2 bytes, purpose of the second byte yet unknown */ - int bummer; - - bummer = stream_read_char (this); size--; + const int bummer __attr_unused = stream_read_char (this); lprintf ("bummer == %02X\n",bummer); vpkg_offset = 0; - vpkg_length = size; + vpkg_length = --size; } else { @@ -1115,23 +1225,22 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { if(this->video_stream->index) input_time = timestamp; else - input_time = (int)((int64_t) this->input->get_current_pos(this->input) + input_time = (int)((int64_t) this->input->get_current_pos(this->input) * 8 * 1000 / this->avg_bitrate); - if(this->data_start && this->data_chunk_size) - input_length = this->data_start + 18 + this->data_chunk_size; - if( input_length ) + const off_t input_length = this->data_start + 18 + this->data_chunk_size; + if( input_length > 18 ) normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length); - + check_newpts (this, pts, PTS_VIDEO, 0); if (this->fragment_size == 0) { lprintf ("new packet starting\n"); - + /* send fragment offset table */ if(this->fragment_count) { lprintf("sending fragment offset table\n"); - + buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); buf->decoder_flags = BUF_FLAG_SPECIAL | BUF_FLAG_FRAME_END; @@ -1144,18 +1253,18 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { xine_fast_memcpy(buf->decoder_info_ptr[2], this->fragment_tab, this->fragment_count*8); - + this->video_fifo->put(this->video_fifo, buf); - + this->fragment_count = 0; } - + decoder_flags = BUF_FLAG_FRAME_START; } else { lprintf ("continuing packet \n"); decoder_flags = 0; } - + /* add entry to fragment offset table */ this->fragment_tab[2*this->fragment_count] = 1; this->fragment_tab[2*this->fragment_count+1] = this->fragment_size; @@ -1165,46 +1274,47 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { * calc size of fragment */ - if ((vpkg_header & 0xc0) == 0x080) + int fragment_size; + switch(vpkg_header & 0xc0) { + case 0x80: fragment_size = vpkg_offset; - else { - if (0x00 == (vpkg_header&0xc0)) - fragment_size = size; - else - fragment_size = vpkg_length; + break; + case 0x00: + fragment_size = size; + break; + default: + fragment_size = vpkg_length; + break; } lprintf ("fragment size is %d\n", fragment_size); /* * read fragment_size bytes of data */ - - n = fragment_size; + + int n = fragment_size; while(n) { buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); - - if(n>buf->max_size) - buf->size = buf->max_size; - else - buf->size = n; + + buf->size = MIN(n, buf->max_size); buf->decoder_flags = decoder_flags; decoder_flags &= ~BUF_FLAG_FRAME_START; - + buf->type = this->video_stream->buf_type; - + if(this->input->read(this->input, buf->content, buf->size) < buf->size) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: failed to read video fragment"); buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; } - - /* RV30 and RV40 streams contain some fragments that shouldn't be passed - * to the decoder. The purpose of these fragments is unknown, but - * realplayer doesn't appear to pass them to the decoder either */ - if((n == fragment_size) && + + /* RV30 and RV40 streams contain some fragments that shouldn't be passed + * to the decoder. The purpose of these fragments is unknown, but + * realplayer doesn't appear to pass them to the decoder either */ + if((n == fragment_size) && (((buf->type == BUF_VIDEO_RV30) && (buf->content[0] & 0x20)) || ((buf->type == BUF_VIDEO_RV40) && (buf->content[0] & 0x80)))) { lprintf("ignoring fragment\n"); @@ -1216,12 +1326,12 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { break; } - + /* if the video stream has b-frames fix the timestamps */ if((this->video_stream->format >= 0x20200002) && (buf->decoder_flags & BUF_FLAG_FRAME_START)) pts = (int64_t) real_fix_timestamp(this, buf->content, timestamp) * 90; - + /* this test was moved from ffmpeg video decoder. * fixme: is pts only valid on frame start? */ if( buf->decoder_flags & BUF_FLAG_FRAME_START ) @@ -1229,13 +1339,13 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { else buf->pts = 0; pts = 0; - + buf->extra_info->input_normpos = normpos; buf->extra_info->input_time = input_time; buf->extra_info->total_time = this->duration; - + this->video_fifo->put(this->video_fifo, buf); - + n -= buf->size; } @@ -1260,71 +1370,131 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { goto discard; else this->audio_need_keyframe = 0; - + /* if we have a seekable stream then use the timestamp for the data * packet for more accurate seeking - if not then estimate time using * average bitrate */ if(this->audio_stream->index) input_time = timestamp; else - input_time = (int)((int64_t) this->input->get_current_pos(this->input) - * 8 * 1000 / this->avg_bitrate); - - if(this->data_start && this->data_chunk_size) - input_length = this->data_start + 18 + this->data_chunk_size; - else - input_length = 0; - - if( input_length ) + input_time = (int)((int64_t) this->input->get_current_pos(this->input) + * 8 * 1000 / this->avg_bitrate); + + const off_t input_length = this->data_start + 18 + this->data_chunk_size; + + if( input_length > 18 ) normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length); - + check_newpts (this, pts, PTS_AUDIO, 0); - + /* Each packet of AAC is made up of several AAC frames preceded by a * header defining the size of the frames */ if(this->audio_stream->buf_type == BUF_AUDIO_AAC) { - int i, frames, *sizes; - + int i; + /* Upper 4 bits of second byte is frame count */ - frames = (stream_read_word(this) & 0xf0) >> 4; - + const int frames = (stream_read_word(this) & 0xf0) >> 4; + /* 2 bytes per frame size */ - sizes = xine_xmalloc(frames*sizeof(int)); + int sizes[frames]; + for(i = 0; i < frames; i++) sizes[i] = stream_read_word(this); - + for(i = 0; i < frames; i++) { - if(_x_demux_read_send_data(this->audio_fifo, this->input, sizes[i], pts, - this->audio_stream->buf_type, 0, normpos, + if(_x_demux_read_send_data(this->audio_fifo, this->input, sizes[i], pts, + this->audio_stream->buf_type, 0, normpos, input_time, this->duration, 0) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: failed to read AAC frame\n"); - free(sizes); this->status = DEMUX_FINISHED; return this->status; } - + pts = 0; /* Only set pts on first frame */ } - - free(sizes); + } else if (this->audio_stream->buf_type == BUF_AUDIO_COOK || + this->audio_stream->buf_type == BUF_AUDIO_ATRK || + this->audio_stream->buf_type == BUF_AUDIO_28_8 || + this->audio_stream->buf_type == BUF_AUDIO_SIPRO) { + /* reorder */ + uint8_t * buffer = this->audio_stream->frame_buffer; + int sps = this->audio_stream->sps; + int sph = this->audio_stream->h; + int cfs = this->audio_stream->cfs; + int w = this->audio_stream->w; + int spc = this->audio_stream->sub_packet_cnt; + int x; + off_t pos; + const size_t fs = this->audio_stream->frame_size; + + if (!buffer) { + this->status = DEMUX_FINISHED; + return this->status; + } + + switch (this->audio_stream->buf_type) { + case BUF_AUDIO_28_8: + for (x = 0; x < sph / 2; x++) { + pos = x * 2 * w + spc * cfs; + if(pos + cfs > fs || this->input->read(this->input, buffer + pos, cfs) < cfs) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + } + break; + case BUF_AUDIO_COOK: + case BUF_AUDIO_ATRK: + for (x = 0; x < w / sps; x++) { + pos = sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1)); + if(pos + sps > fs || this->input->read(this->input, buffer + pos, sps) < sps) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + } + break; + case BUF_AUDIO_SIPRO: + pos = spc * w; + if(pos + w > fs || this->input->read(this->input, buffer + pos, w) < w) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + if (spc == sph - 1) + demux_real_sipro_swap (buffer, sph * w * 2 / 96); + break; + } + if(++this->audio_stream->sub_packet_cnt == sph) { + this->audio_stream->sub_packet_cnt = 0; + _x_demux_send_data(this->audio_fifo, buffer, this->audio_stream->frame_size, + pts, this->audio_stream->buf_type, 0, normpos, input_time, + this->duration, 0); + } } else { - if(_x_demux_read_send_data(this->audio_fifo, this->input, size, pts, + if(_x_demux_read_send_data(this->audio_fifo, this->input, size, pts, this->audio_stream->buf_type, 0, normpos, input_time, this->duration, 0) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_real: failed to read audio chunk\n"); this->status = DEMUX_FINISHED; return this->status; } - + /* FIXME: dp->flags = (flags & 0x2) ? 0x10 : 0; */ } - + } else { /* discard */ @@ -1342,18 +1512,10 @@ discard: /* check if it's time to reload */ if (!this->current_data_chunk_packet_count && this->next_data_chunk_offset) { - char preamble[PREAMBLE_SIZE]; unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE]; /* seek to the next DATA chunk offset */ - this->input->seek(this->input, this->next_data_chunk_offset, SEEK_SET); - - /* load the DATA chunk preamble */ - if (this->input->read(this->input, preamble, PREAMBLE_SIZE) != - PREAMBLE_SIZE) { - this->status = DEMUX_FINISHED; - return this->status; - } + this->input->seek(this->input, this->next_data_chunk_offset + PREAMBLE_SIZE, SEEK_SET); /* load the rest of the DATA chunk header */ if (this->input->read(this->input, data_chunk_header, @@ -1415,14 +1577,14 @@ static int demux_real_seek (demux_plugin_t *this_gen, demux_real_t *this = (demux_real_t *) this_gen; real_index_entry_t *index, *other_index = NULL; int i = 0, entries; - + lprintf("seek start_pos=%d, start_time=%d, playing=%d\n", (int)start_pos, start_time, playing); if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) && ((this->audio_stream && this->audio_stream->index) || (this->video_stream && this->video_stream->index))) { - + start_pos = (off_t) ( (double) start_pos / 65535 * this->input->get_length (this->input) ); @@ -1459,6 +1621,9 @@ static int demux_real_seek (demux_plugin_t *this_gen, this->input->seek(this->input, index[i].offset, SEEK_SET); if(playing) { + if(this->audio_stream) + this->audio_stream->sub_packet_cnt = 0; + this->buf_flag_seek = 1; _x_demux_flush_engine(this->stream); } @@ -1467,14 +1632,14 @@ static int demux_real_seek (demux_plugin_t *this_gen, /* RTSP supports only time based seek */ if (start_pos && !start_time) start_time = (int64_t) this->duration * start_pos / 65535; - + this->input->seek_time(this->input, start_time, SEEK_SET); } this->send_newpts = 1; this->old_seqnum = -1; this->fragment_size = 0; - + this->next_ts = 0; this->next_seq = 0; @@ -1489,19 +1654,16 @@ static void demux_real_dispose (demux_plugin_t *this_gen) { for(i = 0; i < this->num_video_streams; i++) { real_free_mdpr(this->video_streams[i].mdpr); - if(this->video_streams[i].index) - free(this->video_streams[i].index); + free(this->video_streams[i].index); } - + for(i = 0; i < this->num_audio_streams; i++) { real_free_mdpr(this->audio_streams[i].mdpr); - if(this->audio_streams[i].index) - free(this->audio_streams[i].index); + free(this->audio_streams[i].index); + free(this->audio_streams[i].frame_buffer); } - - if(this->fragment_tab) - free(this->fragment_tab); - + + free(this->fragment_tab); free(this); } @@ -1528,21 +1690,27 @@ static int demux_real_get_optional_data(demux_plugin_t *this_gen, } /* help function to discover stream type. returns: + * -1 if couldn't read * 0 if not known. * 1 if normal stream. * 2 if reference stream. */ -static int real_check_stream_type(uint8_t *buf, int len) +static int real_check_stream_type(input_plugin_t *input) { - if ((buf[0] == 0x2e) - && (buf[1] == 'R') - && (buf[2] == 'M') - && (buf[3] == 'F')) + uint8_t buf[1024]; + off_t len = _x_demux_read_header(input, buf, sizeof(buf)); + + if ( len < 4 ) + return -1; + + if ( memcmp(buf, "\x2eRMF", 4) == 0 ) return 1; - buf[len] = '\0'; - if( strstr(buf,"pnm://") || strstr(buf,"rtsp://") || strstr(buf,"<smil>") || - !strncmp(buf,"http://",7) ) +#define my_strnstr(haystack, haystacklen, needle) \ + memmem(haystack, haystacklen, needle, sizeof(needle)) + + if( my_strnstr(buf, len, "pnm://") || my_strnstr(buf, len, "rtsp://") || + my_strnstr(buf, len, "<smil>") || !strncmp(buf, "http://", MIN(7, len)) ) return 2; return 0; @@ -1551,32 +1719,24 @@ static int real_check_stream_type(uint8_t *buf, int len) static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { - demux_real_t *this; - uint8_t buf[1024+1]; - int len, stream_type=0; - - switch (stream->content_detection_method) { - - case METHOD_BY_CONTENT:{ + /* discover stream type */ + const int stream_type = real_check_stream_type(input); - if (! (len = _x_demux_read_header(input, buf, 1024)) ) - return NULL; + if ( stream_type < 0 ) + return NULL; - lprintf ("read 4 bytes: %02x %02x %02x %02x\n", - buf[0], buf[1], buf[2], buf[3]); + switch (stream->content_detection_method) { - if (!(stream_type = real_check_stream_type(buf,len))) + case METHOD_BY_CONTENT: + if ( stream_type < 1 ) return NULL; - } - lprintf ("by content accepted.\n"); - break; + lprintf ("by content accepted.\n"); + break; case METHOD_BY_EXTENSION: { - const char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); + const char *const mrl = input->get_mrl (input); + const char *const extensions = class_gen->get_extensions (class_gen); lprintf ("by extension '%s'\n", mrl); @@ -1595,17 +1755,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - - this = xine_xmalloc (sizeof (demux_real_t)); + demux_real_t *this = calloc(1, sizeof(demux_real_t)); this->stream = stream; this->input = input; - /* discover stream type */ - if(!stream_type) - if ( (len = _x_demux_read_header(this->input, buf, 1024)) ) - stream_type = real_check_stream_type(buf,len); - if(stream_type == 2){ this->reference_mode = 1; lprintf("reference stream detected\n"); @@ -1642,7 +1796,7 @@ static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-pn-realaudio: ra, rm, ram: Real Media file;" "audio/x-pn-realaudio-plugin: rpm: Real Media plugin file;" "audio/x-real-audio: ra, rm, ram: Real Media file;" - "application/vnd.rn-realmedia: ra, rm, ram: Real Media file;"; + "application/vnd.rn-realmedia: ra, rm, ram: Real Media file;"; } static void class_dispose (demux_class_t *this_gen) { @@ -1652,9 +1806,7 @@ static void class_dispose (demux_class_t *this_gen) { } static void *init_class (xine_t *xine, void *data) { - demux_real_class_t *this; - - this = xine_xmalloc (sizeof (demux_real_class_t)); + demux_real_class_t *const this = calloc(1, sizeof(demux_real_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index 70c9b310a..3c18f7ec3 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -41,6 +41,8 @@ #include "bswap.h" #include "group_audio.h" +#include "real_common.h" + #define RA_FILE_HEADER_PREV_SIZE 22 typedef struct { @@ -61,7 +63,13 @@ typedef struct { off_t data_start; off_t data_size; - + + uint32_t cfs; + uint16_t w, h; + int frame_len; + size_t frame_size; + uint8_t *frame_buffer; + unsigned char *header; unsigned int header_size; } demux_ra_t; @@ -70,26 +78,24 @@ typedef struct { demux_class_t demux_class; } demux_ra_class_t; +/* Map flavour to bytes per second */ +static const int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second + /* returns 1 if the RealAudio file was opened successfully, 0 otherwise */ static int open_ra_file(demux_ra_t *this) { - unsigned char file_header[RA_FILE_HEADER_PREV_SIZE], len; - unsigned short version; - off_t offset; - + uint8_t file_header[RA_FILE_HEADER_PREV_SIZE]; /* check the signature */ if (_x_demux_read_header(this->input, file_header, RA_FILE_HEADER_PREV_SIZE) != RA_FILE_HEADER_PREV_SIZE) return 0; - if ((file_header[0] != '.') || - (file_header[1] != 'r') || - (file_header[2] != 'a')) + if ( memcmp(file_header, ".ra", 3) != 0 ) return 0; /* read version */ - version = _X_BE_16(&file_header[0x04]); - + const uint16_t version = _X_BE_16(&file_header[0x04]); + /* read header size according to version */ if (version == 3) this->header_size = _X_BE_16(&file_header[0x06]) + 8; @@ -99,86 +105,121 @@ static int open_ra_file(demux_ra_t *this) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unknown version number %d\n", version); return 0; } - + /* allocate for and read header data */ - this->header = xine_xmalloc(this->header_size); - - if (_x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) { + this->header = malloc(this->header_size); + + if (!this->header || _x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unable to read header\n"); free(this->header); return 0; } - + + off_t offset; /* read header data according to version */ if((version == 3) && (this->header_size >= 32)) { this->data_size = _X_BE_32(&this->header[0x12]); - + this->block_align = 240; - + offset = 0x16; } else if(this->header_size >= 72) { - this->data_size = _X_BE_32(&this->header[0x1C]); - + this->data_size = _X_BE_32(&this->header[0x1C]); + this->block_align = _X_BE_16(&this->header[0x2A]); - + if(this->header[0x3D] == 4) this->fourcc = _X_ME_32(&this->header[0x3E]); else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: invalid fourcc size %d\n", this->header[0x3D]); free(this->header); return 0; } - + offset = 0x45; } else { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: header too small\n"); free(this->header); return 0; } - + /* Read title */ - len = this->header[offset]; - if(len && ((offset+len+2) < this->header_size)) { - _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE, - &this->header[offset+1], len); - offset += len+1; - } else - offset++; - + { + const uint8_t len = this->header[offset]; + if(len && ((offset+len+2) < this->header_size)) { + _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE, + &this->header[offset+1], len); + offset += len+1; + } else + offset++; + } + /* Author */ - len = this->header[offset]; - if(len && ((offset+len+1) < this->header_size)) { - _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST, - &this->header[offset+1], len); - offset += len+1; - } else - offset++; - + { + const uint8_t len = this->header[offset]; + if(len && ((offset+len+1) < this->header_size)) { + _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST, + &this->header[offset+1], len); + offset += len+1; + } else + offset++; + } + /* Copyright/Date */ - len = this->header[offset]; - if(len && ((offset+len) <= this->header_size)) { - _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR, - &this->header[offset+1], len); - offset += len+1; - } else - offset++; - + { + const uint8_t len = this->header[offset]; + if(len && ((offset+len) <= this->header_size)) { + _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR, + &this->header[offset+1], len); + offset += len+1; + } else + offset++; + } + /* Fourcc for version 3 comes after meta info */ - if((version == 3) && ((offset+7) <= this->header_size)) { - if(this->header[offset+2] == 4) - this->fourcc = _X_ME_32(&this->header[offset+3]); - else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]); - free(this->header); - return 0; + if(version == 3) { + if (((offset+7) <= this->header_size)) { + if(this->header[offset+2] == 4) + this->fourcc = _X_ME_32(&this->header[offset+3]); + else { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]); + free(this->header); + return 0; + } + } else { + this->fourcc = ME_FOURCC('l', 'p', 'c', 'J'); } } - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->fourcc); this->audio_type = _x_formattag_to_buf_audio(this->fourcc); + if (version == 4) { + const uint16_t sps = _X_BE_16 (this->header+44) ? : 1; + this->w = _X_BE_16 (this->header+42); + this->h = _X_BE_16 (this->header+40); + this->cfs = _X_BE_32 (this->header+24); + + if (this->w < 0x8000 && this->h < 0x8000) { + uint64_t fs; + this->frame_len = this->w * this->h; + fs = (uint64_t) this->frame_len * sps; + if (fs < 0x80000000) { + this->frame_size = fs; + this->frame_buffer = calloc(this->frame_size, 1); + } + } + if (! this->frame_buffer) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: malloc failed\n"); + return 0; + } + + if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) + this->block_align = this->cfs; + } + /* seek to start of data */ this->data_start = this->header_size; if (this->input->seek(this->input, this->data_start, SEEK_SET) != @@ -197,27 +238,57 @@ static int demux_ra_send_chunk(demux_plugin_t *this_gen) { demux_ra_t *this = (demux_ra_t *) this_gen; off_t current_normpos = 0; - int64_t current_pts; /* just load data chunks from wherever the stream happens to be * pointing; issue a DEMUX_FINISHED status if EOF is reached */ if( this->input->get_length (this->input) ) - current_normpos = (int)( (double) (this->input->get_current_pos (this->input) - this->data_start) * + current_normpos = (int)( (double) (this->input->get_current_pos (this->input) - this->data_start) * 65535 / this->data_size ); - current_pts = 0; /* let the engine sort out the pts for now */ + const int64_t current_pts = 0; /* let the engine sort out the pts for now */ if (this->seek_flag) { _x_demux_control_newpts(this->stream, current_pts, BUF_FLAG_SEEK); this->seek_flag = 0; } - if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align, - current_pts, this->audio_type, 0, current_normpos, + if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) { + if (this->audio_type == BUF_AUDIO_SIPRO) { + if(this->input->read(this->input, this->frame_buffer, this->frame_len) < this->frame_len) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_realaudio: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + demux_real_sipro_swap (this->frame_buffer, this->frame_len * 2 / 96); + } else { + int x, y; + + for (y = 0; y < this->h; y++) + for (x = 0; x < this->h / 2; x++) { + const int pos = x * 2 * this->w + y * this->cfs; + if(this->input->read(this->input, this->frame_buffer + pos, + this->cfs) < this->cfs) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_realaudio: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + } + } + + _x_demux_send_data(this->audio_fifo, + this->frame_buffer, this->frame_size, + current_pts, this->audio_type, 0, + current_normpos, current_pts / 90, 0, 0); + } else if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align, + current_pts, this->audio_type, 0, current_normpos, current_pts / 90, 0, 0) < 0) { - this->status = DEMUX_FINISHED; + this->status = DEMUX_FINISHED; } - + return this->status; } @@ -243,12 +314,9 @@ static void demux_ra_send_headers(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = this->audio_type; buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END; - - if(this->header_size > buf->max_size) - buf->size = buf->max_size; - else - buf->size = this->header_size; - + + buf->size = MIN(this->header_size, buf->max_size); + memcpy(buf->content, this->header, buf->size); this->audio_fifo->put (this->audio_fifo, buf); @@ -296,9 +364,11 @@ static int demux_ra_seek (demux_plugin_t *this_gen, static void demux_ra_dispose (demux_plugin_t *this_gen) { demux_ra_t *this = (demux_ra_t *) this_gen; - + if(this->header) free(this->header); + if (this->frame_buffer) + free(this->frame_buffer); free(this); } @@ -311,8 +381,6 @@ static int demux_ra_get_status (demux_plugin_t *this_gen) { /* return the approximate length in miliseconds */ static int demux_ra_get_stream_length (demux_plugin_t *this_gen) { - demux_ra_t *this = (demux_ra_t *) this_gen; - return 0; } @@ -330,9 +398,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_ra_t *this; - this = xine_xmalloc (sizeof (demux_ra_t)); + this = calloc(1, sizeof(demux_ra_t)); this->stream = stream; this->input = input; + this->frame_buffer = NULL; this->demux_plugin.send_headers = demux_ra_send_headers; this->demux_plugin.send_chunk = demux_ra_send_chunk; @@ -370,7 +439,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str } break; - + default: free (this); return NULL; @@ -404,7 +473,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_realaudio_init_plugin (xine_t *xine, void *data) { demux_ra_class_t *this; - this = xine_xmalloc (sizeof (demux_ra_class_t)); + this = calloc(1, sizeof(demux_ra_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c index 18edaea87..346d487aa 100644 --- a/src/demuxers/demux_roq.c +++ b/src/demuxers/demux_roq.c @@ -47,7 +47,6 @@ #include "bswap.h" #include "group_games.h" -#define RoQ_MAGIC_NUMBER 0x1084 #define RoQ_CHUNK_PREAMBLE_SIZE 8 #define RoQ_AUDIO_SAMPLE_RATE 22050 @@ -93,10 +92,11 @@ static int open_roq_file(demux_roq_t *this) { return 0; /* check for the RoQ magic numbers */ - if ((_X_LE_16(&preamble[0]) != RoQ_MAGIC_NUMBER) || - (_X_LE_32(&preamble[2]) != 0xFFFFFFFF)) + static const uint8_t RoQ_MAGIC_STRING[] = + { 0x10, 0x84, 0xFF, 0xFF, 0xFF, 0xFF }; + if( memcmp(preamble, RoQ_MAGIC_STRING, sizeof(RoQ_MAGIC_STRING)) != 0 ) return 0; - + this->bih.biSize = sizeof(xine_bmiheader); this->bih.biWidth = this->bih.biHeight = 0; this->wave.nChannels = 0; /* assume no audio at first */ @@ -119,7 +119,7 @@ static int open_roq_file(demux_roq_t *this) { while (i-- > 0) { /* if this read fails, then maybe it's just a really small RoQ file * (even less than 2 seconds) */ - if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != + if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) break; chunk_type = _X_LE_16(&preamble[0]); @@ -181,7 +181,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) { off_t current_file_pos; /* fetch the next preamble */ - if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != + if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != RoQ_CHUNK_PREAMBLE_SIZE) { this->status = DEMUX_FINISHED; return this->status; @@ -193,21 +193,21 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) { if ((chunk_type == RoQ_SOUND_MONO) || (chunk_type == RoQ_SOUND_STEREO)) { if( this->audio_fifo ) { - + /* do this calculation carefully because I can't trust the * 64-bit numerical manipulation */ audio_pts = this->audio_byte_count; audio_pts *= 90000; audio_pts /= (RoQ_AUDIO_SAMPLE_RATE * this->wave.nChannels); this->audio_byte_count += chunk_size - 8; /* do not count the preamble */ - + current_file_pos = this->input->get_current_pos(this->input); /* send out the preamble */ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_ROQ; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) * + buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) * 65535 / this->input->get_length (this->input) ); buf->pts = 0; buf->size = RoQ_CHUNK_PREAMBLE_SIZE; @@ -219,7 +219,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_ROQ; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) current_file_pos * + buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->input->get_length (this->input) ); buf->pts = audio_pts; @@ -256,7 +256,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_ROQ; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) * + buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) * 65535 / this->input->get_length (this->input) ); buf->pts = this->video_pts_counter; buf->size = RoQ_CHUNK_PREAMBLE_SIZE; @@ -267,7 +267,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_VIDEO_ROQ; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) current_file_pos * + buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->input->get_length (this->input) ); buf->pts = this->video_pts_counter; @@ -411,7 +411,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_roq_t)); + this = calloc(1, sizeof(demux_roq_t)); this->stream = stream; this->input = input; @@ -485,7 +485,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_roq_init_plugin (xine_t *xine, void *data) { demux_roq_class_t *this; - this = xine_xmalloc (sizeof (demux_roq_class_t)); + this = calloc(1, sizeof(demux_roq_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_shn.c b/src/demuxers/demux_shn.c index 87324ab45..b4f7c764b 100644 --- a/src/demuxers/demux_shn.c +++ b/src/demuxers/demux_shn.c @@ -83,16 +83,16 @@ static int demux_shn_send_chunk(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_SHORTEN; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); buf->pts = 0; bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; - } else + } else buf->size = bytes_read; /* each buffer stands on its own */ @@ -182,7 +182,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_shn_t *this; - this = xine_xmalloc (sizeof (demux_shn_t)); + this = calloc(1, sizeof(demux_shn_t)); this->stream = stream; this->input = input; @@ -253,7 +253,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_shn_init_plugin (xine_t *xine, void *data) { demux_shn_class_t *this; - this = xine_xmalloc (sizeof (demux_shn_class_t)); + this = calloc(1, sizeof(demux_shn_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_slave.c b/src/demuxers/demux_slave.c index 436d37579..de530f224 100644 --- a/src/demuxers/demux_slave.c +++ b/src/demuxers/demux_slave.c @@ -2,19 +2,19 @@ * Copyright (C) 2000-2003 the xine project * May 2003 - Miguel Freitas * This plugin was sponsored by 1Control - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -51,7 +51,7 @@ #define CHECK_VPTS_INTERVAL 2*90000 #define NETWORK_PREBUFFER 90000 -typedef struct { +typedef struct { demux_plugin_t demux_plugin; xine_stream_t *stream; @@ -86,14 +86,15 @@ static int demux_slave_next (demux_slave_t *this) { char fifo_name[11]; uint8_t *p, *s; int64_t curvpts; - + /* fill the scratch buffer */ n = this->input->read(this->input, &this->scratch[this->scratch_used], SCRATCH_SIZE - this->scratch_used); - this->scratch_used += n; + if (n > 0) + this->scratch_used += n; this->scratch[this->scratch_used] = '\0'; - if( !n ) { + if (n <= 0) { lprintf("connection closed\n"); this->status = DEMUX_FINISHED; return 0; @@ -186,10 +187,8 @@ static int demux_slave_next (demux_slave_t *this) { buf->decoder_flags = decoder_flags; /* set decoder info */ - for( i = 0; i < BUF_NUM_DEC_INFO; i++ ) { - buf->decoder_info[i] = this->decoder_info[i]; - buf->decoder_info_ptr[i] = this->decoder_info_ptr[i]; - } + memcpy(buf->decoder_info, this->decoder_info, sizeof(this->decoder_info)); + memcpy(buf->decoder_info_ptr, this->decoder_info_ptr, sizeof(this->decoder_info)); memset(this->decoder_info, 0, sizeof(this->decoder_info)); memset(this->decoder_info_ptr, 0, sizeof(this->decoder_info_ptr)); @@ -331,7 +330,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_slave_t *this; static char slave_id_str[] = "master xine v1\n"; - this = xine_xmalloc (sizeof (demux_slave_t)); + this = calloc(1, sizeof(demux_slave_t)); switch (stream->content_detection_method) { @@ -414,7 +413,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_slave_class_t *this; - this = xine_xmalloc (sizeof (demux_slave_class_t)); + this = calloc(1, sizeof(demux_slave_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; @@ -434,7 +433,7 @@ static const demuxer_info_t demux_info_slave = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "slave", XINE_VERSION_CODE, &demux_info_slave, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_smjpeg.c b/src/demuxers/demux_smjpeg.c index 899fbf7e3..04a46fa78 100644 --- a/src/demuxers/demux_smjpeg.c +++ b/src/demuxers/demux_smjpeg.c @@ -55,7 +55,6 @@ #define vidD_TAG FOURCC_TAG('v', 'i', 'd', 'D') #define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M') -#define SMJPEG_SIGNATURE_SIZE 8 /* 16 is the max size of a header chunk (the video header) */ #define SMJPEG_VIDEO_HEADER_SIZE 16 #define SMJPEG_AUDIO_HEADER_SIZE 12 @@ -98,27 +97,22 @@ static int open_smjpeg_file(demux_smjpeg_t *this) { unsigned char header_chunk[SMJPEG_HEADER_CHUNK_MAX_SIZE]; unsigned int audio_codec = 0; - if (_x_demux_read_header(this->input, signature, SMJPEG_SIGNATURE_SIZE) != - SMJPEG_SIGNATURE_SIZE) + static const uint8_t SMJPEG_SIGNATURE[8] = + { 0x00, 0x0A, 'S', 'M', 'J', 'P', 'E', 'G' }; + + if (_x_demux_read_header(this->input, signature, sizeof(SMJPEG_SIGNATURE)) != + sizeof(SMJPEG_SIGNATURE)) return 0; - /* check for the SMJPEG signature */ - if ((signature[0] != 0x00) || - (signature[1] != 0x0A) || - (signature[2] != 'S') || - (signature[3] != 'M') || - (signature[4] != 'J') || - (signature[5] != 'P') || - (signature[6] != 'E') || - (signature[7] != 'G')) + if (memcmp(signature, SMJPEG_SIGNATURE, sizeof(SMJPEG_SIGNATURE)) != 0) return 0; /* file is qualified; jump over the header + version to the duration */ - this->input->seek(this->input, SMJPEG_SIGNATURE_SIZE + 4, SEEK_SET); + this->input->seek(this->input, sizeof(SMJPEG_SIGNATURE) + 4, SEEK_SET); if (this->input->read(this->input, header_chunk, 4) != 4) return 0; this->duration = _X_BE_32(&header_chunk[0]); - + /* initial state: no video and no audio (until headers found) */ this->video_type = this->audio_type = 0; this->input_length = this->input->get_length (this->input); @@ -400,7 +394,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_smjpeg_t)); + this = calloc(1, sizeof(demux_smjpeg_t)); this->stream = stream; this->input = input; @@ -474,7 +468,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_smjpeg_init_plugin (xine_t *xine, void *data) { demux_smjpeg_class_t *this; - this = xine_xmalloc (sizeof (demux_smjpeg_class_t)); + this = calloc(1, sizeof(demux_smjpeg_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_snd.c b/src/demuxers/demux_snd.c index 0965a75ae..66e2bd543 100644 --- a/src/demuxers/demux_snd.c +++ b/src/demuxers/demux_snd.c @@ -42,8 +42,6 @@ #define SND_HEADER_SIZE 24 #define PCM_BLOCK_ALIGN 1024 -/* this is the big-endian hex value '.snd' */ -#define snd_TAG 0x2E736E64 typedef struct { demux_plugin_t demux_plugin; @@ -83,7 +81,7 @@ static int open_snd_file(demux_snd_t *this) { return 0; /* check the signature */ - if (_X_BE_32(&header[0]) != snd_TAG) + if ( !_x_is_fourcc(&header[0], ".snd") ) return 0; /* file is qualified; skip over the header bytes in the stream */ @@ -112,11 +110,11 @@ static int open_snd_file(demux_snd_t *this) { this->audio_bytes_per_second = this->audio_channels * this->audio_sample_rate; break; - + case 2: this->audio_type = BUF_AUDIO_LPCM_BE; this->audio_bits = 8; - this->audio_frames = this->data_size / + this->audio_frames = this->data_size / (this->audio_channels * this->audio_bits / 8); this->audio_block_align = PCM_BLOCK_ALIGN; this->audio_bytes_per_second = this->audio_channels * @@ -126,7 +124,7 @@ static int open_snd_file(demux_snd_t *this) { case 3: this->audio_type = BUF_AUDIO_LPCM_BE; this->audio_bits = 16; - this->audio_frames = this->data_size / + this->audio_frames = this->data_size / (this->audio_channels * this->audio_bits / 8); this->audio_block_align = PCM_BLOCK_ALIGN; this->audio_bytes_per_second = this->audio_channels * @@ -165,7 +163,7 @@ static int demux_snd_send_chunk(demux_plugin_t *this_gen) { /* just load data chunks from wherever the stream happens to be * pointing; issue a DEMUX_FINISHED status if EOF is reached */ remaining_sample_bytes = this->audio_block_align; - current_file_pos = + current_file_pos = this->input->get_current_pos(this->input) - this->data_start; current_pts = current_file_pos; @@ -207,7 +205,7 @@ static int demux_snd_send_chunk(demux_plugin_t *this_gen) { for (i = 0; i < buf->size; i++) buf->content[i] += 0x80; } - + this->audio_fifo->put (this->audio_fifo, buf); } return this->status; @@ -253,11 +251,11 @@ static int demux_snd_seek (demux_plugin_t *this_gen, off_t start_pos, int start_ demux_snd_t *this = (demux_snd_t *) this_gen; start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); - + this->seek_flag = 1; this->status = DEMUX_OK; _x_demux_flush_engine (this->stream); - + /* if input is non-seekable, do not proceed with the rest of this * seek function */ if (!INPUT_IS_SEEKABLE(this->input)) @@ -318,7 +316,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_snd_t *this; - this = xine_xmalloc (sizeof (demux_snd_t)); + this = calloc(1, sizeof(demux_snd_t)); this->stream = stream; this->input = input; @@ -348,7 +346,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str } } /* falling through is intended */ - + case METHOD_BY_CONTENT: case METHOD_EXPLICIT: @@ -382,7 +380,7 @@ static const char *get_extensions (demux_class_t *this_gen) { static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/basic: snd,au: ULAW (Sun) audio;" "audio/x-basic: snd,au: ULAW (Sun) audio;" - "audio/x-pn-au: snd,au: ULAW (Sun) audio;"; + "audio/x-pn-au: snd,au: ULAW (Sun) audio;"; } @@ -395,7 +393,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_snd_init_plugin (xine_t *xine, void *data) { demux_snd_class_t *this; - this = xine_xmalloc (sizeof (demux_snd_class_t)); + this = calloc(1, sizeof(demux_snd_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_str.c b/src/demuxers/demux_str.c index 2cf542014..d88432817 100644 --- a/src/demuxers/demux_str.c +++ b/src/demuxers/demux_str.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2003 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -102,7 +102,7 @@ * - then follows 16-bit RLE data until the EOD * - RLE format: bits 15-10: # of 0s preceding this value (unsigned) * bits 9-0: this value (signed) - * - e.g. 3 bytes (2,10)(0,20)(3,30) -> 0 0 10 20 0 0 0 30 + * - e.g. 3 bytes (2,10)(0,20)(3,30) -> 0 0 10 20 0 0 0 30 * - 16 bits: EOD (0xFE00) * - 16 bits: 0xFE00 end-of-data footer */ @@ -139,20 +139,15 @@ #define CD_RAW_SECTOR_SIZE 2352 +#define STR_MAGIC "\x60\x01\x01\x80" #define STR_MAX_CHANNELS 32 -#define STR_MAGIC (0x80010160) - #define CDXA_TYPE_MASK 0x0E #define CDXA_TYPE_DATA 0x08 #define CDXA_TYPE_AUDIO 0x04 #define CDXA_TYPE_VIDEO 0x02 #define CDXA_SUBMODE_EOF 0x80 /* set if EOF */ -#define FOURCC_TAG BE_FOURCC -#define RIFF_TAG FOURCC_TAG('R', 'I', 'F', 'F') -#define CDXA_TAG FOURCC_TAG('C', 'D', 'X', 'A') - /* FIXME */ #define FRAME_DURATION 45000 @@ -188,9 +183,7 @@ static int open_str_file(demux_str_t *this) { unsigned char check_bytes[STR_CHECK_BYTES]; int local_offset, sector, channel; - for (channel = 0; channel < STR_MAX_CHANNELS; channel++) { - this->channel_type[channel] = 0; - } + memset(this->channel_type, 0, sizeof(this->channel_type)); this->input->seek(this->input, 0, SEEK_SET); if (this->input->read(this->input, check_bytes, STR_CHECK_BYTES) != @@ -200,8 +193,8 @@ static int open_str_file(demux_str_t *this) { } /* check for STR with a RIFF header */ - if ((_X_BE_32(&check_bytes[0]) == RIFF_TAG) && - (_X_BE_32(&check_bytes[8]) == CDXA_TAG)) + if ( _x_is_fourcc(&check_bytes[0], "RIFF") && + _x_is_fourcc(&check_bytes[8], "CDXA") ) local_offset = 0x2C; else local_offset = 0; @@ -218,16 +211,20 @@ static int open_str_file(demux_str_t *this) { check_bytes[local_offset + 0x13]); /* check for 12-byte sync marker */ - if ((_X_BE_32(&check_bytes[local_offset + 0]) != 0x00FFFFFF) || - (_X_BE_32(&check_bytes[local_offset + 4]) != 0xFFFFFFFF) || - (_X_BE_32(&check_bytes[local_offset + 8]) != 0xFFFFFF00)) { + static const uint8_t sync_marker[12] = + { 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0X00 + }; + if ( memcmp(&check_bytes[local_offset], + sync_marker, sizeof(sync_marker)) != 0 ) { lprintf("sector %d sync error\n", sector); return 0; } /* the 32 bits starting at 0x10 and at 0x14 should be the same */ - if (_X_BE_32(&check_bytes[local_offset + 0x10]) != - _X_BE_32(&check_bytes[local_offset + 0x14])) { + if (memcmp(&check_bytes[local_offset + 0x10], + &check_bytes[local_offset + 0x14], 4) != 0) { lprintf("sector %d control bits copy error\n", sector); return 0; } @@ -246,7 +243,7 @@ static int open_str_file(demux_str_t *this) { case CDXA_TYPE_VIDEO: /* first time we have seen video/data in this channel? */ if ((!(this->channel_type[channel] & CDXA_TYPE_DATA)) && - (_X_LE_32(&check_bytes[local_offset + 0x18]) == STR_MAGIC)) { + (_x_is_fourcc(&check_bytes[local_offset + 0x18], STR_MAGIC))) { /* mark this channel as having video data */ this->channel_type[channel] |= CDXA_TYPE_VIDEO; @@ -347,7 +344,7 @@ static int demux_str_send_chunk(demux_plugin_t *this_gen) { case CDXA_TYPE_DATA: /* video chunk */ - if (_X_LE_32(§or[0x18]) != STR_MAGIC || + if (!_x_is_fourcc(§or[0x18], STR_MAGIC) || channel != this->default_video_channel) { return 0; } @@ -370,7 +367,7 @@ static int demux_str_send_chunk(demux_plugin_t *this_gen) { */ if( this->data_size ) - buf->extra_info->input_normpos = (int)( (double) current_pos * + buf->extra_info->input_normpos = (int)( (double) current_pos * 65535 / this->data_size ); buf->extra_info->input_time = (current_pos*1000)/(CD_RAW_SECTOR_SIZE*75); @@ -408,7 +405,7 @@ static int demux_str_send_chunk(demux_plugin_t *this_gen) { } if( this->data_size ) - buf->extra_info->input_normpos = (int)( (double) current_pos * + buf->extra_info->input_normpos = (int)( (double) current_pos * 65535 / this->data_size ); buf->extra_info->input_time = (current_pos*1000)/(CD_RAW_SECTOR_SIZE*75); @@ -532,7 +529,7 @@ static int demux_str_get_status (demux_plugin_t *this_gen) { static int demux_str_get_stream_length (demux_plugin_t *this_gen) { demux_str_t *this = (demux_str_t *) this_gen; - return (int)((int64_t) this->input->get_length(this->input) + return (int)((int64_t) this->input->get_length(this->input) * 1000 / (CD_RAW_SECTOR_SIZE * 75)); } @@ -555,7 +552,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_str_t)); + this = calloc(1, sizeof(demux_str_t)); this->stream = stream; this->input = input; @@ -578,7 +575,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); - + if (!_x_demux_check_extension (mrl, extensions)) { free (this); return NULL; @@ -628,7 +625,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_str_init_plugin (xine_t *xine, void *data) { demux_str_class_t *this; - this = xine_xmalloc (sizeof (demux_str_class_t)); + this = calloc(1, sizeof(demux_str_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index 86a14f019..1a19340f3 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -1,3 +1,4 @@ + /* * Copyright (C) 2000-2003 the xine project * @@ -33,8 +34,13 @@ * Date Author * ---- ------ * + * 8-Apr-2009 Petri Hintukainen <phi@sdf-eu.org> + * - support for 192-byte packets (HDMV/BluRay) + * - support for audio inside PES PID 0xfd (HDMV/BluRay) + * - demux HDMV/BluRay bitmap subtitles + * * 28-Nov-2004 Mike Lampard <mlampard> - * - Added support for PMT sections larger than 1 ts packet + * - Added support for PMT sections larger than 1 ts packet * * 28-Aug-2004 James Courtier-Dutton <jcdutton> * - Improve PAT and PMT handling. Added some FIXME comments. @@ -52,7 +58,7 @@ * - dynamic allocation leaks fixes * * 27-May-2002 Giovanni Baronetti and Mauro Borghi <mauro.borghi@tilab.com> - * - fill buffers before putting them in fifos + * - fill buffers before putting them in fifos * - force PMT reparsing when PMT PID changes * - accept non seekable input plugins -- FIX? * - accept dvb as input plugin @@ -167,14 +173,14 @@ #define PKT_SIZE 188 #define BODY_SIZE (188 - 4) /* more PIDS are needed due "auto-detection". 40 spare media entries */ -#define MAX_PIDS ((BODY_SIZE - 1 - 13) / 4) + 40 +#define MAX_PIDS ((BODY_SIZE - 1 - 13) / 4) + 40 #define MAX_PMTS ((BODY_SIZE - 1 - 13) / 4) + 10 #define SYNC_BYTE 0x47 #define MIN_SYNCS 3 -#define NPKT_PER_READ 100 +#define NPKT_PER_READ 96 // 96*188 = 94*192 -#define BUF_SIZE (NPKT_PER_READ * PKT_SIZE) +#define BUF_SIZE (NPKT_PER_READ * (PKT_SIZE + 4)) #define MAX_PES_BUF_SIZE 2048 @@ -185,9 +191,6 @@ #define INVALID_PROGRAM ((unsigned int)(-1)) #define INVALID_CC ((unsigned int)(-1)) -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define MAX(a,b) (((a)>(b))?(a):(b)) - #define PROG_STREAM_MAP 0xBC #define PRIVATE_STREAM1 0xBD #define PADDING_STREAM 0xBE @@ -220,7 +223,23 @@ ISO_13818_PART7_AUDIO = 0x0f, /* ISO/IEC 13818-7 Audio with ADTS transport sytax */ ISO_14496_PART2_VIDEO = 0x10, /* ISO/IEC 14496-2 Visual (MPEG-4) */ ISO_14496_PART3_AUDIO = 0x11, /* ISO/IEC 14496-3 Audio with LATM transport syntax */ - ISO_14496_PART10_VIDEO = 0x1b /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ + ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */ + STREAM_VIDEO_MPEG = 0x80, + STREAM_AUDIO_AC3 = 0x81, + + STREAM_VIDEO_VC1 = 0xea, /* VC-1 Video */ + + HDMV_AUDIO_80_PCM = 0x80, /* BluRay PCM */ + HDMV_AUDIO_82_DTS = 0x82, /* DTS */ + HDMV_AUDIO_83_TRUEHD = 0x83, /* Dolby TrueHD, primary audio */ + HDMV_AUDIO_84_EAC3 = 0x84, /* Dolby Digital plus, primary audio */ + HDMV_AUDIO_85_DTS_HRA = 0x85, /* DTS-HRA */ + HDMV_AUDIO_86_DTS_HD_MA = 0x86, /* DTS-HD Master audio */ + + HDMV_SPU_BITMAP = 0x90, + HDMV_SPU_INTERACTIVE = 0x91, + HDMV_SPU_TEXT = 0x92, + } streamType; #define WRAP_THRESHOLD 270000 @@ -228,6 +247,11 @@ #define PTS_AUDIO 0 #define PTS_VIDEO 1 +#undef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#undef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) + /* ** ** DATA STRUCTURES @@ -246,24 +270,25 @@ typedef struct { int64_t pts; buf_element_t *buf; unsigned int counter; - uint8_t descriptor_tag; + uint16_t descriptor_tag; /* +0x100 for PES stream IDs (no available TS descriptor tag?) */ int64_t packet_count; int corrupted_pes; uint32_t buffered_bytes; + int autodetected; } demux_ts_media; /* DVBSUB */ -#define MAX_SPU_LANGS 16 +#define MAX_SPU_LANGS 32 typedef struct { spu_dvb_descriptor_t desc; int pid; int media_index; } demux_ts_spu_lang; - + /* Audio Channels */ -#define MAX_AUDIO_TRACKS 16 +#define MAX_AUDIO_TRACKS 32 typedef struct { int pid; @@ -288,6 +313,10 @@ typedef struct { int status; + int hdmv; /* -1 = unknown, 0 = mpeg-ts, 1 = hdmv/m2ts */ + int pkt_size; /* TS packet size */ + int pkt_offset; /* TS packet offset */ + int blockSize; int rate; int media_num; @@ -309,10 +338,10 @@ typedef struct { unsigned int pid_count; unsigned int videoPid; unsigned int videoMedia; - + demux_ts_audio_track audio_tracks[MAX_AUDIO_TRACKS]; int audio_tracks_count; - + int send_end_buffers; int64_t last_pts[2]; int send_newpts; @@ -340,7 +369,7 @@ typedef struct { int32_t npkt_read; uint8_t buf[BUF_SIZE]; /* == PKT_SIZE * NPKT_PER_READ */ - + int numPreview; } demux_ts_t; @@ -368,7 +397,7 @@ static void demux_ts_build_crc32_table(demux_ts_t*this) { } } -static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data, +static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data, int32_t length, uint32_t crc32) { int32_t i; @@ -413,7 +442,7 @@ static void check_newpts( demux_ts_t *this, int64_t pts, int video ) The original code worked well when the wrap happend like this: V7 A7 V8 V9 A9 Dv V0 V1 da A1 V2 V3 A3 V4 - + Legend: Vn = video packet with timestamp n An = audio packet with timestamp n @@ -431,27 +460,27 @@ static void check_newpts( demux_ts_t *this, int64_t pts, int video ) a delay of almoust 26.5 hours! The new code gives the following sequences for the above examples: - + V7 A7 V8 V9 A9 Dv V0 V1 A1 V2 V3 A3 V4 V7 V8 A7 V9 Dv V0 Da A9 Dv V1 V2 A1 V3 V4 A3 After proving this code it should be cleaned up to use just a single variable "last_pts". */ - + /* this->last_pts[video] = pts; -*/ +*/ this->last_pts[video] = this->last_pts[1-video] = pts; } } /* Send a BUF_SPU_DVB to let xine know of that channel. */ -static void demux_send_special_spu_buf( demux_ts_t *this, int spu_channel ) +static void demux_send_special_spu_buf( demux_ts_t *this, uint32_t spu_type, int spu_channel ) { buf_element_t *buf; buf = this->video_fifo->buffer_pool_alloc( this->video_fifo ); - buf->type = BUF_SPU_DVB|spu_channel; + buf->type = spu_type|spu_channel; buf->content = buf->mem; buf->size = 0; this->video_fifo->put( this->video_fifo, buf ); @@ -466,7 +495,7 @@ static void demux_send_special_spu_buf( demux_ts_t *this, int spu_channel ) static void demux_ts_update_spu_channel(demux_ts_t *this) { buf_element_t *buf; - + this->current_spu_channel = this->stream->spu_channel; buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); @@ -475,7 +504,7 @@ static void demux_ts_update_spu_channel(demux_ts_t *this) buf->decoder_flags = BUF_FLAG_SPECIAL; buf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR; buf->size = 0; - + if (this->current_spu_channel >= 0 && this->current_spu_channel < this->spu_langs_count) { @@ -504,6 +533,10 @@ static void demux_ts_update_spu_channel(demux_ts_t *this) #endif } + if ((this->media[this->spu_media].type & BUF_MAJOR_MASK) == BUF_SPU_HDMV) { + buf->type = BUF_SPU_HDMV; + } + this->video_fifo->put(this->video_fifo, buf); } @@ -540,7 +573,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, * indicator set. */ if (!pusi) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: demux error! PAT without payload unit start indicator\n"); return; } @@ -550,7 +583,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, */ pkt += pkt[4]; if (pkt - original_pkt > PKT_SIZE) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: demux error! PAT with invalid pointer\n"); return; } @@ -584,13 +617,13 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, } if (pkt - original_pkt > BODY_SIZE - 1 - 3 - section_length) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: FIXME: (unsupported )PAT spans multiple TS packets\n"); return; } if ((section_number != 0) || (last_section_number != 0)) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: FIXME: (unsupported) PAT consists of multiple (%d) sections\n", last_section_number); return; } @@ -599,11 +632,11 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, calc_crc32 = demux_ts_compute_crc32 (this, pkt+5, section_length+3-4, 0xffffffff); if (crc32 != calc_crc32) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: demux error! PAT with invalid CRC32: packet_crc32: %.8x calc_crc32: %.8x\n", crc32,calc_crc32); return; - } + } #ifdef TS_PAT_LOG else { printf ("demux_ts: PAT CRC32 ok.\n"); @@ -647,13 +680,12 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, this->last_pmt_crc = 0; this->videoPid = INVALID_PID; this->spu_pid = INVALID_PID; - } - this->pmt_pid[program_count] = pmt_pid; - if (this->pmt[program_count] != NULL) { - free(this->pmt[program_count]); - this->pmt[program_count] = NULL; - this->pmt_write_ptr[program_count] = NULL; + if (this->pmt[program_count] != NULL) { + free(this->pmt[program_count]); + this->pmt[program_count] = NULL; + this->pmt_write_ptr[program_count] = NULL; + } } #ifdef TS_PAT_LOG if (this->program_number[program_count] != INVALID_PROGRAM) @@ -682,7 +714,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, /* we should have a PES packet here */ if (p[0] || p[1] || (p[2] != 1)) { - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (xine, XINE_VERBOSITY_DEBUG, "demux_ts: error %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]); return 0 ; } @@ -733,7 +765,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, /* sometimes corruption on header_len causes segfault in memcpy below */ if (header_len + 9 > pkt_len) { - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (xine, XINE_VERBOSITY_DEBUG, "demux_ts: illegal value for PES_header_data_length (0x%x)\n", header_len); return 0; } @@ -741,10 +773,28 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, p += header_len + 9; packet_len -= header_len + 3; - if (stream_id == 0xbd) { + if (m->descriptor_tag == STREAM_VIDEO_VC1) { + m->content = p; + m->size = packet_len; + m->type = BUF_VIDEO_VC1; + return 1; + } + + if (m->descriptor_tag == HDMV_SPU_BITMAP) { + long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3; + + m->content = p; + m->size = packet_len; + m->type |= BUF_SPU_HDMV; + m->buf->decoder_info[2] = payload_len; + return 1; + + } else + + if (stream_id == 0xbd || stream_id == 0xfd /* HDMV */) { int spu_id; - + lprintf ("audio buf = %02X %02X %02X %02X %02X %02X %02X %02X\n", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); @@ -752,15 +802,42 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, * we check the descriptor tag first because some stations * do not include any of the ac3 header info in their audio tracks * these "raw" streams may begin with a byte that looks like a stream type. + * For audio streams, m->type already contains the stream no. */ - if((m->descriptor_tag == 0x81) || /* ac3 - raw */ + if((m->descriptor_tag == STREAM_AUDIO_AC3) || /* ac3 - raw */ (p[0] == 0x0B && p[1] == 0x77)) { /* ac3 - syncword */ m->content = p; m->size = packet_len; m->type |= BUF_AUDIO_A52; return 1; - } else if (m->descriptor_tag == 0x06 + } else if (m->descriptor_tag == HDMV_AUDIO_83_TRUEHD) { + /* TODO: separate AC3 and TrueHD streams ... */ + m->content = p; + m->size = packet_len; + m->type |= BUF_AUDIO_A52; + return 1; + + } else if (m->descriptor_tag == HDMV_AUDIO_82_DTS || + m->descriptor_tag == HDMV_AUDIO_86_DTS_HD_MA ) { + m->content = p; + m->size = packet_len; + m->type |= BUF_AUDIO_DTS; + return 1; + + } else if (m->descriptor_tag == HDMV_AUDIO_80_PCM) { + + m->content = p + 4; + m->size = packet_len - 4; + m->type |= BUF_AUDIO_LPCM_BE; + + m->buf->decoder_flags |= BUF_FLAG_SPECIAL; + m->buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG; + m->buf->decoder_info[2] = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0]; + + return 1; + + } else if (m->descriptor_tag == ISO_13818_PES_PRIVATE && p[0] == 0x20 && p[1] == 0x00) { /* DVBSUB */ long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3; @@ -808,6 +885,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, switch (m->descriptor_tag) { case ISO_11172_VIDEO: case ISO_13818_VIDEO: + case STREAM_VIDEO_MPEG: lprintf ("demux_ts: found MPEG video type.\n"); m->type = BUF_VIDEO_MPEG; break; @@ -831,7 +909,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, m->content = p; m->size = packet_len; switch (m->descriptor_tag) { - case ISO_11172_AUDIO: + case ISO_11172_AUDIO: case ISO_13818_AUDIO: lprintf ("demux_ts: found MPEG audio track.\n"); m->type |= BUF_AUDIO_MPEG; @@ -880,7 +958,7 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, case (i.e. adaptation field only) when it does not get bumped. */ if (m->counter != INVALID_CC) { if ((m->counter & 0x0f) != cc) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: PID 0x%.4x: unexpected cc %d (expected %d)\n", m->pid, cc, m->counter); } } @@ -906,13 +984,13 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, else if ( this->numPreview<5 ) m->buf->decoder_flags=BUF_FLAG_PREVIEW; else - m->buf->decoder_flags=BUF_FLAG_FRAME_END; + m->buf->decoder_flags |= BUF_FLAG_FRAME_END; } m->buf->pts = m->pts; m->buf->decoder_info[0] = 1; - + if( this->input->get_length (this->input) ) - m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); if (this->rate) m->buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -930,13 +1008,15 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, if (!demux_ts_parse_pes_header(this->stream->xine, m, ts, len, this->stream)) { m->buf->free_buffer(m->buf); m->buf = NULL; - - if (m->corrupted_pes > CORRUPT_PES_THRESHOLD) { - if (this->videoPid == m->pid) + + if (m->corrupted_pes > CORRUPT_PES_THRESHOLD && m->autodetected) { + if (this->videoPid == m->pid) { this->videoPid = INVALID_PID; + this->last_pmt_crc = 0; + } } else { m->corrupted_pes++; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: PID 0x%.4x: corrupted pes encountered\n", m->pid); } } else { @@ -955,7 +1035,7 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, m->buf->pts = m->pts; m->buf->decoder_info[0] = 1; if( this->input->get_length (this->input) ) - m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * + m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * 65535 / this->input->get_length (this->input) ); if (this->rate) m->buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input) @@ -982,7 +1062,7 @@ static void demux_ts_pes_new(demux_ts_t*this, unsigned int mediaIndex, unsigned int pid, fifo_buffer_t *fifo, - uint8_t descriptor) { + uint16_t descriptor) { demux_ts_media *m = &this->media[mediaIndex]; @@ -1040,7 +1120,7 @@ static void demux_ts_get_reg_desc(demux_ts_t *this, uint32_t *dest, { *dest = (d[2] << 24) | (d[3] << 16) | (d[4] << 8) | d[5]; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: found registration format identifier: 0x%.4x\n", *dest); return; } @@ -1062,7 +1142,7 @@ static inline int ts_payloadsize(unsigned char * tsp) } return 184; } - + /* * NAME demux_ts_parse_pmt @@ -1092,14 +1172,14 @@ static void demux_ts_parse_pmt (demux_ts_t *this, uint32_t crc32; uint32_t calc_crc32; uint32_t coded_length; - unsigned int pid; + unsigned int pid; unsigned char *stream; - unsigned int i; - int count; - char *ptr = NULL; + unsigned int i; + int count; + char *ptr = NULL; unsigned char len; - unsigned int offset=0; - + unsigned int offset=0; + /* * A new section should start with the payload unit start * indicator set. We allocate some mem (max. allowed for a PM section) @@ -1108,7 +1188,7 @@ static void demux_ts_parse_pmt (demux_ts_t *this, if (pusi) { pkt+=pkt[4]; /* pointer to start of section */ offset=1; - + if (this->pmt[program_count] != NULL) free(this->pmt[program_count]); this->pmt[program_count] = (uint8_t *) calloc(4096, sizeof(unsigned char)); this->pmt_write_ptr[program_count] = this->pmt[program_count]; @@ -1152,7 +1232,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num } if ((section_number != 0) || (last_section_number != 0)) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: FIXME (unsupported) PMT consists of multiple (%d) sections\n", last_section_number); return; } @@ -1178,7 +1258,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num len = count-offset; memcpy (this->pmt_write_ptr[program_count], ptr, len); this->pmt_write_ptr[program_count] +=len; - + #ifdef TS_PMT_LOG printf ("ts_demux: wr_ptr: %p, will be %p when finished\n", this->pmt_write_ptr[program_count], @@ -1193,6 +1273,15 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num return; } + if (!section_length) { + free (this->pmt[program_count]); + this->pmt[program_count] = NULL; +#ifdef TS_PMT_LOG + printf ("ts_demux: eek, zero-length section?\n"); +#endif + return; + } + #ifdef TS_PMT_LOG printf ("ts_demux: have all TS packets for the PMT section\n"); #endif @@ -1207,9 +1296,9 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num this->pmt[program_count], section_length+3-4, 0xffffffff); if (crc32 != calc_crc32) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: demux error! PMT with invalid CRC32: packet_crc32: %#.8x calc_crc32: %#.8x\n", - crc32,calc_crc32); + crc32,calc_crc32); return; } else { @@ -1230,6 +1319,15 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num } } + /* + * Forget the current video, audio and subtitle PIDs; if the PMT has not + * changed, we'll pick them up again when we parse this PMT, while if the + * PMT has changed (e.g. an IPTV streamer that's just changed its source), + * we'll get new PIDs that we should follow. + */ + this->audio_tracks_count = 0; + this->videoPid = INVALID_PID; + this->spu_pid = INVALID_PID; /* * ES definitions start here...we are going to learn upto one video @@ -1247,7 +1345,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num stream = &this->pmt[program_count][12] + program_info_length; coded_length = 13 + program_info_length; if (coded_length > section_length) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux error! PMT with inconsistent progInfo length\n"); return; } @@ -1264,7 +1362,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num stream_info_length = ((stream[3] << 8) | stream[4]) & 0x0fff; coded_length = 5 + stream_info_length; if (coded_length > section_length) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux error! PMT with inconsistent streamInfo length\n"); return; } @@ -1278,6 +1376,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num case ISO_13818_VIDEO: case ISO_14496_PART2_VIDEO: case ISO_14496_PART10_VIDEO: + case STREAM_VIDEO_VC1: if (this->videoPid == INVALID_PID) { #ifdef TS_PMT_LOG printf ("demux_ts: PMT video pid 0x%.4x type %2.2x\n", pid, stream[0]); @@ -1331,7 +1430,6 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num case ISO_13818_PES_PRIVATE: for (i = 5; i < coded_length; i += stream[i+1] + 2) { if ((stream[i] == 0x6a) && (this->audio_tracks_count < MAX_AUDIO_TRACKS)) { - uint32_t format_identifier=0; int i, found = 0; for(i = 0; i < this->audio_tracks_count; i++) { if(this->audio_tracks[i].pid == pid) { @@ -1344,7 +1442,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num printf ("demux_ts: PMT AC3 audio pid 0x%.4x type %2.2x\n", pid, stream[0]); #endif demux_ts_pes_new(this, this->media_num, pid, - this->audio_fifo, 0x81); + this->audio_fifo, STREAM_AUDIO_AC3); this->audio_tracks[this->audio_tracks_count].pid = pid; this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; @@ -1379,9 +1477,9 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num { int no = this->spu_langs_count; demux_ts_spu_lang *lang = &this->spu_langs[no]; - + this->spu_langs_count++; - + memcpy(lang->desc.lang, &stream[pos], 3); lang->desc.lang[3] = 0; lang->desc.comp_page_id = @@ -1392,7 +1490,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num lang->media_index = this->media_num; this->media[this->media_num].type = no; demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); - demux_send_special_spu_buf( this, no ); + demux_send_special_spu_buf( this, BUF_SPU_DVB, no ); #ifdef TS_LOG printf("demux_ts: DVBSUB: pid 0x%.4x: %s page %ld %ld type %2.2x\n", pid, lang->desc.lang, @@ -1405,6 +1503,46 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num } break; + case HDMV_SPU_INTERACTIVE: + case HDMV_SPU_TEXT: + if (this->hdmv > 0) { + printf("demux_ts: Skipping unsupported HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n", + stream[0], pid); + break; + } + /* fall thru */ + + case HDMV_SPU_BITMAP: + if (this->hdmv > 0) { + if (pid >= 0x1200 && pid < 0x1300) { + /* HDMV Presentation Graphics / SPU */ + + if (this->spu_langs_count >= MAX_SPU_LANGS) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_ts: too many SPU tracks! ignoring pid 0x%.4x\n", + pid); + break; + } + + demux_ts_spu_lang *lang = &this->spu_langs[this->spu_langs_count]; + + memset(lang->desc.lang, 0, sizeof(lang->desc.lang)); + /*memcpy(lang->desc.lang, &stream[pos], 3);*/ + /*lang->desc.lang[3] = 0;*/ + lang->pid = pid; + lang->media_index = this->media_num; + this->media[this->media_num].type = this->spu_langs_count; + demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]); + demux_send_special_spu_buf( this, BUF_SPU_HDMV, this->spu_langs_count ); + this->spu_langs_count++; +#ifdef TS_PMT_LOG + printf("demux_ts: HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n", + stream[0], pid); +#endif + break; + } + } + /* fall thru */ default: /* This following section handles all the cases where the audio track info is stored in PMT user info with stream id >= 0x80 @@ -1412,7 +1550,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num * then we check the registration format identifier to see if it holds "AC-3" (0x41432d33) and * if is does, we tag this as an audio stream. * FIXME: This will need expanding if we ever see a DTS or other media format here. - */ + */ if ((this->audio_tracks_count < MAX_AUDIO_TRACKS) && (stream[0] >= 0x80) ) { int i, found = 0; for(i = 0; i < this->audio_tracks_count; i++) { @@ -1426,7 +1564,10 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num demux_ts_get_reg_desc(this, &format_identifier, stream + 5, stream_info_length); /* If no format identifier, assume A52 */ - if ((format_identifier == 0x41432d33) || (format_identifier == 0)) { + if (( format_identifier == 0x41432d33) || + ( format_identifier == 0) || + ((format_identifier == 0x48444d56 || this->hdmv>0) && stream[0] == HDMV_AUDIO_80_PCM) /* BluRay PCM */) { + demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo, stream[0]); this->audio_tracks[this->audio_tracks_count].pid = pid; this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; @@ -1491,10 +1632,10 @@ static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: about to resync!\n"); for (p=0; p < npkt_read; p++) { - for(n=0; n < PKT_SIZE; n++) { + for(n=0; n < this->pkt_size; n++) { sync_ok = 1; for (i=0; i < MIN(MIN_SYNCS, npkt_read - p); i++) { - if (buf[n + ((i+p) * PKT_SIZE)] != SYNC_BYTE) { + if (buf[this->pkt_offset + n + ((i+p) * this->pkt_size)] != SYNC_BYTE) { sync_ok = 0; break; } @@ -1506,14 +1647,14 @@ static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { if (sync_ok) { /* Found sync, fill in */ - memmove(&buf[0], &buf[n + p * PKT_SIZE], - ((PKT_SIZE * (npkt_read - p)) - n)); + memmove(&buf[0], &buf[n + p * this->pkt_size], + ((this->pkt_size * (npkt_read - p)) - n)); read_length = this->input->read(this->input, - &buf[(PKT_SIZE * (npkt_read - p)) - n], - n + p * PKT_SIZE); + &buf[(this->pkt_size * (npkt_read - p)) - n], + n + p * this->pkt_size); /* FIXME: when read_length is not as required... we now stop demuxing */ - if (read_length != (n + p * PKT_SIZE)) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + if (read_length != (n + p * this->pkt_size)) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts_tsync_correct: sync found, but read failed\n"); return 0; } @@ -1531,6 +1672,32 @@ static int sync_detect(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) { sync_ok = 1; + if (this->hdmv) { + this->pkt_size = PKT_SIZE + 4; + this->pkt_offset = 4; + for (i=0; i < MIN(MIN_SYNCS, npkt_read - 3); i++) { + if (buf[this->pkt_offset + i * this->pkt_size] != SYNC_BYTE) { + sync_ok = 0; + break; + } + } + if (sync_ok) { + if (this->hdmv < 0) { + /* fix npkt_read (packet size is 192, not 188) */ + this->npkt_read = npkt_read * PKT_SIZE / this->pkt_size; + } + this->hdmv = 1; + return sync_ok; + } + if (this->hdmv > 0) + return sync_correct(this, buf, npkt_read); + + /* plain ts */ + this->hdmv = 0; + this->pkt_size = PKT_SIZE; + this->pkt_offset = 0; + } + for (i=0; i < MIN(MIN_SYNCS, npkt_read); i++) { if (buf[i * PKT_SIZE] != SYNC_BYTE) { sync_ok = 0; @@ -1554,15 +1721,15 @@ static unsigned char * demux_synchronise(demux_ts_t* this) { /* NEW: handle read returning less packets than NPKT_PER_READ... */ do { read_length = this->input->read(this->input, this->buf, - PKT_SIZE * NPKT_PER_READ); - if (read_length % PKT_SIZE) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + this->pkt_size * NPKT_PER_READ); + if (read_length < 0 || read_length % this->pkt_size) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: read returned %d bytes (not a multiple of %d!)\n", - read_length, PKT_SIZE); + read_length, this->pkt_size); this->status = DEMUX_FINISHED; return NULL; } - this->npkt_read = read_length / PKT_SIZE; + this->npkt_read = read_length / this->pkt_size; #ifdef TS_READ_STATS this->rstat[this->npkt_read]++; @@ -1589,13 +1756,13 @@ static unsigned char * demux_synchronise(demux_ts_t* this) { return NULL; } } - return_pointer = &(this->buf)[PKT_SIZE * this->packet_number]; + return_pointer = &(this->buf)[this->pkt_offset + this->pkt_size * this->packet_number]; this->packet_number++; return return_pointer; } -static int64_t demux_ts_adaptation_field_parse(uint8_t *data, +static int64_t demux_ts_adaptation_field_parse(uint8_t *data, uint32_t adaptation_field_length) { uint32_t discontinuity_indicator=0; @@ -1717,7 +1884,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { transport_error_indicator = (originalPkt[1] >> 7) & 0x01; payload_unit_start_indicator = (originalPkt[1] >> 6) & 0x01; transport_priority = (originalPkt[1] >> 5) & 0x01; - pid = ((originalPkt[1] << 8) | + pid = ((originalPkt[1] << 8) | originalPkt[2]) & 0x1fff; transport_scrambling_control = (originalPkt[3] >> 6) & 0x03; adaptation_field_control = (originalPkt[3] >> 4) & 0x03; @@ -1737,8 +1904,8 @@ static void demux_ts_parse_packet (demux_ts_t*this) { /* * Discard packets that are obviously bad. */ - if (sync_byte != 0x47) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + if (sync_byte != SYNC_BYTE) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux error! invalid ts sync byte %.2x\n", sync_byte); return; } @@ -1753,7 +1920,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { if (transport_scrambling_control) { if (this->videoPid == pid) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: selected videoPid is scrambled; skipping...\n"); } for (i=0; i < this->scrambled_npids; i++) { @@ -1778,7 +1945,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { */ data_offset += adaptation_field_length + 1; } - + if (! (adaptation_field_control & 0x1)) { return; } @@ -1790,10 +1957,10 @@ static void demux_ts_parse_packet (demux_ts_t*this) { */ program_count=0; if(this->media_num<MAX_PMTS) - while ((this->program_number[program_count] != INVALID_PROGRAM) && - (program_count < MAX_PMTS)) { + while ((this->program_number[program_count] != INVALID_PROGRAM) && + (program_count < MAX_PMTS)) { if (pid == this->pmt_pid[program_count]) { - + #ifdef TS_LOG printf ("demux_ts: PMT prog: 0x%.4x pid: 0x%.4x\n", this->program_number[program_count], @@ -1806,7 +1973,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { } program_count++; } - + if (payload_unit_start_indicator && this->media_num < MAX_PIDS){ int pes_stream_id; if (pid == 0) { @@ -1820,7 +1987,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { #ifdef TS_HEADER_LOG printf("demux_ts:ts_pes_header:stream_id=0x%.2x\n",pes_stream_id); #endif - + if ( (pes_stream_id >= VIDEO_STREAM_S) && (pes_stream_id <= VIDEO_STREAM_E) ) { if ( this->videoPid == INVALID_PID) { int i, found = 0; @@ -1830,20 +1997,21 @@ static void demux_ts_parse_packet (demux_ts_t*this) { break; } } - + if (found && (this->media[i].corrupted_pes == 0)) { this->videoPid = pid; this->videoMedia = i; } else if (!found) { this->videoPid = pid; this->videoMedia = this->media_num; - demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, pes_stream_id); + this->media[this->videoMedia].autodetected = 1; + demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, 0x100 + pes_stream_id); } - + if (this->videoPid != INVALID_PID) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: auto-detected video pid 0x%.4x\n", pid); - } + } } } else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) ) { if (this->audio_tracks_count < MAX_AUDIO_TRACKS) { @@ -1859,20 +2027,21 @@ static void demux_ts_parse_packet (demux_ts_t*this) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: auto-detected audio pid 0x%.4x\n", pid); #endif + /* store PID, index and stream no. */ this->audio_tracks[this->audio_tracks_count].pid = pid; this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; this->media[this->media_num].type = this->audio_tracks_count; demux_ts_pes_new(this, this->media_num++, pid, - this->audio_fifo,pes_stream_id); + this->audio_fifo, 0x100 + pes_stream_id); this->audio_tracks_count++; } } } } - + if (data_len > PKT_SIZE) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: demux error! invalid payload size %d\n", data_len); } else { @@ -1946,7 +2115,7 @@ static void demux_ts_event_handler (demux_ts_t *this) { this->last_pmt_crc = 0; _x_demux_control_start (this->stream); break; - + } xine_event_free (event); @@ -1985,7 +2154,7 @@ static void demux_ts_dispose (demux_plugin_t *this_gen) { } } for (i=0; i < MAX_PIDS; i++) { - if (this->media[i].buf != NULL) { + if (this->media[i].buf != NULL) { this->media[i].buf->free_buffer(this->media[i].buf); this->media[i].buf = NULL; } @@ -2022,23 +2191,23 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) { this->last_pmt_crc = 0; _x_demux_control_start (this->stream); - + this->input->seek (this->input, 0, SEEK_SET); this->send_newpts = 1; - + demux_ts_build_crc32_table (this); - + this->status = DEMUX_OK ; this->send_end_buffers = 1; this->scrambled_npids = 0; - + /* DVBSUB */ this->spu_pid = INVALID_PID; this->spu_langs_count = 0; this->current_spu_channel = -1; - + /* FIXME ? */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); @@ -2065,11 +2234,11 @@ static int demux_ts_seek (demux_plugin_t *this_gen, } this->send_newpts = 1; - + for (i=0; i<MAX_PIDS; i++) { demux_ts_media *m = &this->media[i]; - if (m->buf != NULL) + if (m->buf != NULL) m->buf->free_buffer(m->buf); m->buf = NULL; m->counter = INVALID_CC; @@ -2078,7 +2247,7 @@ static int demux_ts_seek (demux_plugin_t *this_gen, } if( !playing ) { - + this->status = DEMUX_OK; this->buf_flag_seek = 0; @@ -2088,7 +2257,7 @@ static int demux_ts_seek (demux_plugin_t *this_gen, _x_demux_flush_engine(this->stream); } - + return this->status; } @@ -2097,7 +2266,7 @@ static int demux_ts_get_stream_length (demux_plugin_t *this_gen) { demux_ts_t*this = (demux_ts_t*)this_gen; if (this->rate) - return (int)((int64_t) this->input->get_length (this->input) + return (int)((int64_t) this->input->get_length (this->input) * 1000 / (this->rate * 50)); else return 0; @@ -2119,7 +2288,7 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, /* be a bit paranoid */ if (this == NULL || this->stream == NULL) return DEMUX_OPTIONAL_UNSUPPORTED; - + switch (data_type) { case DEMUX_OPTIONAL_DATA_AUDIOLANG: @@ -2138,7 +2307,7 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, if (channel>=0 && channel<this->spu_langs_count) { memcpy(str, this->spu_langs[channel].desc.lang, 3); str[3] = 0;} - else + else strcpy(str, "none"); return DEMUX_OPTIONAL_SUCCESS; @@ -2147,45 +2316,54 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, } } +static int detect_ts(uint8_t *buf, size_t len, int ts_size) +{ + int i, j; + int try_again, ts_detected = 0; + size_t packs = len / ts_size - 2; + + for (i = 0; i < ts_size; i++) { + try_again = 0; + if (buf[i] == SYNC_BYTE) { + for (j = 1; j < packs; j++) { + if (buf[i + j*ts_size] != SYNC_BYTE) { + try_again = 1; + break; + } + } + if (try_again == 0) { +#ifdef TS_LOG + printf ("demux_ts: found 0x47 pattern at offset %d\n", i); +#endif + ts_detected = 1; + } + } + } -static demux_plugin_t *open_plugin (demux_class_t *class_gen, - xine_stream_t *stream, + return ts_detected; +} + +static demux_plugin_t *open_plugin (demux_class_t *class_gen, + xine_stream_t *stream, input_plugin_t *input) { - + demux_ts_t *this; int i; + int hdmv = -1; switch (stream->content_detection_method) { case METHOD_BY_CONTENT: { uint8_t buf[2069]; - int i, j; - int try_again, ts_detected; - if (!_x_demux_read_header(input, buf, 2069)) + if (!_x_demux_read_header(input, buf, sizeof(buf))) return NULL; - ts_detected = 0; - - for (i = 0; i < 188; i++) { - try_again = 0; - if (buf[i] == 0x47) { - for (j = 1; j <= 10; j++) { - if (buf[i + j*188] != 0x47) { - try_again = 1; - break; - } - } - if (try_again == 0) { -#ifdef TS_LOG - printf ("demux_ts: found 0x47 pattern at offset %d\n", i); -#endif - ts_detected = 1; - } - } - } - - if (!ts_detected) + if (detect_ts(buf, sizeof(buf), PKT_SIZE)) + hdmv = 0; + else if (detect_ts(buf, sizeof(buf), PKT_SIZE+4)) + hdmv = 1; + else return NULL; } break; @@ -2193,6 +2371,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, case METHOD_BY_EXTENSION: { const char *const mrl = input->get_mrl (input); + if (_x_demux_check_extension (mrl, "m2ts mts")) + hdmv = 1; + else + hdmv = 0; + /* check extension */ const char *const extensions = class_gen->get_extensions (class_gen); @@ -2229,7 +2412,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, * if we reach this point, the input has been accepted. */ - this = xine_xmalloc(sizeof(*this)); + this = calloc(1, sizeof(*this)); this->stream = stream; this->input = input; this->blockSize = PKT_SIZE; @@ -2243,13 +2426,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->demux_plugin.get_capabilities = demux_ts_get_capabilities; this->demux_plugin.get_optional_data = demux_ts_get_optional_data; this->demux_plugin.demux_class = class_gen; - + /* * Initialise our specialised data. */ for (i = 0; i < MAX_PIDS; i++) { this->media[i].pid = INVALID_PID; this->media[i].buf = NULL; + this->media[i].autodetected = 0; } for (i = 0; i < MAX_PMTS; i++) { @@ -2267,14 +2451,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->last_pmt_crc = 0; this->rate = 16000; /* FIXME */ - - this->status = DEMUX_FINISHED; -#ifdef TS_READ_STATS - for (i=0; i<=NPKT_PER_READ; i++) { - this->rstat[i] = 0; - } -#endif + this->status = DEMUX_FINISHED; /* DVBSUB */ this->spu_pid = INVALID_PID; @@ -2283,9 +2461,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, /* dvb */ this->event_queue = xine_event_new_queue (this->stream); - + + /* HDMV */ + this->hdmv = hdmv; + this->pkt_offset = (hdmv > 0) ? 4 : 0; + this->pkt_size = PKT_SIZE + this->pkt_offset; + this->numPreview=0; - + return &this->demux_plugin; } @@ -2296,7 +2479,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, static const char *get_description (demux_class_t *this_gen) { return "MPEG Transport Stream demuxer"; } - + static const char *get_identifier (demux_class_t *this_gen) { return "MPEG_TS"; } @@ -2317,10 +2500,10 @@ static void class_dispose (demux_class_t *this_gen) { } static void *init_class (xine_t *xine, void *data) { - + demux_ts_class_t *this; - - this = xine_xmalloc (sizeof (demux_ts_class_t)); + + this = calloc(1, sizeof(demux_ts_class_t)); this->config = xine->config; this->xine = xine; @@ -2343,7 +2526,7 @@ static const demuxer_info_t demux_info_ts = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "mpeg-ts", XINE_VERSION_CODE, &demux_info_ts, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c index f6eadd652..7462cd874 100644 --- a/src/demuxers/demux_tta.c +++ b/src/demuxers/demux_tta.c @@ -19,11 +19,21 @@ * * True Audio demuxer by Diego Pettenò <flameeyes@gentoo.org> * Inspired by tta libavformat demuxer by Alex Beregszaszi + * + * Seek + time support added by Kelvie Wong <kelvie@ieee.org> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "demux_tta" #define LOG_VERBOSE +// This is from the TTA spec, the length (in seconds) of a frame +// http://www.true-audio.com/TTA_Lossless_Audio_Codec_-_Format_Description +#define FRAME_TIME 1.04489795918367346939 + #include "xine_internal.h" #include "xineutils.h" #include "demux.h" @@ -43,6 +53,8 @@ typedef struct { uint32_t totalframes; uint32_t currentframe; + off_t datastart; + int status; union { @@ -52,9 +64,9 @@ typedef struct { uint16_t channels; uint16_t bits_per_sample; uint32_t samplerate; - uint32_t data_length; + uint32_t data_length; /* Number of samples */ uint32_t crc32; - } __attribute__((__packed__)) tta; + } XINE_PACKED tta; uint8_t buffer[22]; /* This is the size of the header */ } header; } demux_tta_t; @@ -72,13 +84,13 @@ static int open_tta_file(demux_tta_t *this) { if (_x_demux_read_header(this->input, peek, 4) != 4) return 0; - if ( _X_BE_32(peek) != FOURCC_32('T', 'T', 'A', '1') ) + if ( !_x_is_fourcc(peek, "TTA1") ) return 0; if ( this->input->read(this->input, this->header.buffer, sizeof(this->header)) != sizeof(this->header) ) return 0; - framelen = 1.04489795918367346939 * le2me_32(this->header.tta.samplerate); + framelen = (uint32_t)(FRAME_TIME * le2me_32(this->header.tta.samplerate)); this->totalframes = le2me_32(this->header.tta.data_length) / framelen + ((le2me_32(this->header.tta.data_length) % framelen) ? 1 : 0); this->currentframe = 0; @@ -87,12 +99,15 @@ static int open_tta_file(demux_tta_t *this) { return 0; } - this->seektable = xine_xmalloc(sizeof(uint32_t)*this->totalframes); + this->seektable = calloc(this->totalframes, sizeof(uint32_t)); this->input->read(this->input, this->seektable, sizeof(uint32_t)*this->totalframes); /* Skip the CRC32 */ this->input->seek(this->input, 4, SEEK_CUR); + /* Store the offset after the header for seeking */ + this->datastart = this->input->get_current_pos(this->input); + return 1; } @@ -100,7 +115,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { demux_tta_t *this = (demux_tta_t *) this_gen; uint32_t bytes_to_read; - if ( this->currentframe > this->totalframes ) { + if ( this->currentframe >= this->totalframes ) { this->status = DEMUX_FINISHED; return this->status; } @@ -115,7 +130,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); buf->type = BUF_AUDIO_TTA; buf->pts = 0; - buf->extra_info->total_time = this->totalframes; + buf->extra_info->total_time = (int)(le2me_32(this->header.tta.data_length) * 1000.0 / le2me_32(this->header.tta.samplerate)); /* milliseconds */ buf->decoder_flags = 0; /* Set normalised position */ @@ -123,9 +138,13 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { (int) ((double) this->currentframe * 65535 / this->totalframes); /* Set time */ - /* buf->extra_info->input_time = this->current_sample / this->samplerate; */ + buf->extra_info->input_time = (int)(FRAME_TIME * this->currentframe)*1000; bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read); + if (bytes_read < 0) { + this->status = DEMUX_FINISHED; + break; + } buf->size = bytes_read; @@ -133,7 +152,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { if ( bytes_to_read <= 0 ) buf->decoder_flags |= BUF_FLAG_FRAME_END; - + this->audio_fifo->put(this->audio_fifo, buf); } @@ -145,6 +164,12 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { static void demux_tta_send_headers(demux_plugin_t *this_gen) { demux_tta_t *this = (demux_tta_t *) this_gen; buf_element_t *buf; + xine_waveformatex wave; + uint32_t total_size = sizeof(xine_waveformatex) + sizeof(this->header) + + sizeof(uint32_t)*this->totalframes; + unsigned char *header; + + header = malloc(total_size); this->audio_fifo = this->stream->audio_fifo; @@ -162,32 +187,51 @@ static void demux_tta_send_headers(demux_plugin_t *this_gen) { /* send start buffers */ _x_demux_control_start(this->stream); - /* send init info to decoders */ - if (this->audio_fifo) { - xine_waveformatex wave; - - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_AUDIO_TTA; - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - buf->decoder_info[0] = 0; - buf->decoder_info[1] = le2me_32(this->header.tta.samplerate); - buf->decoder_info[2] = le2me_16(this->header.tta.bits_per_sample); - buf->decoder_info[3] = le2me_16(this->header.tta.channels); - - buf->size = sizeof(xine_waveformatex) + sizeof(this->header) + sizeof(uint32_t)*this->totalframes; - memcpy(buf->content+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header)); - memcpy(buf->content+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes); + /* create header */ + wave.cbSize = total_size - sizeof(xine_waveformatex); - wave.cbSize = buf->size - sizeof(xine_waveformatex); - memcpy(buf->content, &wave, sizeof(wave)); + memcpy(header, &wave, sizeof(wave)); + memcpy(header+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header)); + memcpy(header+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes); - this->audio_fifo->put (this->audio_fifo, buf); + /* send init info to decoders */ + if (this->audio_fifo) { + uint32_t bytes_left = total_size; + + /* We are sending the seektable as well, and this may be larger than + buf->max_size */ + while (bytes_left) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER; + buf->type = BUF_AUDIO_TTA; + + /* Copy min(bytes_left, max_size) bytes */ + buf->size = bytes_left < buf->max_size ? bytes_left : buf->max_size; + memcpy(buf->content, header+(total_size-bytes_left), buf->size); + + bytes_left -= buf->size; + + /* The decoder information only needs the decoder information on the last + buffer element. */ + if (!bytes_left) { + buf->decoder_flags |= BUF_FLAG_FRAME_END; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = le2me_32(this->header.tta.samplerate); + buf->decoder_info[2] = le2me_16(this->header.tta.bits_per_sample); + buf->decoder_info[3] = le2me_16(this->header.tta.channels); + } + this->audio_fifo->put (this->audio_fifo, buf); + } } + free(header); } static int demux_tta_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing) { demux_tta_t *this = (demux_tta_t *) this_gen; + uint32_t start_frame; + uint32_t frame_index; + off_t start_off = this->datastart; /* if thread is not running, initialize demuxer */ if( !playing ) { @@ -196,6 +240,27 @@ static int demux_tta_seek (demux_plugin_t *this_gen, _x_demux_control_newpts(this->stream, 0, 0); this->status = DEMUX_OK; + + } else { + + /* Get the starting frame */ + if( start_pos ) + start_frame = start_pos * this->totalframes / 65535; + else + start_frame = (uint32_t)((double)start_time/ 1000.0 / FRAME_TIME); + + /* Now we find the offset */ + for( frame_index = 0; frame_index < start_frame; frame_index++ ) + start_off += le2me_32(this->seektable[frame_index]); + + /* Let's seek! We store the current frame internally, so let's update that + * as well */ + _x_demux_flush_engine(this->stream); + this->input->seek(this->input, start_off, SEEK_SET); + this->currentframe = start_frame; + _x_demux_control_newpts(this->stream, (int)(FRAME_TIME * start_frame) * 90000, BUF_FLAG_SEEK); + + this->status = DEMUX_OK; } return this->status; @@ -204,6 +269,7 @@ static int demux_tta_seek (demux_plugin_t *this_gen, static void demux_tta_dispose (demux_plugin_t *this_gen) { demux_tta_t *this = (demux_tta_t *) this_gen; + free(this->seektable); free(this); } @@ -214,9 +280,8 @@ static int demux_tta_get_status (demux_plugin_t *this_gen) { } static int demux_tta_get_stream_length (demux_plugin_t *this_gen) { -// demux_tta_t *this = (demux_tta_t *) this_gen; - - return 0; + demux_tta_t *this = (demux_tta_t *) this_gen; + return le2me_32(this->header.tta.data_length) * 1000.0 / le2me_32(this->header.tta.samplerate); /* milliseconds */ } static uint32_t demux_tta_get_capabilities(demux_plugin_t *this_gen) { @@ -233,7 +298,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_tta_t *this; - this = xine_xmalloc (sizeof (demux_tta_t)); + this = calloc(1, sizeof(demux_tta_t)); this->stream = stream; this->input = input; @@ -295,7 +360,8 @@ static const char *get_extensions (demux_class_t *this_gen) { } static const char *get_mimetypes (demux_class_t *this_gen) { - return NULL; + return "audio/x-tta: tta: True Audio;" + "audio/tta: tta: True Audio;"; } static void class_dispose (demux_class_t *this_gen) { @@ -307,7 +373,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_tta_init_plugin (xine_t *xine, void *data) { demux_tta_class_t *this; - this = xine_xmalloc (sizeof (demux_tta_class_t)); + this = calloc(1, sizeof(demux_tta_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_vmd.c b/src/demuxers/demux_vmd.c index 8b0087417..6aec12580 100644 --- a/src/demuxers/demux_vmd.c +++ b/src/demuxers/demux_vmd.c @@ -19,7 +19,7 @@ */ /* - * Sierra Video and Music Data (.vmd) File Demuxer + * Sierra Video and Music Data (.vmd) File Demuxer * by Mike Melanson (melanson@pcisys.net) * For more information on the VMD file format, visit: * http://www.pcisys.net/~melanson/codecs/ @@ -109,7 +109,7 @@ static int open_vmd_file(demux_vmd_t *this) { unsigned int total_frames; int64_t current_video_pts = 0; - if (_x_demux_read_header(this->input, vmd_header, VMD_HEADER_SIZE) != + if (_x_demux_read_header(this->input, vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE) return 0; @@ -168,7 +168,7 @@ static int open_vmd_file(demux_vmd_t *this) { return 0; } - this->frame_table = xine_xmalloc(this->frame_count * sizeof(vmd_frame_t)); + this->frame_table = calloc(this->frame_count, sizeof(vmd_frame_t)); current_offset = this->data_start = _X_LE_32(&vmd_header[20]); this->data_size = toc_offset - this->data_start; @@ -234,7 +234,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_VMD; if( this->data_size ) - buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * + buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * 65535 / this->data_size); memcpy(buf->content, frame->frame_record, BYTES_PER_FRAME_RECORD); buf->size = BYTES_PER_FRAME_RECORD; @@ -246,7 +246,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_VMD; if( this->data_size ) - buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * + buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * 65535 / this->data_size); if (remaining_bytes > buf->max_size) @@ -277,7 +277,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_VMD; if( this->data_size ) - buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * + buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * 65535 / this->data_size); memcpy(buf->content, frame->frame_record, BYTES_PER_FRAME_RECORD); buf->size = BYTES_PER_FRAME_RECORD; @@ -289,7 +289,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_VMD; if( this->data_size ) - buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * + buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) * 65535 / this->data_size); if (remaining_bytes > buf->max_size) @@ -421,7 +421,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_vmd_t *this; - this = xine_xmalloc (sizeof (demux_vmd_t)); + this = calloc(1, sizeof(demux_vmd_t)); this->stream = stream; this->input = input; @@ -495,7 +495,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_vmd_init_plugin (xine_t *xine, void *data) { demux_vmd_class_t *this; - this = xine_xmalloc (sizeof (demux_vmd_class_t)); + this = calloc(1, sizeof(demux_vmd_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_voc.c b/src/demuxers/demux_voc.c index 0439980f8..1ddbc1727 100644 --- a/src/demuxers/demux_voc.c +++ b/src/demuxers/demux_voc.c @@ -85,7 +85,7 @@ static int open_voc_file(demux_voc_t *this) { return 0; /* check the signature */ - if (strncmp(header, VOC_SIGNATURE, strlen(VOC_SIGNATURE)) != 0) + if (memcmp(header, VOC_SIGNATURE, sizeof(VOC_SIGNATURE)-1) != 0) return 0; /* file is qualified */ @@ -93,7 +93,7 @@ static int open_voc_file(demux_voc_t *this) { this->input->seek(this->input, first_block_offset, SEEK_SET); /* load the block preamble */ - if (this->input->read(this->input, preamble, BLOCK_PREAMBLE_SIZE) != + if (this->input->read(this->input, preamble, BLOCK_PREAMBLE_SIZE) != BLOCK_PREAMBLE_SIZE) return 0; @@ -106,7 +106,7 @@ static int open_voc_file(demux_voc_t *this) { } /* assemble 24-bit, little endian length */ - this->data_size = preamble[1] | (preamble[2] << 8) | (preamble[3] << 16); + this->data_size = _X_LE_24(&preamble[1]); /* get the next 2 bytes (re-use preamble bytes) */ if (this->input->read(this->input, preamble, 2) != 2) @@ -142,7 +142,7 @@ static int demux_voc_send_chunk(demux_plugin_t *this_gen) { /* just load data chunks from wherever the stream happens to be * pointing; issue a DEMUX_FINISHED status if EOF is reached */ remaining_sample_bytes = PCM_BLOCK_ALIGN; - current_file_pos = + current_file_pos = this->input->get_current_pos(this->input) - this->data_start; current_pts = current_file_pos; @@ -231,7 +231,7 @@ static int demux_voc_seek (demux_plugin_t *this_gen, off_t start_pos, int start_ start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); - + this->seek_flag = 1; this->status = DEMUX_OK; _x_demux_flush_engine (this->stream); @@ -296,7 +296,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_voc_t *this; - this = xine_xmalloc (sizeof (demux_voc_t)); + this = calloc(1, sizeof(demux_voc_t)); this->stream = stream; this->input = input; @@ -370,7 +370,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_voc_init_plugin (xine_t *xine, void *data) { demux_voc_class_t *this; - this = xine_xmalloc (sizeof (demux_voc_class_t)); + this = calloc(1, sizeof(demux_voc_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_vox.c b/src/demuxers/demux_vox.c index 3ce2ad705..ccf9bf877 100644 --- a/src/demuxers/demux_vox.c +++ b/src/demuxers/demux_vox.c @@ -77,7 +77,7 @@ static int demux_vox_send_chunk (demux_plugin_t *this_gen) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_DIALOGIC_IMA; bytes_read = this->input->read(this->input, buf->content, buf->max_size); - if (bytes_read == 0) { + if (bytes_read <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; @@ -87,7 +87,7 @@ static int demux_vox_send_chunk (demux_plugin_t *this_gen) { buf->size = buf->max_size; if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) current_file_pos * + buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->input->get_length (this->input) ); buf->extra_info->input_time = audio_pts / 90; buf->pts = audio_pts; @@ -166,7 +166,7 @@ static int demux_vox_get_status (demux_plugin_t *this_gen) { static int demux_vox_get_stream_length (demux_plugin_t *this_gen) { demux_vox_t *this = (demux_vox_t *) this_gen; - return (int)((int64_t)this->input->get_length(this->input) + return (int)((int64_t)this->input->get_length(this->input) * 2 * 1000 / DIALOGIC_SAMPLERATE); } @@ -203,7 +203,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return NULL; } - this = xine_xmalloc (sizeof (demux_vox_t)); + this = calloc(1, sizeof(demux_vox_t)); this->stream = stream; this->input = input; @@ -247,7 +247,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_vox_init_plugin (xine_t *xine, void *data) { demux_vox_class_t *this; - this = xine_xmalloc (sizeof (demux_vox_class_t)); + this = calloc(1, sizeof(demux_vox_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_vqa.c b/src/demuxers/demux_vqa.c index 40242476b..578be14ee 100644 --- a/src/demuxers/demux_vqa.c +++ b/src/demuxers/demux_vqa.c @@ -25,7 +25,7 @@ * * Quick technical note: VQA files begin with a header that includes a * frame index. This ought to be useful for seeking within a VQA file. - * However, seeking is infeasible due to the audio encoding: Each audio + * However, seeking is infeasible due to the audio encoding: Each audio * block needs information from the previous audio block in order to be * decoded, thus making random seeking difficult. */ @@ -96,8 +96,8 @@ static int open_vqa_file(demux_vqa_t *this) { return 0; /* check for the VQA signatures */ - if ((_X_BE_32(&scratch[0]) != FORM_TAG) || - (_X_BE_32(&scratch[8]) != WVQA_TAG)) + if (!_x_is_fourcc(&scratch[0], "FORM") || + !_x_is_fourcc(&scratch[8], "WVQA") ) return 0; /* file is qualified; skip to the start of the VQA header */ @@ -108,7 +108,7 @@ static int open_vqa_file(demux_vqa_t *this) { this->filesize = 1; /* load the VQA header */ - if (this->input->read(this->input, vqa_header, VQA_HEADER_SIZE) != + if (this->input->read(this->input, vqa_header, VQA_HEADER_SIZE) != VQA_HEADER_SIZE) return 0; @@ -334,7 +334,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_vqa_t *this; - this = xine_xmalloc (sizeof (demux_vqa_t)); + this = calloc(1, sizeof(demux_vqa_t)); this->stream = stream; this->input = input; @@ -408,7 +408,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_vqa_init_plugin (xine_t *xine, void *data) { demux_vqa_class_t *this; - this = xine_xmalloc (sizeof (demux_vqa_class_t)); + this = calloc(1, sizeof(demux_vqa_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c index 33baaf973..99c50ad67 100644 --- a/src/demuxers/demux_wav.c +++ b/src/demuxers/demux_wav.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2005 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -41,9 +41,11 @@ #include "bswap.h" #include "group_audio.h" -#define WAV_SIGNATURE_SIZE 16 +#define WAV_SIGNATURE_SIZE 12 /* this is the hex value for 'data' */ #define data_TAG 0x61746164 +/* this is the hex value for 'fmt ' */ +#define fmt_TAG 0x20746D66 #define PCM_BLOCK_ALIGN 1024 #define PREFERED_BLOCK_SIZE 4096 @@ -74,31 +76,62 @@ typedef struct { static int demux_wav_get_stream_length (demux_plugin_t *this_gen); -/* returns 1 if the WAV file was opened successfully, 0 otherwise */ -static int open_wav_file(demux_wav_t *this) { - uint8_t signature[WAV_SIGNATURE_SIZE]; +/* searches for the chunk with the given tag from the beginning of WAV file + * returns 1 if chunk was found, 0 otherwise, + * fills chunk_size and chunk_pos if chunk was found + * NOTE: chunk_pos is set to the position of the first byte of chunk data */ +static int find_chunk_by_tag(demux_wav_t *this, const uint32_t given_chunk_tag, + uint32_t *found_chunk_size, off_t *found_chunk_pos) { uint32_t chunk_tag; uint32_t chunk_size; uint8_t chunk_preamble[8]; + /* search for the chunks from the start of the WAV file */ + this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET); + + while (1) { + if (this->input->read(this->input, chunk_preamble, 8) != 8) { + return 0; + } + + chunk_tag = _X_LE_32(&chunk_preamble[0]); + chunk_size = _X_LE_32(&chunk_preamble[4]); + + if (chunk_tag == given_chunk_tag) { + if (found_chunk_size) + *found_chunk_size = _X_LE_32(&chunk_preamble[4]); + if (found_chunk_pos) + *found_chunk_pos = this->input->get_current_pos(this->input); + return 1; + } else { + this->input->seek(this->input, chunk_size, SEEK_CUR); + } + } +} + +/* returns 1 if the WAV file was opened successfully, 0 otherwise */ +static int open_wav_file(demux_wav_t *this) { + uint8_t signature[WAV_SIGNATURE_SIZE]; + off_t wave_pos; + uint32_t wave_size; + /* check the signature */ if (_x_demux_read_header(this->input, signature, WAV_SIGNATURE_SIZE) != WAV_SIGNATURE_SIZE) return 0; - if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVEfmt ", 8) ) + if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVE", 4) ) return 0; - /* file is qualified; skip over the header bytes in the stream */ - this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET); - - /* go after the format structure */ - if (this->input->read(this->input, - (unsigned char *)&this->wave_size, 4) != 4) + /* search for the 'fmt ' chunk first */ + wave_pos = 0; + if (find_chunk_by_tag(this, fmt_TAG, &wave_size, &wave_pos)==0) return 0; - this->wave_size = le2me_32(this->wave_size); - this->wave = xine_xmalloc( this->wave_size ); - - if (this->input->read(this->input, (void *)this->wave, this->wave_size) != + this->wave_size = wave_size; + + this->input->seek(this->input, wave_pos, SEEK_SET); + this->wave = malloc( this->wave_size ); + + if (!this->wave || this->input->read(this->input, (void *)this->wave, this->wave_size) != this->wave_size) { free (this->wave); return 0; @@ -114,28 +147,21 @@ static int open_wav_file(demux_wav_t *this) { return 0; } - /* traverse through the chunks to find the 'data' chunk */ + /* search for the 'data' chunk */ this->data_start = this->data_size = 0; - while (this->data_start == 0) { - - if (this->input->read(this->input, chunk_preamble, 8) != 8) { - free (this->wave); - return 0; - } - chunk_tag = _X_LE_32(&chunk_preamble[0]); - chunk_size = _X_LE_32(&chunk_preamble[4]); - - if (chunk_tag == data_TAG) { - this->data_start = this->input->get_current_pos(this->input); - /* Get the data length from the file itself, instead of the data - * TAG, for broken files */ - this->data_size = this->input->get_length(this->input); - } else { - this->input->seek(this->input, chunk_size, SEEK_CUR); - } + if (find_chunk_by_tag(this, data_TAG, NULL, &this->data_start)==0) + { + free (this->wave); + return 0; + } + else + { + /* Get the data length from the file itself, instead of the data + * TAG, for broken files */ + this->input->seek(this->input, this->data_start, SEEK_SET); + this->data_size = this->input->get_length(this->input); + return 1; } - - return 1; } static int demux_wav_send_chunk(demux_plugin_t *this_gen) { @@ -184,11 +210,16 @@ static int demux_wav_send_chunk(demux_plugin_t *this_gen) { buf->size = remaining_sample_bytes; remaining_sample_bytes -= buf->size; - if (this->input->read(this->input, buf->content, buf->size) != + off_t read; + if ((read = this->input->read(this->input, buf->content, buf->size)) != buf->size) { - buf->free_buffer(buf); - this->status = DEMUX_FINISHED; - break; + if (read == 0) { + buf->free_buffer(buf); + this->status = DEMUX_FINISHED; + break; + } else { + buf->size = read; + } } #if 0 @@ -337,7 +368,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_wav_t *this; uint32_t align; - this = xine_xmalloc (sizeof (demux_wav_t)); + this = calloc(1, sizeof(demux_wav_t)); this->stream = stream; this->input = input; @@ -423,7 +454,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_wav_init_plugin (xine_t *xine, void *data) { demux_wav_class_t *this; - this = xine_xmalloc (sizeof (demux_wav_class_t)); + this = calloc(1, sizeof(demux_wav_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_wc3movie.c b/src/demuxers/demux_wc3movie.c index 596d47f4a..36cc4eabb 100644 --- a/src/demuxers/demux_wc3movie.c +++ b/src/demuxers/demux_wc3movie.c @@ -102,7 +102,7 @@ typedef struct { } demux_mve_class_t; /* bizarre palette lookup table */ -const unsigned char wc3_pal_lookup[] = { +static const unsigned char wc3_pal_lookup[] = { 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A, 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2A, 0x2C, @@ -177,7 +177,7 @@ static int demux_mve_send_chunk(demux_plugin_t *this_gen) { } } this->current_shot++; - + /* this is the start of a new shot; send a new palette */ if (this->input->read(this->input, preamble, 4) != 4) { this->status = DEMUX_FINISHED; @@ -205,7 +205,7 @@ static int demux_mve_send_chunk(demux_plugin_t *this_gen) { } else if (chunk_tag == AUDI_TAG) { if( this->audio_fifo ) { audio_pts = this->video_pts - WC3_PTS_INC; - + while (chunk_size) { buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); buf->type = BUF_AUDIO_LPCM_LE; @@ -213,23 +213,23 @@ static int demux_mve_send_chunk(demux_plugin_t *this_gen) { buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->data_size); buf->extra_info->input_time = audio_pts / 90; buf->pts = audio_pts; - + if (chunk_size > buf->max_size) buf->size = buf->max_size; else buf->size = chunk_size; chunk_size -= buf->size; - + if (this->input->read(this->input, buf->content, buf->size) != buf->size) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; break; } - + if (!chunk_size) buf->decoder_flags |= BUF_FLAG_FRAME_END; - + this->audio_fifo->put (this->audio_fifo, buf); } }else{ @@ -293,7 +293,7 @@ static void demux_mve_send_headers(demux_plugin_t *this_gen) { /* load stream information */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); - /* this is not strictly correct-- some WC3 MVE files do not contain + /* this is not strictly correct-- some WC3 MVE files do not contain * audio, but I'm too lazy to check if that is the case */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, @@ -357,9 +357,9 @@ static int open_mve_file(demux_mve_t *this) { if (_x_demux_read_header(this->input, header, WC3_HEADER_SIZE) != WC3_HEADER_SIZE) return 0; - if ((_X_BE_32(&header[0]) != FORM_TAG) || - (_X_BE_32(&header[8]) != MOVE_TAG) || - (_X_BE_32(&header[12]) != PC_TAG)) + if ( !_x_is_fourcc(&header[0], "FORM") || + !_x_is_fourcc(&header[8], "MOVE") || + !_x_is_fourcc(&header[12], "_PC_") ) return 0; /* file is qualified */ @@ -376,19 +376,23 @@ static int open_mve_file(demux_mve_t *this) { if (this->input->read(this->input, preamble, 4) != 4) return 0; this->number_of_shots = _X_LE_32(&preamble[0]); - + /* allocate space for the shot offset index and set offsets to 0 */ - this->shot_offsets = xine_xmalloc(this->number_of_shots * sizeof(off_t)); + this->shot_offsets = calloc(this->number_of_shots, sizeof(off_t)); this->current_shot = 0; - for (i = 0; i < this->number_of_shots; i++) - this->shot_offsets[i] = 0; /* skip the SOND chunk */ this->input->seek(this->input, 12, SEEK_CUR); /* load the palette chunks */ - this->palettes = xine_xmalloc(this->number_of_shots * PALETTE_SIZE * + this->palettes = calloc(this->number_of_shots, PALETTE_SIZE * sizeof(palette_entry_t)); + + if (!this->shot_offsets || !this->palettes) { + free (this->shot_offsets); + return 0; + } + for (i = 0; i < this->number_of_shots; i++) { /* make sure there was a valid palette chunk preamble */ if (this->input->read(this->input, preamble, PREAMBLE_SIZE) != @@ -398,8 +402,8 @@ static int open_mve_file(demux_mve_t *this) { return 0; } - if ((_X_BE_32(&preamble[0]) != PALT_TAG) || - (_X_BE_32(&preamble[4]) != PALETTE_CHUNK_SIZE)) { + if ( !_x_is_fourcc(&preamble[0], "PALT") || + (_X_BE_32(&preamble[4]) != PALETTE_CHUNK_SIZE)) { xine_log(this->stream->xine, XINE_LOG_MSG, _("demux_wc3movie: There was a problem while loading palette chunks\n")); free (this->palettes); @@ -460,8 +464,9 @@ static int open_mve_file(demux_mve_t *this) { case BNAM_TAG: /* load the name into the stream attributes */ - title = realloc (title, chunk_size); - if (this->input->read(this->input, title, chunk_size) != chunk_size) { + free (title); + title = malloc (chunk_size); + if (!title || this->input->read(this->input, title, chunk_size) != chunk_size) { free (title); free (this->palettes); free (this->shot_offsets); @@ -535,13 +540,13 @@ static int demux_mve_seek (demux_plugin_t *this_gen, start_time /= 1000; start_pos = (off_t) ( (double) start_pos / 65535 * this->data_size ); - + this->status = DEMUX_OK; _x_demux_flush_engine(this->stream); this->seek_flag = 1; /* if input is non-seekable, do not proceed with the rest of this - * seek function */ + * seek function */ if (!INPUT_IS_SEEKABLE(this->input)) return this->status; @@ -561,7 +566,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen, chunk_size = (_X_BE_32(&preamble[4]) + 1) & (~1); if (chunk_tag == SHOT_TAG) { - this->shot_offsets[0] = + this->shot_offsets[0] = this->input->get_current_pos(this->input) - PREAMBLE_SIZE; /* skip the four SHOT data bytes (palette index) */ this->input->seek(this->input, 4, SEEK_CUR); @@ -576,7 +581,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen, start_pos += this->data_start; for (i = 0; i < this->number_of_shots - 1; i++) { - /* if the next shot offset has not been recorded, traverse through the + /* if the next shot offset has not been recorded, traverse through the * file until it is found */ if (this->shot_offsets[i + 1] == 0) { off_t current_pos; @@ -602,7 +607,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen, chunk_size = (_X_BE_32(&preamble[4]) + 1) & (~1); if (chunk_tag == SHOT_TAG) { - this->shot_offsets[i + 1] = + this->shot_offsets[i + 1] = this->input->get_current_pos(this->input) - PREAMBLE_SIZE; /* skip the four SHOT data bytes (palette index) */ this->input->seek(this->input, 4, SEEK_CUR); @@ -615,7 +620,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen, /* check if the seek-to offset falls in between this shot offset and * the next one */ - if ((start_pos >= this->shot_offsets[i]) && + if ((start_pos >= this->shot_offsets[i]) && (start_pos < this->shot_offsets[i + 1])) { new_shot = i; @@ -667,7 +672,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str demux_mve_t *this; - this = xine_xmalloc (sizeof (demux_mve_t)); + this = calloc(1, sizeof(demux_mve_t)); this->stream = stream; this->input = input; @@ -741,7 +746,7 @@ static void class_dispose (demux_class_t *this_gen) { void *demux_wc3movie_init_plugin (xine_t *xine, void *data) { demux_mve_class_t *this; - this = xine_xmalloc (sizeof (demux_mve_class_t)); + this = calloc(1, sizeof(demux_mve_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_yuv4mpeg2.c b/src/demuxers/demux_yuv4mpeg2.c index 9c5856710..aa1a4dff6 100644 --- a/src/demuxers/demux_yuv4mpeg2.c +++ b/src/demuxers/demux_yuv4mpeg2.c @@ -69,7 +69,7 @@ typedef struct { int aspect_d; int progressive; int top_field_first; - + unsigned int frame_pts_inc; unsigned int frame_size; @@ -86,7 +86,7 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { char *header_ptr, *header_endptr, *header_end; this->bih.biWidth = this->bih.biHeight = this->fps_n = this->fps_d = - this->aspect_n = this->aspect_d = this->progressive = + this->aspect_n = this->aspect_d = this->progressive = this->top_field_first = this->data_start = 0; if (_x_demux_read_header(this->input, header, Y4M_HEADER_BYTES) != Y4M_HEADER_BYTES) @@ -98,11 +98,11 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { /* null terminate the read data */ header[Y4M_HEADER_BYTES] = '\0'; - + /* check for stream header terminator */ if ((header_end = strchr(header, '\n')) == NULL) return 0; - + /* read tagged fields in stream header */ header_ptr = &header[Y4M_SIGNATURE_SIZE]; while (header_ptr < header_end) { @@ -111,7 +111,7 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { break; else header_ptr++; - + switch (*header_ptr) { case 'W': /* read the width */ @@ -153,31 +153,31 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { return 0; else header_ptr = header_endptr; - + /* denominator */ this->fps_d = strtol(header_ptr + 1, &header_endptr, 10); if (header_endptr == header_ptr + 1) return 0; else header_ptr = header_endptr; - + break; case 'A': - /* read aspect ratio - stored as a ratio(!) + /* read aspect ratio - stored as a ratio(!) * numerator */ this->aspect_n = strtol(header_ptr + 1, &header_endptr, 10); if ((header_endptr == header_ptr + 1) || (*header_endptr != ':')) return 0; else header_ptr = header_endptr; - + /* denominator */ this->aspect_d = strtol(header_ptr + 1, &header_endptr, 10); if (header_endptr == header_ptr + 1) return 0; else header_ptr = header_endptr; - + break; default: /* skip whatever this is */ @@ -185,7 +185,7 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { header_ptr++; } } - + /* make sure all the data was found */ if (!this->bih.biWidth || !this->bih.biHeight || !this->fps_n || !this->fps_d) return 0; @@ -194,25 +194,17 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { this->frame_size = this->bih.biWidth * this->bih.biHeight * 3 / 2; /* pts difference between frames */ - this->frame_pts_inc = (90000 * this->fps_d) / this->fps_n; - + this->frame_pts_inc = (90000 * this->fps_d) / this->fps_n; + /* finally, look for the first frame */ - while ((header_ptr - header) < (Y4M_HEADER_BYTES - 4)) { - if((header_ptr[0] == 'F') && - (header_ptr[1] == 'R') && - (header_ptr[2] == 'A') && - (header_ptr[3] == 'M') && - (header_ptr[4] == 'E')) { - this->data_start = header_ptr - header; - break; - } else - header_ptr++; - } - + char *data_start_ptr = memmem(header_ptr, Y4M_HEADER_BYTES, "FRAME", 5); + /* make sure the first frame was found */ - if(!this->data_start) + if ( !data_start_ptr ) return 0; - + + this->data_start = data_start_ptr - header; + /* compute size of all frames */ if (INPUT_IS_SEEKABLE(this->input)) { this->data_size = this->input->get_length(this->input) - @@ -228,29 +220,26 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) { demux_yuv4mpeg2_t *this = (demux_yuv4mpeg2_t *) this_gen; - buf_element_t *buf = NULL; - unsigned char preamble[Y4M_FRAME_SIGNATURE_SIZE]; - int bytes_remaining; - off_t current_file_pos; - int64_t pts; - /* validate that this is an actual frame boundary */ - if (this->input->read(this->input, preamble, Y4M_FRAME_SIGNATURE_SIZE) != - Y4M_FRAME_SIGNATURE_SIZE) { - this->status = DEMUX_FINISHED; - return this->status; - } - if (memcmp(preamble, Y4M_FRAME_SIGNATURE, Y4M_FRAME_SIGNATURE_SIZE) != - 0) { - this->status = DEMUX_FINISHED; - return this->status; + { + uint8_t preamble[Y4M_FRAME_SIGNATURE_SIZE]; + if (this->input->read(this->input, preamble, Y4M_FRAME_SIGNATURE_SIZE) != + Y4M_FRAME_SIGNATURE_SIZE) { + this->status = DEMUX_FINISHED; + return this->status; + } + if (memcmp(preamble, Y4M_FRAME_SIGNATURE, Y4M_FRAME_SIGNATURE_SIZE) != + 0) { + this->status = DEMUX_FINISHED; + return this->status; + } } /* load and dispatch the raw frame */ - bytes_remaining = this->frame_size; - current_file_pos = + int bytes_remaining = this->frame_size; + off_t current_file_pos = this->input->get_current_pos(this->input) - this->data_start; - pts = current_file_pos; + int64_t pts = current_file_pos; pts /= (this->frame_size + Y4M_FRAME_SIGNATURE_SIZE); pts *= this->frame_pts_inc; @@ -261,17 +250,14 @@ static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) { } while(bytes_remaining) { - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf_element_t *buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_I420; if( this->data_size ) buf->extra_info->input_normpos = (int)((double) current_file_pos * 65535 / this->data_size); buf->extra_info->input_time = pts / 90; buf->pts = pts; - if (bytes_remaining > buf->max_size) - buf->size = buf->max_size; - else - buf->size = bytes_remaining; + buf->size = MIN(bytes_remaining, buf->max_size); bytes_remaining -= buf->size; if (this->input->read(this->input, buf->content, buf->size) != @@ -285,13 +271,12 @@ static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) { buf->decoder_flags |= BUF_FLAG_FRAME_END; this->video_fifo->put(this->video_fifo, buf); } - + return this->status; -} +} static void demux_yuv4mpeg2_send_headers(demux_plugin_t *this_gen) { demux_yuv4mpeg2_t *this = (demux_yuv4mpeg2_t *) this_gen; - buf_element_t *buf; this->video_fifo = this->stream->video_fifo; this->audio_fifo = this->stream->audio_fifo; @@ -310,17 +295,17 @@ static void demux_yuv4mpeg2_send_headers(demux_plugin_t *this_gen) { _x_demux_control_start(this->stream); /* send init info to decoders */ - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf_element_t *buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE| BUF_FLAG_FRAME_END; buf->decoder_info[0] = this->frame_pts_inc; /* initial video step */ - + if(this->aspect_n && this->aspect_d) { buf->decoder_flags |= BUF_FLAG_ASPECT; buf->decoder_info[1] = this->bih.biWidth * this->aspect_n; buf->decoder_info[2] = this->bih.biHeight * this->aspect_d; } - + buf->decoder_info[3] = this->progressive; buf->decoder_info[4] = this->top_field_first; @@ -342,7 +327,7 @@ static int demux_yuv4mpeg2_seek (demux_plugin_t *this_gen, /* YUV4MPEG2 files are essentially constant bit-rate video. Seek along * the calculated frame boundaries. Divide the requested seek offset - * by the frame size integer-wise to obtain the desired frame number + * by the frame size integer-wise to obtain the desired frame number * and then multiply the frame number by the frame size to get the * starting offset. Add the data_start offset to obtain the final * offset. */ @@ -385,7 +370,7 @@ static int demux_yuv4mpeg2_get_status (demux_plugin_t *this_gen) { static int demux_yuv4mpeg2_get_stream_length (demux_plugin_t *this_gen) { demux_yuv4mpeg2_t *this = (demux_yuv4mpeg2_t *) this_gen; - return (int)(((int64_t) this->data_size * 1000 * this->fps_d) / + return (int)(((int64_t) this->data_size * 1000 * this->fps_d) / ((this->frame_size + Y4M_FRAME_SIGNATURE_SIZE) * this->fps_n)); } @@ -400,10 +385,7 @@ static int demux_yuv4mpeg2_get_optional_data(demux_plugin_t *this_gen, static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { - - demux_yuv4mpeg2_t *this; - - this = xine_xmalloc (sizeof (demux_yuv4mpeg2_t)); + demux_yuv4mpeg2_t *this = calloc(1, sizeof(demux_yuv4mpeg2_t)); this->stream = stream; this->input = input; @@ -422,10 +404,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - const char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); + const char *const mrl = input->get_mrl (input); + const char *const extensions = class_gen->get_extensions (class_gen); if (!_x_demux_check_extension (mrl, extensions)) { free (this); @@ -477,7 +457,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_plugin (xine_t *xine, void *data) { demux_yuv4mpeg2_class_t *this; - this = xine_xmalloc (sizeof (demux_yuv4mpeg2_class_t)); + this = calloc(1, sizeof(demux_yuv4mpeg2_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/demux_yuv_frames.c b/src/demuxers/demux_yuv_frames.c index 774329c05..81dd2b03a 100644 --- a/src/demuxers/demux_yuv_frames.c +++ b/src/demuxers/demux_yuv_frames.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2003-2004 the xine project * Copyright (C) 2003 Jeroen Asselman <j.asselman@itsec-ps.nl> - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -70,8 +70,6 @@ static int demux_yuv_frames_get_status (demux_plugin_t *this_gen) { } static int switch_buf(demux_yuv_frames_t *this , buf_element_t *buf){ - int result = 0; - if (!buf) return 0; @@ -88,8 +86,7 @@ static int switch_buf(demux_yuv_frames_t *this , buf_element_t *buf){ case BUF_VIDEO_I420: case BUF_VIDEO_YUY2: this->video_fifo->put(this->video_fifo, buf); - result = 1; /* 1, we still should read audio */ - break; + return 1; /* 1, we still should read audio */ case BUF_AUDIO_LPCM_LE: if (!_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO)) _x_demux_control_newpts(this->stream, buf->pts, 0); @@ -100,7 +97,7 @@ static int switch_buf(demux_yuv_frames_t *this , buf_element_t *buf){ buf->free_buffer(buf); } - return result; + return 0; } static int demux_yuv_frames_send_chunk (demux_plugin_t *this_gen){ @@ -123,21 +120,27 @@ static void demux_yuv_frames_send_headers (demux_plugin_t *this_gen){ this->video_fifo = this->stream->video_fifo; this->audio_fifo = this->stream->audio_fifo; - + _x_demux_control_start(this->stream); if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO)) { buf = this->input->read_block(this->input, this->audio_fifo, 0); - - this->audio_fifo->put(this->audio_fifo, buf); + + if (buf) + this->audio_fifo->put(this->audio_fifo, buf); + else + this->status = DEMUX_FINISHED; } - + if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO)) { buf = this->input->read_block(this->input, this->video_fifo, 0); - - this->video_fifo->put(this->video_fifo, buf); + + if (buf) + this->video_fifo->put(this->video_fifo, buf); + else + this->status = DEMUX_FINISHED; } - + this->status = DEMUX_OK; } @@ -203,7 +206,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, * if we reach this point, the input has been accepted. */ - this = xine_xmalloc (sizeof (demux_yuv_frames_t)); + this = calloc(1, sizeof(demux_yuv_frames_t)); this->stream = stream; this->input = input; @@ -253,7 +256,7 @@ static void class_dispose (demux_class_t *this_gen) { static void *init_class (xine_t *xine, void *data) { demux_yuv_frames_class_t *this; - this = xine_xmalloc (sizeof (demux_yuv_frames_class_t)); + this = calloc(1, sizeof(demux_yuv_frames_class_t)); this->demux_class.open_plugin = open_plugin; this->demux_class.get_description = get_description; diff --git a/src/demuxers/ebml.c b/src/demuxers/ebml.c index ac44aecd7..75fbfde75 100644 --- a/src/demuxers/ebml.c +++ b/src/demuxers/ebml.c @@ -40,7 +40,7 @@ ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input) { ebml_parser_t *ebml; - + ebml = malloc(sizeof(ebml_parser_t)); ebml->xine = xine; ebml->input = input; @@ -52,15 +52,15 @@ ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input) { ebml->doctype = NULL; ebml->doctype_version = 0; ebml->doctype_read_version = 0; - + ebml->level = 0; - + return ebml; } void dispose_ebml_parser(ebml_parser_t *ebml) { - free(ebml); + free(ebml); } @@ -132,7 +132,7 @@ static int ebml_read_elem_len(ebml_parser_t *ebml, uint64_t *len) { int ff_bytes; uint64_t value; int i; - + if (ebml->input->read(ebml->input, data, 1) != 1) { off_t pos = ebml->input->get_current_pos(ebml->input); xprintf(ebml->xine, XINE_VERBOSITY_LOG, @@ -162,7 +162,7 @@ static int ebml_read_elem_len(ebml_parser_t *ebml, uint64_t *len) { ff_bytes = 1; else ff_bytes = 0; - + /* read the rest of the len */ if (ebml->input->read(ebml->input, data + 1, size - 1) != (size - 1)) { off_t pos = ebml->input->get_current_pos(ebml->input); @@ -231,7 +231,7 @@ int ebml_read_uint(ebml_parser_t *ebml, ebml_elem_t *elem, uint64_t *num) { "ebml: Invalid integer element size %" PRIu64 "\n", size); return 0; } - + if (!ebml_read_elem_data (ebml, data, size)) return 0; @@ -253,7 +253,7 @@ int ebml_read_sint (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *num) { "ebml: Invalid integer element size %" PRIu64 "\n", size); return 0; } - + if (!ebml_read_elem_data(ebml, data, size)) return 0; @@ -262,7 +262,7 @@ int ebml_read_sint (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *num) { *num = -1; else *num = 0; - + while (size > 0) { *num = (*num << 8) | data[elem->len - size]; size--; @@ -310,7 +310,7 @@ int ebml_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem, char *str) { if (!ebml_read_elem_data(ebml, str, size)) return 0; - + return 1; } @@ -318,6 +318,22 @@ int ebml_read_utf8 (ebml_parser_t *ebml, ebml_elem_t *elem, char *str) { return ebml_read_ascii (ebml, elem, str); } +char *ebml_alloc_read_ascii (ebml_parser_t *ebml, ebml_elem_t *elem) +{ + char *text; + if (elem->len >= 4096) + return NULL; + text = malloc(elem->len + 1); + if (text) + { + text[elem->len] = '\0'; + if (ebml_read_ascii (ebml, elem, text)) + return text; + free (text); + } + return NULL; +} + int ebml_read_date (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *date) { return ebml_read_sint (ebml, elem, date); } @@ -330,7 +346,7 @@ int ebml_read_master (ebml_parser_t *ebml, ebml_elem_t *elem) { top_elem->start = elem->start; top_elem->len = elem->len; top_elem->id = elem->id; - + ebml->level++; lprintf("id: 0x%x, len: %" PRIu64 ", level: %d\n", elem->id, elem->len, ebml->level); if (ebml->level >= EBML_STACK_SIZE) { @@ -362,20 +378,20 @@ int ebml_check_header(ebml_parser_t *ebml) { "ebml: invalid master element\n"); return 0; } - + if (master.id != EBML_ID_EBML) { xprintf(ebml->xine, XINE_VERBOSITY_LOG, "ebml: invalid master element\n"); return 0; } - + if (!ebml_read_master (ebml, &master)) return 0; next_level = 1; while (next_level == 1) { ebml_elem_t elem; - + if (!ebml_read_elem_head(ebml, &elem)) return 0; @@ -389,7 +405,7 @@ int ebml_check_header(ebml_parser_t *ebml) { ebml->version = num; break; } - + case EBML_ID_EBMLREADVERSION: { uint64_t num; @@ -423,10 +439,8 @@ int ebml_check_header(ebml_parser_t *ebml) { } case EBML_ID_DOCTYPE: { - char *text = malloc(elem.len + 1); - - text[elem.len] = '\0'; - if (!ebml_read_ascii (ebml, &elem, text)) + char *text = ebml_alloc_read_ascii (ebml, &elem); + if (!text) return 0; lprintf("doctype: %s\n", text); diff --git a/src/demuxers/ebml.h b/src/demuxers/ebml.h index 35078c502..6d750a98c 100644 --- a/src/demuxers/ebml.h +++ b/src/demuxers/ebml.h @@ -48,7 +48,7 @@ typedef struct ebml_parser_s { /* xine stuff */ xine_t *xine; input_plugin_t *input; - + /* EBML Parser Stack Management */ ebml_elem_t elem_stack[EBML_STACK_SIZE]; int level; @@ -61,11 +61,11 @@ typedef struct ebml_parser_s { char *doctype; uint64_t doctype_version; uint64_t doctype_read_version; - + } ebml_parser_t; -ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input); +ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input) XINE_MALLOC; void dispose_ebml_parser (ebml_parser_t *ebml); @@ -91,6 +91,8 @@ int ebml_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem, char *str); int ebml_read_utf8(ebml_parser_t *ebml, ebml_elem_t *elem, char *str); +char *ebml_alloc_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem); + int ebml_read_date(ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *date); int ebml_read_master(ebml_parser_t *ebml, ebml_elem_t *elem); diff --git a/src/demuxers/group_audio.c b/src/demuxers/group_audio.c index 2643a8b80..f405d0292 100644 --- a/src/demuxers/group_audio.c +++ b/src/demuxers/group_audio.c @@ -110,7 +110,7 @@ static const demuxer_info_t demux_info_mod = { #endif const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "aac", XINE_VERSION_CODE, &demux_info_aac, demux_aac_init_plugin }, { PLUGIN_DEMUX, 26, "ac3", XINE_VERSION_CODE, &demux_info_ac3, demux_ac3_init_plugin }, { PLUGIN_DEMUX, 26, "aud", XINE_VERSION_CODE, &demux_info_aud, demux_aud_init_plugin }, diff --git a/src/demuxers/group_audio.h b/src/demuxers/group_audio.h index 424e5c8e0..d2cd91875 100644 --- a/src/demuxers/group_audio.h +++ b/src/demuxers/group_audio.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/demuxers/group_games.c b/src/demuxers/group_games.c index ad257c2fb..f08e8477d 100644 --- a/src/demuxers/group_games.c +++ b/src/demuxers/group_games.c @@ -78,7 +78,7 @@ static const demuxer_info_t demux_info_vmd = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "wve", XINE_VERSION_CODE, &demux_info_eawve, demux_eawve_init_plugin}, { PLUGIN_DEMUX, 26, "idcin", XINE_VERSION_CODE, &demux_info_idcin, demux_idcin_init_plugin }, { PLUGIN_DEMUX, 26, "ipmovie", XINE_VERSION_CODE, &demux_info_ipmovie, demux_ipmovie_init_plugin }, diff --git a/src/demuxers/group_games.h b/src/demuxers/group_games.h index f93d4bb07..ea6b00e75 100644 --- a/src/demuxers/group_games.h +++ b/src/demuxers/group_games.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/demuxers/id3.c b/src/demuxers/id3.c index 6b36cc666..15599ffea 100644 --- a/src/demuxers/id3.c +++ b/src/demuxers/id3.c @@ -29,7 +29,7 @@ * * ID3v2 specs: http://www.id3.org/ */ - + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -84,7 +84,7 @@ static const char* const id3_encoding[] = { "UTF-16", /* 0x01 */ "UTF-16BE", /* 0x02 */ "UTF-8"}; /* 0x03 */ - + int id3v1_parse_tag (input_plugin_t *input, xine_stream_t *stream) { off_t len; @@ -113,7 +113,7 @@ int id3v1_parse_tag (input_plugin_t *input, xine_stream_t *stream) { if (tag.genre < ID3_GENRE_COUNT) { _x_meta_info_set(stream, XINE_META_INFO_GENRE, id3_genre[tag.genre]); } - + } return 1; } else { @@ -126,12 +126,12 @@ static int id3v2_parse_genre(char* dest, char *src, int len) { int state = 0; char *buf = dest; unsigned int index = 0; - + while (*src) { lprintf("state=%d\n", state); if ((buf - dest) >= len) return 0; - + switch (state) { case 0: /* initial state */ @@ -241,7 +241,7 @@ static int id3v2_parse_header(input_plugin_t *input, uint8_t *mp3_frame_header, lprintf("tag: ID3 v2.%d.%d\n", mp3_frame_header[3], tag_header->revision); lprintf("flags: %d\n", tag_header->flags); - lprintf("size: %d\n", tag_header->size); + lprintf("size: %zu\n", tag_header->size); return 1; } else { return 0; @@ -259,9 +259,9 @@ static int id3v22_parse_frame_header(input_plugin_t *input, if (len == ID3V22_FRAME_HEADER_SIZE) { frame_header->id = (buf[0] << 16) + (buf[1] << 8) + buf[2]; - frame_header->size = _X_BE_24_synchsafe(&buf[3]); + frame_header->size = _X_BE_24(&buf[3]); - lprintf("frame: %c%c%c: size: %d\n", buf[0], buf[1], buf[2], + lprintf("frame: %c%c%c: size: %zu\n", buf[0], buf[1], buf[2], frame_header->size); return 1; @@ -275,8 +275,11 @@ static int id3v22_interp_frame(input_plugin_t *input, id3v22_frame_header_t *frame_header) { char *buf; int enc; - - buf = malloc(frame_header->size + 1); + const size_t bufsize = frame_header->size + 2; + if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */ + return 0; + + buf = malloc(bufsize); if (buf == NULL) { lprintf("malloc error"); return 0; @@ -284,6 +287,7 @@ static int id3v22_interp_frame(input_plugin_t *input, if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -292,7 +296,7 @@ static int id3v22_interp_frame(input_plugin_t *input, case ( FOURCC_TAG(0, 'T', 'C', 'O') ): { char tmp[1024]; - + if (id3v2_parse_genre(tmp, buf + 1, 1024)) { _x_meta_info_set(stream, XINE_META_INFO_GENRE, tmp); } @@ -337,9 +341,9 @@ static int id3v22_interp_frame(input_plugin_t *input, } -int id3v22_parse_tag(input_plugin_t *input, - xine_stream_t *stream, - int8_t *mp3_frame_header) { +static int id3v22_parse_tag(input_plugin_t *input, + xine_stream_t *stream, + int8_t *mp3_frame_header) { id3v2_header_t tag_header; id3v22_frame_header_t tag_frame_header; int pos = 0; @@ -348,22 +352,22 @@ int id3v22_parse_tag(input_plugin_t *input, if (tag_header.flags & ID3V22_ZERO_FLAG) { /* invalid flags */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid header flags (%02x)\n", tag_header.flags); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid header flags (%02x)\n", tag_header.flags); input->seek (input, tag_header.size - pos, SEEK_CUR); return 0; } if (tag_header.flags & ID3V22_COMPRESS_FLAG) { /* compressed tag: not supported */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: compressed tags are not supported\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": compressed tags are not supported\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 0; } if (tag_header.flags & ID3V22_UNSYNCH_FLAG) { /* unsynchronized tag: not supported */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: unsynchronized tags are not supported\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": unsynchronized tags are not supported\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 0; } @@ -371,15 +375,15 @@ int id3v22_parse_tag(input_plugin_t *input, while ((pos + ID3V22_FRAME_HEADER_SIZE) <= tag_header.size) { if (id3v22_parse_frame_header(input, &tag_frame_header)) { pos += ID3V22_FRAME_HEADER_SIZE; - if (tag_frame_header.id && tag_frame_header.size) { + if (tag_frame_header.id) { if ((pos + tag_frame_header.size) <= tag_header.size) { if (!id3v22_interp_frame(input, stream, &tag_frame_header)) { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame content\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid frame content\n"); } } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame header\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid frame header\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } @@ -390,14 +394,14 @@ int id3v22_parse_tag(input_plugin_t *input, return 1; } } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: id3v2_parse_frame_header problem\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": id3v2_parse_frame_header problem\n"); return 0; } } return 1; } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "id3: id3v2_parse_header problem\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": id3v2_parse_header problem\n"); return 0; } } @@ -415,7 +419,7 @@ static int id3v23_parse_frame_header(input_plugin_t *input, frame_header->size = _X_BE_32(&buf[4]); frame_header->flags = _X_BE_16(buf + 8); - lprintf("frame: %c%c%c%c, size: %d, flags: %X\n", buf[0], buf[1], buf[2], buf[3], + lprintf("frame: %c%c%c%c, size: %zu, flags: %X\n", buf[0], buf[1], buf[2], buf[3], frame_header->size, frame_header->flags); return 1; @@ -429,9 +433,9 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input, uint8_t buf[14]; if (input->read (input, buf, 4) == 4) { - - frame_ext_header->size = _X_BE_32_synchsafe(&buf[0]); - + + frame_ext_header->size = _X_BE_32(&buf[0]); + if (frame_ext_header->size == 6) { if (input->read (input, buf + 4, 6) == 6) { frame_ext_header->flags = _X_BE_16(buf + 4); @@ -439,7 +443,7 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input, frame_ext_header->crc = 0; } else { return 0; - } + } } else if (frame_ext_header->size == 10) { if (input->read (input, buf + 4, 10) == 10) { @@ -451,11 +455,11 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input, } } else { - lprintf("invalid ext header size: %d\n", frame_ext_header->size); + lprintf("invalid ext header size: %zu\n", frame_ext_header->size); return 0; } - lprintf("ext header: size: %d, flags: %X, padding_size: %d, crc: %d\n", + lprintf("ext header: size: %zu, flags: %X, padding_size: %d, crc: %d\n", frame_ext_header->size, frame_ext_header->flags, frame_ext_header->padding_size, frame_ext_header->crc); return 1; @@ -469,8 +473,11 @@ static int id3v23_interp_frame(input_plugin_t *input, id3v23_frame_header_t *frame_header) { char *buf; int enc; + const size_t bufsize = frame_header->size + 2; + if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */ + return 0; - buf = malloc(frame_header->size + 1); + buf = malloc(bufsize); if (buf == NULL) { lprintf("malloc error"); return 0; @@ -478,6 +485,7 @@ static int id3v23_interp_frame(input_plugin_t *input, if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -486,7 +494,7 @@ static int id3v23_interp_frame(input_plugin_t *input, case ( FOURCC_TAG('T', 'C', 'O', 'N') ): { char tmp[1024]; - + if (id3v2_parse_genre(tmp, buf + 1, 1024)) { _x_meta_info_set(stream, XINE_META_INFO_GENRE, tmp); } @@ -530,9 +538,9 @@ static int id3v23_interp_frame(input_plugin_t *input, } } -int id3v23_parse_tag(input_plugin_t *input, - xine_stream_t *stream, - int8_t *mp3_frame_header) { +static int id3v23_parse_tag(input_plugin_t *input, + xine_stream_t *stream, + int8_t *mp3_frame_header) { id3v2_header_t tag_header; id3v23_frame_header_t tag_frame_header; id3v23_frame_ext_header_t tag_frame_ext_header; @@ -542,15 +550,15 @@ int id3v23_parse_tag(input_plugin_t *input, if (tag_header.flags & ID3V23_ZERO_FLAG) { /* invalid flags */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid header flags (%02x)\n", tag_header.flags); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid header flags (%02x)\n", tag_header.flags); input->seek (input, tag_header.size - pos, SEEK_CUR); return 0; } if (tag_header.flags & ID3V23_UNSYNCH_FLAG) { /* unsynchronized tag: not supported */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: unsynchronized tags are not supported\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": unsynchronized tags are not supported\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 0; } @@ -559,38 +567,40 @@ int id3v23_parse_tag(input_plugin_t *input, if (!id3v23_parse_frame_ext_header(input, &tag_frame_ext_header)) { return 0; } + pos += tag_frame_ext_header.size; } /* frame parsing */ while ((pos + ID3V23_FRAME_HEADER_SIZE) <= tag_header.size) { if (id3v23_parse_frame_header(input, &tag_frame_header)) { pos += ID3V23_FRAME_HEADER_SIZE; - if (tag_frame_header.id && tag_frame_header.size) { + if (tag_frame_header.id) { if ((pos + tag_frame_header.size) <= tag_header.size) { if (!id3v23_interp_frame(input, stream, &tag_frame_header)) { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame content\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid frame content\n"); } } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame header\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid frame header\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } pos += tag_frame_header.size; } else { /* end of frames, the rest is padding */ - input->seek (input, tag_header.size - pos, SEEK_CUR); + lprintf("skipping padding %zu bytes\n", tag_header.size - pos); + input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: id3v2_parse_frame_header problem\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": id3v2_parse_frame_header problem\n"); return 0; } } return 1; } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "id3v23: id3v2_parse_header problem\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": id3v2_parse_header problem\n"); return 0; } } @@ -600,7 +610,7 @@ int id3v23_parse_tag(input_plugin_t *input, /* id3v2 "genre" parsing code. what a ugly format ! */ static int id3v24_parse_genre(char* dest, char *src, int len) { unsigned int index = 0; - + dest[0] = '\0'; if (sscanf(src, "%u", &index) == 1) { if (index < ID3_GENRE_COUNT) { @@ -621,10 +631,10 @@ static int id3v24_parse_frame_header(input_plugin_t *input, len = input->read (input, buf, ID3V24_FRAME_HEADER_SIZE); if (len == ID3V24_FRAME_HEADER_SIZE) { frame_header->id = _X_BE_32(buf); - frame_header->size = _X_BE_32_synchsafe(&buf[4]); + frame_header->size = _X_BE_32(&buf[4]); frame_header->flags = _X_BE_16(&buf[8]); - lprintf("frame: %c%c%c%c, size: %d, flags: %X\n", buf[0], buf[1], buf[2], buf[3], + lprintf("frame: %c%c%c%c, size: %zu, flags: %X\n", buf[0], buf[1], buf[2], buf[3], frame_header->size, frame_header->flags); return 1; @@ -638,8 +648,8 @@ static int id3v24_parse_ext_header(input_plugin_t *input, uint8_t buf[5]; if (input->read (input, buf, 4) == 4) { - - frame_ext_header->size = _X_BE_32_synchsafe(&buf[0]); + + frame_ext_header->size = _X_BE_32(&buf[0]); if (input->read (input, buf, 2) == 2) { uint8_t flags_size = buf[0]; @@ -704,7 +714,7 @@ static int id3v24_parse_ext_header(input_plugin_t *input, } else { return 0; } - lprintf("ext header: size: %d, flags: %X, crc: %d, restrictions: %8X\n", + lprintf("ext header: size: %zu, flags: %X, crc: %d, restrictions: %8X\n", frame_ext_header->size, frame_ext_header->flags, frame_ext_header->crc, frame_ext_header->restrictions); return 1; @@ -718,8 +728,11 @@ static int id3v24_interp_frame(input_plugin_t *input, id3v24_frame_header_t *frame_header) { char *buf; int enc; + const size_t bufsize = frame_header->size + 2; + if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */ + return 0; - buf = malloc(frame_header->size + 1); + buf = malloc(bufsize); if (buf == NULL) { lprintf("malloc error"); return 0; @@ -727,17 +740,18 @@ static int id3v24_interp_frame(input_plugin_t *input, if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; - + lprintf("data: %s\n", buf+1); switch (frame_header->id) { case ( FOURCC_TAG('T', 'C', 'O', 'N') ): { char tmp[1024]; - + if (id3v24_parse_genre(tmp, buf + 1, 1024)) { _x_meta_info_set(stream, XINE_META_INFO_GENRE, tmp); } @@ -757,6 +771,7 @@ static int id3v24_interp_frame(input_plugin_t *input, break; case ( FOURCC_TAG('T', 'Y', 'E', 'R') ): + case ( FOURCC_TAG('T', 'D', 'R', 'C') ): _x_meta_info_set_generic(stream, XINE_META_INFO_YEAR, buf + 1, id3_encoding[enc]); break; @@ -781,9 +796,9 @@ static int id3v24_interp_frame(input_plugin_t *input, } } -int id3v24_parse_tag(input_plugin_t *input, - xine_stream_t *stream, - int8_t *mp3_frame_header) { +static int id3v24_parse_tag(input_plugin_t *input, + xine_stream_t *stream, + int8_t *mp3_frame_header) { id3v2_header_t tag_header; id3v24_frame_header_t tag_frame_header; id3v24_frame_ext_header_t tag_frame_ext_header; @@ -793,8 +808,8 @@ int id3v24_parse_tag(input_plugin_t *input, if (tag_header.flags & ID3V24_ZERO_FLAG) { /* invalid flags */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid header flags (%02x)\n", tag_header.flags); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid header flags (%02x)\n", tag_header.flags); input->seek (input, tag_header.size - pos, SEEK_CUR); return 0; } @@ -809,20 +824,21 @@ int id3v24_parse_tag(input_plugin_t *input, if (!id3v24_parse_ext_header(input, &tag_frame_ext_header)) { return 0; } + pos += tag_frame_ext_header.size; } /* frame parsing */ while ((pos + ID3V24_FRAME_HEADER_SIZE) <= tag_header.size) { if (id3v24_parse_frame_header(input, &tag_frame_header)) { pos += ID3V24_FRAME_HEADER_SIZE; - if (tag_frame_header.id && tag_frame_header.size) { + if (tag_frame_header.id) { if ((pos + tag_frame_header.size) <= tag_header.size) { if (!id3v24_interp_frame(input, stream, &tag_frame_header)) { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame content\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid frame content\n"); } } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame header\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": invalid frame header\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } @@ -833,8 +849,8 @@ int id3v24_parse_tag(input_plugin_t *input, return 1; } } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: id3v2_parse_frame_header problem\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + LOG_MODULE ": id3v2_parse_frame_header problem\n"); return 0; } } @@ -844,7 +860,7 @@ int id3v24_parse_tag(input_plugin_t *input, } return 1; } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "id3v23: id3v2_parse_header problem\n"); + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": id3v2_parse_header problem\n"); return 0; } } @@ -858,22 +874,22 @@ int id3v2_parse_tag(input_plugin_t *input, switch(mp3_frame_header[3]) { case 2: - xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.2 tag\n"); + xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": ID3V2.2 tag\n"); result = id3v22_parse_tag(input, stream, mp3_frame_header); break; - + case 3: - xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.3 tag\n"); + xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": ID3V2.3 tag\n"); result = id3v23_parse_tag(input, stream, mp3_frame_header); break; case 4: - xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.4 tag\n"); + xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": ID3V2.4 tag\n"); result = id3v24_parse_tag(input, stream, mp3_frame_header); break; default: - xprintf(stream->xine, XINE_VERBOSITY_LOG, "Unknown ID3v2 version: 0x%02x.\n", mp3_frame_header[3]); + xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": Unknown ID3v2 version: 0x%02x.\n", mp3_frame_header[3]); } return result; diff --git a/src/demuxers/id3.h b/src/demuxers/id3.h index b4ea4b6be..41babe2b4 100644 --- a/src/demuxers/id3.h +++ b/src/demuxers/id3.h @@ -103,22 +103,22 @@ typedef struct { uint32_t id; uint8_t revision; uint8_t flags; - uint32_t size; + size_t size; } id3v2_header_t; typedef struct { uint32_t id; - uint32_t size; + size_t size; } id3v22_frame_header_t; typedef struct { uint32_t id; - uint32_t size; + size_t size; uint16_t flags; } id3v23_frame_header_t; typedef struct { - uint32_t size; + size_t size; uint16_t flags; uint32_t padding_size; uint32_t crc; @@ -128,12 +128,12 @@ typedef id3v2_header_t id3v24_footer_t; typedef struct { uint32_t id; - uint32_t size; + size_t size; uint16_t flags; } id3v24_frame_header_t; typedef struct { - uint32_t size; + size_t size; uint8_t flags; uint32_t crc; uint8_t restrictions; @@ -151,19 +151,16 @@ typedef struct { int id3v1_parse_tag (input_plugin_t *input, xine_stream_t *stream); -int id3v22_parse_tag(input_plugin_t *input, - xine_stream_t *stream, - int8_t *mp3_frame_header); - -int id3v23_parse_tag(input_plugin_t *input, - xine_stream_t *stream, - int8_t *mp3_frame_header); - -int id3v24_parse_tag(input_plugin_t *input, - xine_stream_t *stream, - int8_t *mp3_frame_header); - -/* Generic function that switch between the three above */ +/** + * @brief Generic function for ID3v2 tags parsing. + * @param input Pointer to the input plugin used by the demuxer, used + * to access the tag's data. + * @param stream Pointer to the xine stream currently being read. + * @param mp3_frame_header Header of the MP3 frame carrying the tag. + * + * @note This function will take care of calling the proper function for + * parsing ID3v2.2, ID3v2.3 or ID3v2.4 tags. + */ int id3v2_parse_tag(input_plugin_t *input, xine_stream_t *stream, int8_t *mp3_frame_header); diff --git a/src/demuxers/iff.h b/src/demuxers/iff.h index 94830f69c..8ac24a697 100644 --- a/src/demuxers/iff.h +++ b/src/demuxers/iff.h @@ -27,8 +27,8 @@ #define IFFP_IFF_H #define IFF_OKAY 0L -#define CLIENT_ERROR 1L -#define NOFILE 5L +#define IFF_CLIENT_ERROR 1L +#define IFF_NOFILE 5L #define FOURCC_CHUNK BE_FOURCC #define IFF_16SV_CHUNK FOURCC_CHUNK('1', '6', 'S', 'V') diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h index 6806c207d..0a8226319 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2007 the xine project + * Copyright (C) 2000-2009 the xine project * * This file is part of xine, a free video player. * @@ -16,6 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Matroska EBML stream handling */ #ifndef MATROSKA_H #define MATROSKA_H @@ -62,6 +64,7 @@ #define MATROSKA_ID_CL_BLOCKGROUP 0xA0 #define MATROSKA_ID_CL_BLOCK 0xA1 #define MATROSKA_ID_CL_BLOCKVIRTUAL 0xA2 +#define MATROSKA_ID_CL_SIMPLEBLOCK 0xA3 #define MATROSKA_ID_CL_BLOCKADDITIONS 0x75A1 #define MATROSKA_ID_CL_BLOCKMORE 0xA6 #define MATROSKA_ID_CL_BLOCKADDID 0xEE @@ -168,10 +171,16 @@ /* Chapters */ #define MATROSKA_ID_CHAPTERS 0x1043A770 #define MATROSKA_ID_CH_EDITIONENTRY 0x45B9 +#define MATROSKA_ID_CH_ED_UID 0x45BC +#define MATROSKA_ID_CH_ED_HIDDEN 0x45BD +#define MATROSKA_ID_CH_ED_DEFAULT 0x45DB +#define MATROSKA_ID_CH_ED_ORDERED 0x45DD #define MATROSKA_ID_CH_ATOM 0xB6 #define MATROSKA_ID_CH_UID 0x73C4 #define MATROSKA_ID_CH_TIMESTART 0x91 #define MATROSKA_ID_CH_TIMEEND 0x92 +#define MATROSKA_ID_CH_HIDDEN 0x98 +#define MATROSKA_ID_CH_ENABLED 0x4598 #define MATROSKA_ID_CH_TRACK 0x8F #define MATROSKA_ID_CH_TRACKNUMBER 0x89 #define MATROSKA_ID_CH_DISPLAY 0x80 @@ -182,6 +191,46 @@ /* Tags */ #define MATROSKA_ID_TAGS 0x1254C367 +/* Chapter (used in tracks) */ +typedef struct { + uint64_t uid; + uint64_t time_start; + uint64_t time_end; + /* if not 0, the chapter could e.g. be used for skipping, but not + * be shown in the chapter list */ + int hidden; + /* disabled chapters should be skipped during playback (using this + * would require parsing control blocks) */ + int enabled; + /* Tracks this chapter belongs to. + * Remember that elements can occur in any order, so in theory the + * chapters could become available before the tracks do. + * TODO: currently unused + */ + /* uint64_t* tracks; */ + /* Chapter titles and locale information + * TODO: chapters can have multiple sets of those, i.e. several tuples + * (title, language, country). The current implementation picks from + * those by the following rules: + * 1) remember the first element + * 2) overwrite with an element where language=="eng" + */ + char* title; + char* language; + char* country; +} matroska_chapter_t; + +/* Edition */ +typedef struct { + uint64_t uid; + unsigned int hidden; + unsigned int is_default; + unsigned int ordered; + + int num_chapters, cap_chapters; + matroska_chapter_t** chapters; +} matroska_edition_t; + /* Matroska Track */ typedef struct { int flag_interlaced; @@ -213,7 +262,8 @@ typedef struct { typedef struct matroska_track_s matroska_track_t; struct matroska_track_s { int track_num; - + uint64_t uid; + uint32_t track_type; uint64_t default_duration; char *language; @@ -222,7 +272,7 @@ struct matroska_track_s { uint32_t codec_private_len; int default_flag; uint32_t compress_algo; - + uint32_t buf_type; fifo_buffer_t *fifo; @@ -235,7 +285,7 @@ struct matroska_track_s { void (*handle_content) (demux_plugin_t *this_gen, matroska_track_t *track, int decoder_flags, - uint8_t *data, int data_len, + uint8_t *data, size_t data_len, int64_t data_pts, int data_duration, int input_normpos, int input_time); }; diff --git a/src/demuxers/qtpalette.h b/src/demuxers/qtpalette.h index a8a44e916..422b570a9 100644 --- a/src/demuxers/qtpalette.h +++ b/src/demuxers/qtpalette.h @@ -11,7 +11,7 @@ static const unsigned char qt_default_palette_4[4 * 4] = { 0x93, 0x65, 0x5E, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xDF, 0xD0, 0xAB, 0x00, - 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00 }; static const unsigned char qt_default_palette_16[16 * 4] = { @@ -30,7 +30,7 @@ static const unsigned char qt_default_palette_16[16 * 4] = { 0xFF, 0xFB, 0xF9, 0x00, 0xE8, 0xCA, 0xC5, 0x00, 0x8A, 0x7C, 0x77, 0x00, - 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00 }; static const unsigned char qt_default_palette_256[256 * 4] = { diff --git a/src/demuxers/real_common.h b/src/demuxers/real_common.h new file mode 100644 index 000000000..4945a65ff --- /dev/null +++ b/src/demuxers/real_common.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + */ + +static inline void demux_real_sipro_swap (char buffer[], int bs) +{ + /* bs = nybbles per subpacket */ + static const unsigned char sipr_swaps[38][2] = { + {0, 63}, {1, 22}, {2, 44}, {3, 90}, {5, 81}, {7, 31}, {8, 86}, {9, 58}, + {10, 36}, {12, 68}, {13, 39}, {14, 73}, {15, 53}, {16, 69}, {17, 57}, + {19, 88}, {20, 34}, {21, 71}, {24, 46}, {25, 94}, {26, 54}, {28, 75}, + {29, 50}, {32, 70}, {33, 92}, {35, 74}, {38, 85}, {40, 56}, {42, 87}, + {43, 65}, {45, 59}, {48, 79}, {49, 93}, {51, 89}, {55, 95}, {61, 76}, + {67, 83}, {77, 80} + }; + int n; + + for (n = 0; n < 38; ++n) + { + int j; + int i = bs * sipr_swaps[n][0]; + int o = bs * sipr_swaps[n][1]; + /* swap nibbles of block 'i' with 'o' TODO: optimize */ + for (j = 0; j < bs; ++j) + { + int x = (i & 1) ? (buffer[i >> 1] >> 4) : (buffer[i >> 1] & 0x0F); + int y = (o & 1) ? (buffer[o >> 1] >> 4) : (buffer[o >> 1] & 0x0F); + if (o & 1) + buffer[o >> 1] = (buffer[o >> 1] & 0x0F) | (x << 4); + else + buffer[o >> 1] = (buffer[o >> 1] & 0xF0) | x; + if (i & 1) + buffer[i >> 1] = (buffer[i >> 1] & 0x0F) | (y << 4); + else + buffer[i >> 1] = (buffer[i >> 1] & 0xF0) | y; + ++i; + ++o; + } + } +} diff --git a/src/dxr3/Makefile.am b/src/dxr3/Makefile.am index f1a61ce12..f6beb521a 100644 --- a/src/dxr3/Makefile.am +++ b/src/dxr3/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(X_CFLAGS) $(LIBFAME_CFLAGS) @@ -5,7 +6,7 @@ AM_CFLAGS = $(X_CFLAGS) $(LIBFAME_CFLAGS) if HAVE_DXR3 dxr3_modules = xineplug_decode_dxr3_video.la \ xineplug_decode_dxr3_spu.la \ - xineplug_vo_out_dxr3.la + xineplug_vo_out_dxr3.la endif if HAVE_X11 link_x_libs = $(X_LIBS) -lXext @@ -17,7 +18,7 @@ if HAVE_LIBRTE link_rte = -lrte endif -xineplug_LTLIBRARIES = $(dxr3_modules) +xineplug_LTLIBRARIES = $(dxr3_modules) xineplug_decode_dxr3_video_la_SOURCES = dxr3_decode_video.c xineplug_decode_dxr3_video_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) @@ -40,7 +41,7 @@ xineplug_vo_out_dxr3_la_SOURCES = \ dxr3_mpeg_encoders.c \ dxr3_spu_encoder.c \ dxr3_scr.c \ - video_out_dxr3.c + video_out_dxr3.c xineplug_vo_out_dxr3_la_LIBADD = $(XINE_LIB) $(link_fame) $(link_rte) $(link_x_libs) $(LTLIBINTL) $(DYNAMIC_LD_LIBS) -lm xineplug_vo_out_dxr3_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) diff --git a/src/dxr3/dxr3.h b/src/dxr3/dxr3.h index f08ddcd04..78e74a7b4 100644 --- a/src/dxr3/dxr3.h +++ b/src/dxr3/dxr3.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/dxr3/dxr3_decode_spu.c b/src/dxr3/dxr3_decode_spu.c index 139939d8e..7682455eb 100644 --- a/src/dxr3/dxr3_decode_spu.c +++ b/src/dxr3/dxr3_decode_spu.c @@ -1,23 +1,27 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* dxr3 spu decoder plugin. * Accepts the spu data from xine and sends it directly to the * corresponding dxr3 device. Also handles dvd menu button highlights. @@ -72,7 +76,7 @@ static const decoder_info_t dxr3_spudec_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_SPU_DECODER, 16, "dxr3-spudec", XINE_VERSION_CODE, &dxr3_spudec_info, &dxr3_spudec_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; @@ -110,7 +114,7 @@ struct pci_node_s { typedef struct dxr3_spudec_class_s { spu_decoder_class_t spu_decoder_class; - + int instance; /* we allow only one instance of this plugin */ } dxr3_spudec_class_t; @@ -120,10 +124,10 @@ typedef struct dxr3_spudec_s { xine_stream_t *stream; dxr3_driver_t *dxr3_vo; /* we need to talk to the video out */ xine_event_queue_t *event_queue; - + int devnum; int fd_spu; /* to access the dxr3 spu device */ - + dxr3_spu_stream_state_t spu_stream_state[MAX_SPU_STREAMS]; uint32_t clut[16]; /* the current color lookup table */ int menu; /* are we in a menu? */ @@ -131,7 +135,7 @@ typedef struct dxr3_spudec_s { pci_node_t pci_cur; /* a list of PCI packs, with the list head being current */ pthread_mutex_t pci_lock; uint32_t buttonN; /* currently highlighted button */ - + int anamorphic; /* this is needed to detect anamorphic menus */ } dxr3_spudec_t; @@ -150,7 +154,7 @@ static inline int dxr3_present(xine_stream_t *stream) plugin_node_t *node; video_driver_class_t *vo_class; int present = 0; - + if (stream->video_driver && stream->video_driver->node) { node = (plugin_node_t *)stream->video_driver->node; if (node->plugin_class) { @@ -177,7 +181,7 @@ static inline void dxr3_spudec_clear_nav_list(dxr3_spudec_t *this) static inline void dxr3_spudec_update_nav(dxr3_spudec_t *this) { metronom_clock_t *clock = this->stream->xine->clock; - + if (this->pci_cur.next && this->pci_cur.next->vpts <= clock->get_current_time(clock)) { pci_node_t *node = this->pci_cur.next; xine_fast_memcpy(&this->pci_cur, this->pci_cur.next, sizeof(pci_node_t)); @@ -197,17 +201,17 @@ static inline void dxr3_swab_clut(int *clut) static void *dxr3_spudec_init_plugin(xine_t *xine, void* data) { dxr3_spudec_class_t *this; - - this = (dxr3_spudec_class_t *)xine_xmalloc(sizeof(dxr3_spudec_class_t)); + + this = calloc(1, sizeof(dxr3_spudec_class_t)); if (!this) return NULL; - + this->spu_decoder_class.open_plugin = dxr3_spudec_open_plugin; this->spu_decoder_class.get_identifier = dxr3_spudec_get_identifier; this->spu_decoder_class.get_description = dxr3_spudec_get_description; this->spu_decoder_class.dispose = dxr3_spudec_class_dispose; - + this->instance = 0; - + return &this->spu_decoder_class; } @@ -217,20 +221,20 @@ static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xi dxr3_spudec_t *this; dxr3_spudec_class_t *class = (dxr3_spudec_class_t *)class_gen; char tmpstr[128]; - + if (class->instance) return NULL; if (!dxr3_present(stream)) return NULL; - - this = (dxr3_spudec_t *)xine_xmalloc(sizeof(dxr3_spudec_t)); + + this = calloc(1, sizeof(dxr3_spudec_t)); if (!this) return NULL; - + this->spu_decoder.decode_data = dxr3_spudec_decode_data; this->spu_decoder.reset = dxr3_spudec_reset; this->spu_decoder.discontinuity = dxr3_spudec_discontinuity; this->spu_decoder.dispose = dxr3_spudec_dispose; this->spu_decoder.get_interact_info = dxr3_spudec_interact_info; this->spu_decoder.set_button = dxr3_spudec_set_button; - + this->class = class; this->stream = stream; /* We need to talk to dxr3 video out to coordinate spus and overlays */ @@ -239,7 +243,7 @@ static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xi this->devnum = stream->xine->config->register_num(stream->xine->config, CONF_KEY, 0, CONF_NAME, CONF_HELP, 10, NULL, NULL); - + pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); if (this->dxr3_vo->fd_spu) this->fd_spu = this->dxr3_vo->fd_spu; @@ -247,7 +251,7 @@ static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xi /* open dxr3 spu device */ snprintf(tmpstr, sizeof(tmpstr), "/dev/em8300_sp-%d", this->devnum); if ((this->fd_spu = open(tmpstr, O_WRONLY)) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("dxr3_decode_spu: Failed to open spu device %s (%s)\n"), tmpstr, strerror(errno)); pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); free(this); @@ -259,19 +263,19 @@ static spu_decoder_t *dxr3_spudec_open_plugin(spu_decoder_class_t *class_gen, xi this->dxr3_vo->fd_spu = this->fd_spu; } pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); - + this->menu = 0; this->button_filter = 1; this->pci_cur.pci.hli.hl_gi.hli_ss = 0; this->pci_cur.next = NULL; this->buttonN = 1; - + this->anamorphic = 0; - + pthread_mutex_init(&this->pci_lock, NULL); - + class->instance = 1; - + return &this->spu_decoder; } @@ -299,11 +303,11 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) dxr3_spu_stream_state_t *state = &this->spu_stream_state[stream_id]; uint32_t spu_channel = this->stream->spu_channel; xine_event_t *event; - + /* handle queued events */ while ((event = xine_event_get(this->event_queue))) { llprintf(LOG_SPU, "event caught: SPU_FD = %i\n",this->fd_spu); - + switch (event->type) { case XINE_EVENT_FRAME_FORMAT_CHANGE: /* we are in anamorphic mode, if the frame is 16:9, but not pan&scan'ed */ @@ -313,17 +317,17 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) llprintf(LOG_BTN, "anamorphic mode %s\n", this->anamorphic ? "on" : "off"); break; } - + xine_event_free(event); } - + /* check, if we need to process the next PCI from the list */ pthread_mutex_lock(&this->pci_lock); dxr3_spudec_update_nav(this); pthread_mutex_unlock(&this->pci_lock); - + if ( (buf->type & 0xffff0000) != BUF_SPU_DVD || - !(buf->decoder_flags & BUF_FLAG_SPECIAL) || + !(buf->decoder_flags & BUF_FLAG_SPECIAL) || buf->decoder_info[1] != BUF_SPECIAL_SPU_DVD_SUBTYPE ) return; @@ -333,7 +337,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) dxr3_swab_clut((int *)buf->content); pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, buf->content)) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: failed to set CLUT (%s)\n", strerror(errno)); /* remember clut, when video out places some overlay we may need to restore it */ memcpy(this->clut, buf->content, 16 * sizeof(uint32_t)); @@ -343,20 +347,20 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) } if (buf->decoder_info[2] == SPU_DVD_SUBTYPE_NAV) { uint8_t *p = buf->content; - + llprintf(LOG_BTN, "got NAV packet\n"); pthread_mutex_lock(&this->pci_lock); - + /* just watch out for menus */ if (p[3] == 0xbf && p[6] == 0x00) { /* Private stream 2 */ pci_t pci; - + navRead_PCI(&pci, p + 7); llprintf(LOG_BTN, "PCI packet hli_ss is %d\n", pci.hli.hl_gi.hli_ss); - + if (pci.hli.hl_gi.hli_ss == 1) { /* menu ahead */ - + /* NAV packets contain start and end presentation timestamps, which tell the * application, when the highlight information in the NAV is supposed to be valid. * We handle these timestamps only in a very stripped-down way: We keep a list @@ -374,7 +378,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) printf("dxr3_decode_spu: DEBUG: allocating new PCI node for hli_s_ptm %d\n", pci.hli.hl_gi.hli_s_ptm); /* append PCI at the end of the list */ while (node->next) node = node->next; - node->next = (pci_node_t *)xine_xmalloc(sizeof(pci_node_t)); + node->next = calloc(1, sizeof(pci_node_t)); node->next->vpts = this->stream->metronom->got_spu_packet(this->stream->metronom, pci.hli.hl_gi.hli_s_ptm); node->next->next = NULL; xine_fast_memcpy(&node->next->pci, &pci, sizeof(pci_t)); @@ -385,7 +389,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) dxr3_spudec_process_nav(this); } } - + if ((pci.hli.hl_gi.hli_ss == 0) && (this->pci_cur.pci.hli.hl_gi.hli_ss == 1)) { /* this is (or: should be, I hope I got this right) a subpicture plane, that hides all menu buttons */ @@ -409,7 +413,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) pthread_mutex_unlock(&this->pci_lock); return; } - + /* We parse the SPUs command and end sequence here for two reasons: * 1. Look for the display duration entry in the spu packets. * If the spu is a menu button highlight pane, this entry must not exist, @@ -490,7 +494,7 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) if (state->spu_length < 0) state->spu_length = 0; state->bytes_passed += buf->size; } - + /* filter unwanted streams */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) { llprintf(LOG_SPU, "Dropping SPU channel %d. Preview data\n", stream_id); @@ -508,43 +512,43 @@ static void dxr3_spudec_decode_data(spu_decoder_t *this_gen, buf_element_t *buf) /* We used to filter for SPU forcing here as well, but this does not work * this way with the DXR3, because we have to evaluate the SPU command sequence * to detect, if a particular SPU is forced or not. See the parsing code above. */ - + pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); - + /* write sync timestamp to the card */ if (buf->pts) { int64_t vpts; uint32_t vpts32; - + vpts = this->stream->metronom->got_spu_packet(this->stream->metronom, buf->pts); llprintf(LOG_PTS, "pts = %" PRId64 " vpts = %" PRIu64 "\n", buf->pts, vpts); vpts32 = vpts; if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPTS, &vpts32)) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: spu setpts failed (%s)\n", strerror(errno)); } - + /* has video out tampered with our palette */ if (this->dxr3_vo->clut_cluttered) { if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, this->clut)) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: failed to set CLUT (%s)\n", strerror(errno)); this->dxr3_vo->clut_cluttered = 0; } - + /* write spu data to the card */ llprintf(LOG_SPU, "write: SPU_FD = %i\n",this->fd_spu); written = write(this->fd_spu, buf->content, buf->size); if (written < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: spu device write failed (%s)\n", strerror(errno)); pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); return; } if (written != buf->size) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: Could only write %zd of %d spu bytes.\n", written, buf->size); - + pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); } @@ -552,7 +556,7 @@ static void dxr3_spudec_reset(spu_decoder_t *this_gen) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; int i; - + for (i = 0; i < MAX_SPU_STREAMS; i++) this->spu_stream_state[i].spu_length = 0; pthread_mutex_lock(&this->pci_lock); @@ -563,7 +567,7 @@ static void dxr3_spudec_reset(spu_decoder_t *this_gen) static void dxr3_spudec_discontinuity(spu_decoder_t *this_gen) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - + pthread_mutex_lock(&this->pci_lock); dxr3_spudec_clear_nav_list(this); pthread_mutex_unlock(&this->pci_lock); @@ -578,7 +582,7 @@ static void dxr3_spudec_dispose(spu_decoder_t *this_gen) 0x00, 0x01, 0x06, 0x00, 0x04, 0x00, 0x07, 0xFF, 0x00, 0x01, 0x00, 0x20, 0x02, 0xFF }; dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - + llprintf(LOG_SPU, "close: SPU_FD = %i\n",this->fd_spu); pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); /* clear any remaining spu */ @@ -588,7 +592,7 @@ static void dxr3_spudec_dispose(spu_decoder_t *this_gen) this->fd_spu = 0; this->dxr3_vo->fd_spu = 0; pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); - + dxr3_spudec_clear_nav_list(this); xine_event_dispose_queue(this->event_queue); pthread_mutex_destroy(&this->pci_lock); @@ -599,7 +603,7 @@ static void dxr3_spudec_dispose(spu_decoder_t *this_gen) static int dxr3_spudec_interact_info(spu_decoder_t *this_gen, void *data) { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; - + pthread_mutex_lock(&this->pci_lock); dxr3_spudec_update_nav(this); memcpy(data, &this->pci_cur.pci, sizeof(pci_t)); @@ -611,7 +615,7 @@ static void dxr3_spudec_set_button(spu_decoder_t *this_gen, int32_t button, int3 { dxr3_spudec_t *this = (dxr3_spudec_t *)this_gen; em8300_button_t btn; - + llprintf(LOG_BTN, "setting button\n"); this->buttonN = button; pthread_mutex_lock(&this->pci_lock); @@ -620,7 +624,7 @@ static void dxr3_spudec_set_button(spu_decoder_t *this_gen, int32_t button, int3 (dxr3_spudec_copy_nav_to_btn(this, mode - 1, &btn ) > 0)) { pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: failed to set spu button (%s)\n", strerror(errno)); pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); } @@ -635,7 +639,7 @@ static void dxr3_spudec_set_button(spu_decoder_t *this_gen, int32_t button, int3 static void dxr3_spudec_process_nav(dxr3_spudec_t *this) { em8300_button_t btn; - + this->menu = 1; this->button_filter = 0; if (this->pci_cur.pci.hli.hl_gi.fosl_btnn > 0) { @@ -651,15 +655,15 @@ static void dxr3_spudec_process_nav(dxr3_spudec_t *this) if ((dxr3_spudec_copy_nav_to_btn(this, 0, &btn ) > 0)) { pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: failed to set spu button (%s)\n", strerror(errno)); pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); } else { /* current button does not exist -> use another one */ xine_event_t event; - + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("requested button not available\n")); - + if (this->buttonN > this->pci_cur.pci.hli.hl_gi.btn_ns) this->buttonN = this->pci_cur.pci.hli.hl_gi.btn_ns; else @@ -669,11 +673,11 @@ static void dxr3_spudec_process_nav(dxr3_spudec_t *this) event.data = &this->buttonN; event.data_length = sizeof(this->buttonN); xine_event_send(this->stream, &event); - + if ((dxr3_spudec_copy_nav_to_btn(this, 0, &btn ) > 0)) { pthread_mutex_lock(&this->dxr3_vo->spu_device_lock); if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: failed to set spu button (%s)\n", strerror(errno)); pthread_mutex_unlock(&this->dxr3_vo->spu_device_lock); } else { @@ -685,10 +689,10 @@ static void dxr3_spudec_process_nav(dxr3_spudec_t *this) static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300_button_t *btn) { btni_t *button_ptr = NULL; - + if ((this->buttonN <= 0) || (this->buttonN > this->pci_cur.pci.hli.hl_gi.btn_ns)) return -1; - + /* choosing a button from a matching button group */ if (this->anamorphic && !this->dxr3_vo->widescreen_enabled && @@ -696,7 +700,7 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300 this->stream->spu_channel_letterbox != this->stream->spu_channel && this->stream->spu_channel_letterbox >= 0) { unsigned int btns_per_group = 36 / this->pci_cur.pci.hli.hl_gi.btngr_ns; - + /* use a letterbox button group for letterboxed anamorphic menus on tv out */ if (!button_ptr && this->pci_cur.pci.hli.hl_gi.btngr_ns >= 1 && (this->pci_cur.pci.hli.hl_gi.btngr1_dsp_ty & 2)) button_ptr = &this->pci_cur.pci.hli.btnit[0 * btns_per_group + this->buttonN - 1]; @@ -704,13 +708,13 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300 button_ptr = &this->pci_cur.pci.hli.btnit[1 * btns_per_group + this->buttonN - 1]; if (!button_ptr && this->pci_cur.pci.hli.hl_gi.btngr_ns >= 3 && (this->pci_cur.pci.hli.hl_gi.btngr3_dsp_ty & 2)) button_ptr = &this->pci_cur.pci.hli.btnit[2 * btns_per_group + this->buttonN - 1]; - + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "No suitable letterbox button group found.\n"); _x_assert(button_ptr); - + } else { unsigned int btns_per_group = 36 / this->pci_cur.pci.hli.hl_gi.btngr_ns; - + /* otherwise use a normal 4:3 or widescreen button group */ if (!button_ptr && this->pci_cur.pci.hli.hl_gi.btngr_ns >= 1 && !(this->pci_cur.pci.hli.hl_gi.btngr1_dsp_ty & 6)) button_ptr = &this->pci_cur.pci.hli.btnit[0 * btns_per_group + this->buttonN - 1]; @@ -718,14 +722,14 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300 button_ptr = &this->pci_cur.pci.hli.btnit[1 * btns_per_group + this->buttonN - 1]; if (!button_ptr && this->pci_cur.pci.hli.hl_gi.btngr_ns >= 3 && !(this->pci_cur.pci.hli.hl_gi.btngr3_dsp_ty & 6)) button_ptr = &this->pci_cur.pci.hli.btnit[2 * btns_per_group + this->buttonN - 1]; - + } if (!button_ptr) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: No suitable menu button group found, using group 1.\n"); button_ptr = &this->pci_cur.pci.hli.btnit[this->buttonN - 1]; } - + if(button_ptr->btn_coln != 0) { llprintf(LOG_BTN, "normal button clut, mode %d\n", mode); btn->color = (this->pci_cur.pci.hli.btn_colit.btn_coli[button_ptr->btn_coln-1][mode] >> 16); @@ -735,7 +739,7 @@ static int dxr3_spudec_copy_nav_to_btn(dxr3_spudec_t *this, int32_t mode, em8300 btn->right = button_ptr->x_end; btn->bottom = button_ptr->y_end; return 1; - } + } return -1; } diff --git a/src/dxr3/dxr3_decode_video.c b/src/dxr3/dxr3_decode_video.c index 3f1c273ff..75a371566 100644 --- a/src/dxr3/dxr3_decode_video.c +++ b/src/dxr3/dxr3_decode_video.c @@ -1,23 +1,27 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* dxr3 video decoder plugin. * Accepts the video data from xine and sends it directly to the * corresponding dxr3 device. Takes precedence over the libmpeg2 @@ -73,7 +77,7 @@ static const decoder_info_t dxr3_video_decoder_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "dxr3-mpeg2", XINE_VERSION_CODE, &dxr3_video_decoder_info, &dxr3_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; @@ -95,9 +99,9 @@ static void dxr3_dispose(video_decoder_t *this_gen); /* plugin structures */ typedef struct dxr3_decoder_class_s { video_decoder_class_t video_decoder_class; - + int instance; /* we allow only one instance of this plugin */ - + metronom_clock_t *clock; /* used for syncing */ } dxr3_decoder_class_t; @@ -106,11 +110,11 @@ typedef struct dxr3_decoder_s { dxr3_decoder_class_t *class; xine_stream_t *stream; dxr3_scr_t *scr; /* shortcut to the scr plugin in the dxr3 video out */ - + int devnum; int fd_control; int fd_video; /* to access the dxr3 devices */ - + int have_header_info; int sequence_open; int width; @@ -119,26 +123,26 @@ typedef struct dxr3_decoder_s { int aspect_code; int frame_rate_code; int repeat_first_field; /* mpeg stream header data */ - + int force_aspect; /* when input plugin has better info, we are forced */ int force_pan_scan; /* to use a certain aspect or to do pan&scan */ - + int use_panscan; int panscan_smart_change; int afd_smart_change; int afd_code; /* use pan&scan info if present in stream */ - + int last_width; int last_height; int last_aspect_code; /* used to detect changes for event sending */ - + unsigned int dts_offset[3]; int sync_every_frame; int sync_retry; int enhanced_mode; int resync_window; int skip_count; /* syncing parameters */ - + int correct_durations; int64_t last_vpts; int force_duration_window; @@ -164,7 +168,7 @@ static inline int dxr3_present(xine_stream_t *stream) plugin_node_t *node; video_driver_class_t *vo_class; int present = 0; - + if (stream->video_driver && stream->video_driver->node) { node = (plugin_node_t *)stream->video_driver->node; if (node->plugin_class) { @@ -180,11 +184,11 @@ static inline int dxr3_present(xine_stream_t *stream) static inline int dxr3_mvcommand(int fd_control, int command) { em8300_register_t reg; - + reg.microcode_register = 1; reg.reg = 0; reg.val = command; - + return ioctl(fd_control, EM8300_IOCTL_WRITEREG, ®); } @@ -192,19 +196,19 @@ static inline int dxr3_mvcommand(int fd_control, int command) static void *dxr3_init_plugin(xine_t *xine, void *data) { dxr3_decoder_class_t *this; - - this = (dxr3_decoder_class_t *)xine_xmalloc(sizeof (dxr3_decoder_class_t)); + + this = calloc(1, sizeof (dxr3_decoder_class_t)); if (!this) return NULL; - + this->video_decoder_class.open_plugin = dxr3_open_plugin; this->video_decoder_class.get_identifier = dxr3_get_identifier; this->video_decoder_class.get_description = dxr3_get_description; this->video_decoder_class.dispose = dxr3_class_dispose; - + this->instance = 0; - + this->clock = xine->clock; - + return &this->video_decoder_class; } @@ -216,40 +220,40 @@ static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_ dxr3_decoder_class_t *class = (dxr3_decoder_class_t *)class_gen; config_values_t *cfg; char tmpstr[128]; - + if (class->instance) return NULL; if (!dxr3_present(stream)) return NULL; - - this = (dxr3_decoder_t *)xine_xmalloc(sizeof (dxr3_decoder_t)); + + this = calloc(1, sizeof (dxr3_decoder_t)); if (!this) return NULL; - + cfg = stream->xine->config; - + this->video_decoder.decode_data = dxr3_decode_data; this->video_decoder.reset = dxr3_reset; this->video_decoder.discontinuity = dxr3_discontinuity; this->video_decoder.flush = dxr3_flush; this->video_decoder.dispose = dxr3_dispose; - + this->class = class; this->stream = stream; this->scr = NULL; - + this->devnum = cfg->register_num(cfg, CONF_KEY, 0, CONF_NAME, CONF_HELP, 10, NULL, NULL); - + snprintf(tmpstr, sizeof(tmpstr), "/dev/em8300-%d", this->devnum); llprintf(LOG_VID, "Entering video init, devname=%s.\n",tmpstr); - + /* open later, because dxr3_video_out might have it open until we request a frame */ this->fd_video = -1; - + if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("dxr3_decode_video: Failed to open control device %s (%s)\n"), tmpstr, strerror(errno)); free(this); return NULL; } - + this->use_panscan = cfg->register_enum(cfg, "dxr3.use_panscan", 0, panscan_types, _("use Pan & Scan info"), _("\"Pan & Scan\" is a special display mode which is sometimes used in MPEG " @@ -262,14 +266,14 @@ static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_ "Enable Pan & Scan based on information embedded in DVB streams. This makes " "use of the Active Format Descriptor (AFD) used in some European DVB channels."), 10, dxr3_update_panscan, this); - + this->dts_offset[0] = 21600; this->dts_offset[1] = 21600; this->dts_offset[2] = 21600; - + this->force_duration_window = -FORCE_DURATION_WINDOW_SIZE; this->last_vpts = this->class->clock->get_current_time(this->class->clock); - + this->sync_every_frame = cfg->register_bool(cfg, "dxr3.playback.sync_every_frame", 0, _("try to sync video every frame"), _("Tries to set a synchronization timestamp for every frame. " @@ -288,14 +292,14 @@ static video_decoder_t *dxr3_open_plugin(video_decoder_class_t *class_gen, xine_ "correction for NTSC streams erroneously labeled as PAL " "streams is implemented. Enable only, when you encounter such streams."), 0, dxr3_update_correct_durations, this); - + /* the dxr3 needs a longer prebuffering to have time for its internal decoding */ this->stream->metronom->set_option(this->stream->metronom, METRONOM_PREBUFFER, 90000); - + (stream->video_out->open) (stream->video_out, stream); - + class->instance = 1; - + return &this->video_decoder; } @@ -313,7 +317,7 @@ static void dxr3_class_dispose(video_decoder_class_t *class_gen) { free(class_gen); } - + static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) { @@ -324,9 +328,9 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) vo_frame_t *img; uint8_t *buffer, byte; uint32_t shift; - + vpts = 0; - + /* handle aspect hints from xine-dvdnav */ if (buf->decoder_flags & BUF_FLAG_SPECIAL) { if (buf->decoder_info[1] == BUF_SPECIAL_ASPECT) { @@ -338,12 +342,12 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) this->force_pan_scan = 0; frame_format_change(this); - + this->last_aspect_code = this->aspect_code; } return; } - + /* parse frames in the buffer handed in, evaluate headers, * send frames to video_out and handle some syncing */ @@ -357,7 +361,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) } /* header code of some kind found */ shift = 0xffffff00; - + if (byte == 0xb2) { /* check for AFD data */ if (buffer + 5 < buf->content + buf->size) { @@ -446,7 +450,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) continue; if (buf->decoder_flags & BUF_FLAG_PREVIEW) continue; - + /* pretend like we have decoded a frame */ img = this->stream->video_out->get_frame(this->stream->video_out, this->width, this->height, this->ratio, @@ -454,20 +458,20 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) img->pts = buf->pts; img->bad_frame = 0; img->duration = get_duration(this); - + skip = img->draw(img, this->stream); - + if (skip <= 0) { /* don't skip */ vpts = img->vpts; /* copy so we can free img */ - + if (this->correct_durations) { /* calculate an average frame duration from metronom's vpts values */ this->avg_duration = this->avg_duration * 0.9 + (vpts - this->last_vpts) * 0.1; llprintf(LOG_PTS, "average frame duration %d\n", this->avg_duration); } - + if (this->skip_count) this->skip_count--; - + if (this->resync_window == 0 && this->scr && this->enhanced_mode && !this->scr->scanning) { /* we are in sync, so we can lock the stream now */ @@ -484,7 +488,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) llprintf(LOG_VID, "%d frames to skip\n", skip); vpts = 0; this->avg_duration = 0; - + /* handle frame skip conditions */ if (this->scr && !this->scr->scanning) this->skip_count += skip; if (this->skip_count > SKIP_TOLERANCE) { @@ -496,7 +500,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) this->skip_count = 0; this->resync_window = 0; } - + if (this->scr && this->scr->scanning) this->resync_window = 0; if (this->resync_window == 0 && this->scr && this->enhanced_mode && !this->scr->scanning) { @@ -515,7 +519,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) img->free(img); /* if sync_every_frame was disabled, decrease the counter - * for a retry + * for a retry * (it might be due to crappy studio logos and stuff * so we should give the main movie a chance) */ @@ -527,7 +531,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) } } if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; - + /* ensure video device is open * (we open it late because on occasion the dxr3 video out driver * wants to open it) @@ -537,15 +541,15 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) metronom_clock_t *clock = this->class->clock; char tmpstr[128]; int64_t time; - + /* open the device for the decoder */ snprintf (tmpstr, sizeof(tmpstr), "/dev/em8300_mv-%d", this->devnum); if ((this->fd_video = open(tmpstr, O_WRONLY)) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("dxr3_decode_video: Failed to open video device %s (%s)\n"), tmpstr, strerror(errno)); + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("dxr3_decode_video: Failed to open video device %s (%s)\n"), tmpstr, strerror(errno)); return; } - + /* We may want to issue a SETPTS, so make sure the scr plugin * is running and registered. Unfortuantely wa cannot do this * earlier, because the dxr3's internal scr gets confused @@ -558,11 +562,11 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) this->scr->scr_plugin.start(&this->scr->scr_plugin, time); clock->register_scr(clock, &this->scr->scr_plugin); } - + /* update the pts timestamp in the card, which tags the data we write to it */ if (vpts) { int64_t delay; - + /* The PTS values written to the DXR3 must be modified based on the difference * between stream's PTS and DTS (decoder timestamp). We receive this * difference via decoder_info */ @@ -578,7 +582,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) llprintf(LOG_PTS, "PTS to DTS correction: %d\n", this->dts_offset[1]); } vpts -= this->dts_offset[2]; - + delay = vpts - this->class->clock->get_current_time( this->class->clock); llprintf(LOG_PTS, "SETPTS got %" PRId64 "\n", vpts); @@ -592,7 +596,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_video: set video pts failed (%s)\n", strerror(errno)); } - + if (delay >= 90000) /* frame more than 1 sec ahead */ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_video: WARNING: vpts %" PRId64 " is %.02f seconds ahead of time!\n", @@ -602,7 +606,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) } else if (buf->pts) llprintf(LOG_PTS, "skip buf->pts = %" PRId64 " (no vpts)\n", buf->pts); - + /* now write the content to the dxr3 mpeg device and, in a dramatic * break with open source tradition, check the return value */ @@ -613,7 +617,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) _("dxr3_decode_video: write to device would block. flushing\n")); dxr3_flush(this_gen); } else { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("dxr3_decode_video: video device write failed (%s)\n"), strerror(errno)); } return; @@ -626,7 +630,7 @@ static void dxr3_decode_data(video_decoder_t *this_gen, buf_element_t *buf) static void dxr3_reset(video_decoder_t *this_gen) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; - + this->sequence_open = 0; } @@ -634,10 +638,10 @@ static void dxr3_discontinuity(video_decoder_t *this_gen) { } -static void dxr3_flush(video_decoder_t *this_gen) +static void dxr3_flush(video_decoder_t *this_gen) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; - + if (this->sequence_open && ++this->sequence_open > 5 && _x_stream_info_get(this->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL)) { /* The dxr3 needs a sequence end code for still menus to work correctly @@ -655,18 +659,18 @@ static void dxr3_dispose(video_decoder_t *this_gen) { dxr3_decoder_t *this = (dxr3_decoder_t *)this_gen; metronom_clock_t *clock = this->class->clock; - + if (this->scr) clock->unregister_scr(clock, &this->scr->scr_plugin); - + dxr3_mvcommand(this->fd_control, MVCOMMAND_FLUSHBUF); - + if (this->fd_video >= 0) close(this->fd_video); close(this->fd_control); - + this->stream->video_out->close(this->stream->video_out, this->stream); this->class->instance = 0; - + free(this); } @@ -680,11 +684,11 @@ static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t * buffer) this->width = ((this->height >> 12) + 15) & ~15; this->height = ((this->height & 0xfff) + 15) & ~15; this->aspect_code = buffer[3] >> 4; - + this->have_header_info = 1; - + if (this->force_aspect) this->aspect_code = this->force_aspect; - + /* when width, height or aspect changes, * we have to send an event for dxr3 spu decoder */ if (!this->last_width || !this->last_height || !this->last_aspect_code || @@ -701,7 +705,7 @@ static void parse_mpeg_header(dxr3_decoder_t *this, uint8_t * buffer) static int get_duration(dxr3_decoder_t *this) { int duration; - + switch (this->frame_rate_code) { case 1: /* 23.976 */ duration = 3754; /* actually it's 3753.75 */ @@ -728,19 +732,19 @@ static int get_duration(dxr3_decoder_t *this) duration = 1500; break; default: - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("dxr3_decode_video: WARNING: unknown frame rate code %d\n"), this->frame_rate_code); duration = 0; break; } - + /* update stream metadata */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, duration); - + if (this->correct_durations && duration) { /* we set an initial average frame duration here */ if (!this->avg_duration) this->avg_duration = duration; - + /* Apply a correction to the framerate-code if metronom * insists on a different frame duration. * The code below is for NTCS streams labeled as PAL streams. @@ -765,7 +769,7 @@ static int get_duration(dxr3_decoder_t *this) return 3000; } } - + if (this->force_duration_window == -FORCE_DURATION_WINDOW_SIZE) /* we are far from a force_duration window */ return duration; @@ -778,7 +782,7 @@ static int get_duration(dxr3_decoder_t *this) this->force_duration_window = -FORCE_DURATION_WINDOW_SIZE; } } - + return duration; } @@ -797,7 +801,7 @@ static void frame_format_change(dxr3_decoder_t *this) data.aspect = this->aspect_code; data.pan_scan = this->force_pan_scan; xine_event_send(this->stream, &event); - + /* update ratio */ switch (this->aspect_code) { case 2: @@ -813,12 +817,12 @@ static void frame_format_change(dxr3_decoder_t *this) if (this->have_header_info) this->ratio = (double)this->width / (double)this->height; } - + /* update stream metadata */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_RATIO, 10000 * this->ratio); - + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "MPEG (DXR3)"); } diff --git a/src/dxr3/dxr3_mpeg_encoders.c b/src/dxr3/dxr3_mpeg_encoders.c index 0c59b0b93..8ca48c6ae 100644 --- a/src/dxr3/dxr3_mpeg_encoders.c +++ b/src/dxr3/dxr3_mpeg_encoders.c @@ -1,26 +1,26 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + /* mpeg encoders for the dxr3 video out plugin. * supports the libfame and librte mpeg encoder libraries. - */ + */ #ifdef HAVE_CONFIG_H # include "config.h" @@ -51,7 +51,7 @@ #include "xineutils.h" #include "video_out_dxr3.h" -/* buffer size for encoded mpeg1 stream; will hold one intra frame +/* buffer size for encoded mpeg1 stream; will hold one intra frame * at 640x480 typical sizes are <50 kB. 512 kB should be plenty */ #define DEFAULT_BUFFER_SIZE 512*1024 @@ -67,7 +67,7 @@ static int rte_on_unneeded(dxr3_driver_t *drv); static int rte_on_close(dxr3_driver_t *drv); /* helper function */ -static void mp1e_callback(rte_context *context, void *data, ssize_t size, +static void mp1e_callback(rte_context *context, void *data, ssize_t size, void *user_data); /* encoder structure */ @@ -103,7 +103,7 @@ typedef struct { } fame_data_t; /* helper function */ -static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, +static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, dxr3_frame_t *frame); #endif @@ -118,15 +118,15 @@ static int lavc_on_close(dxr3_driver_t *drv); int dxr3_rte_init(dxr3_driver_t *drv) { rte_data_t* this; - + if (!rte_init()) { xprintf(drv->class->xine, XINE_VERBOSITY_LOG, _("dxr3_mpeg_encoder: failed to init librte\n")); return 0; } - - this = xine_xmalloc(sizeof(rte_data_t)); + + this = calloc(1, sizeof(rte_data_t)); if (!this) return 0; - + this->encoder_data.type = ENC_RTE; this->encoder_data.on_update_format = rte_on_update_format; this->encoder_data.on_frame_copy = NULL; @@ -134,7 +134,7 @@ int dxr3_rte_init(dxr3_driver_t *drv) this->encoder_data.on_unneeded = rte_on_unneeded; this->encoder_data.on_close = rte_on_close; this->context = 0; - + drv->enc = &this->encoder_data; return 1; } @@ -142,7 +142,7 @@ int dxr3_rte_init(dxr3_driver_t *drv) static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) { rte_data_t *this = (rte_data_t *)drv->enc; - rte_context *context; + rte_context *context; rte_codec *codec; double fps; @@ -152,13 +152,13 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) rte_context_destroy(this->context); this->context = 0; } - + if ((frame->vo_frame.pitches[0] % 16 != 0) || (frame->oheight % 16 != 0)) { - xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, _("dxr3_mpeg_encoder: rte only handles video dimensions which are multiples of 16\n")); return 0; } - + this->width = frame->vo_frame.pitches[0]; this->height = frame->oheight; @@ -172,7 +172,7 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) #if LOG_ENC rte_set_verbosity(context, 2); #endif - + /* get mpeg codec handle */ codec = rte_codec_set(context, RTE_STREAM_VIDEO, 0, "mpeg1_video"); if (!codec) { @@ -181,26 +181,26 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) this->context = 0; return 0; } - + this->rte_bitrate = drv->class->xine->config->register_range(drv->class->xine->config, "dxr3.encoding.rte_bitrate", 10000, 1000, 20000, - _("rte mpeg output bitrate (kbit/s)"), + _("rte mpeg output bitrate (kbit/s)"), _("The bitrate the mpeg encoder library librte should use for DXR3's encoding mode. " "Higher values will increase quality and CPU usage."), 10, NULL, NULL); this->rte_bitrate *= 1000; /* config in kbit/s, rte wants bit/s */ - - /* FIXME: this needs to be replaced with a codec option call. + + /* FIXME: this needs to be replaced with a codec option call. * However, there seems to be none for the colour format! - * So we'll use the deprecated set_video_parameters instead. + * So we'll use the deprecated set_video_parameters instead. * Alternative is to manually set context->video_format (RTE_YU... ) * and context->video_bytes (= width * height * bytes/pixel) */ - rte_set_video_parameters(context, + rte_set_video_parameters(context, (frame->vo_frame.format == XINE_IMGFMT_YV12 ? RTE_YUV420 : RTE_YUYV), - context->width, context->height, + context->width, context->height, context->video_rate, context->output_video_bits, context->gop_sequence); - + /* Now set a whole bunch of codec options * If I understand correctly, virtual_frame_rate is the frame rate * of the source (can be anything), while coded_frame_rate must be @@ -208,27 +208,27 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) */ fps = 90000.0 / frame->vo_frame.duration; if (!rte_option_set(codec, "virtual_frame_rate", fps)) - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: WARNING: rte_option_set failed; virtual_frame_rate = %g.\n", fps); if (!rte_option_set(codec, "coded_frame_rate", fps)) - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: WARNING: rte_option_set failed; coded_frame_rate = %g.\n", fps); if (!rte_option_set(codec, "bit_rate", (int)this->rte_bitrate)) xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: WARNING: rte_option_set failed; bit_rate = %d.\n", (int)this->rte_bitrate); if (!rte_option_set(codec, "gop_sequence", "I")) - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: WARNING: rte_option_set failed; gop_sequence = \"I\".\n"); /* just to be sure, disable motion comp (not needed in I frames) */ if (!rte_option_set(codec, "motion_compensation", 0)) xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: WARNING: rte_option_set failed; motion_compensation = 0.\n"); - + rte_set_input(context, RTE_VIDEO, RTE_PUSH, FALSE, NULL, NULL, NULL); rte_set_output(context, mp1e_callback, NULL, NULL); - + if (!rte_init_context(context)) { - xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, _("dxr3_mpeg_encoder: cannot init the context: %s\n"), context->error); rte_context_destroy(context); this->context = 0; @@ -236,7 +236,7 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) } /* do the sync'ing and start encoding */ if (!rte_start_encoding(context)) { - xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, _("dxr3_mpeg_encoder: cannot start encoding: %s\n"), context->error); rte_context_destroy(context); this->context = 0; @@ -244,11 +244,11 @@ static int rte_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) } this->rte_ptr = rte_push_video_data(context, NULL, 0); if (!this->rte_ptr) { - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: failed to get encoder buffer pointer.\n"); return 0; } - + return 1; } @@ -274,7 +274,7 @@ static int rte_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) static int rte_on_unneeded(dxr3_driver_t *drv) { rte_data_t *this = (rte_data_t *)drv->enc; - + if (this->context) { rte_stop(this->context); rte_context_destroy(this->context); @@ -297,15 +297,15 @@ static void mp1e_callback(rte_context *context, void *data, ssize_t size, void * dxr3_driver_t *drv = (dxr3_driver_t *)user_data; char tmpstr[128]; ssize_t written; - + written = write(drv->fd_video, data, size); if (written < 0) { - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: video device write failed (%s)\n", strerror(errno)); return; } if (written != size) - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: Could only write %d of %d mpeg bytes.\n", written, size); } #endif @@ -315,10 +315,10 @@ static void mp1e_callback(rte_context *context, void *data, ssize_t size, void * int dxr3_fame_init(dxr3_driver_t *drv) { fame_data_t *this; - - this = xine_xmalloc(sizeof(fame_data_t)); + + this = calloc(1, sizeof(fame_data_t)); if (!this) return 0; - + this->encoder_data.type = ENC_FAME; this->encoder_data.on_update_format = fame_on_update_format; this->encoder_data.on_frame_copy = NULL; @@ -326,36 +326,36 @@ int dxr3_fame_init(dxr3_driver_t *drv) this->encoder_data.on_unneeded = fame_on_unneeded; this->encoder_data.on_close = fame_on_close; this->context = 0; - + drv->enc = &this->encoder_data; return 1; } -static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) +static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) { fame_data_t *this = (fame_data_t *)drv->enc; fame_parameters_t init_fp = FAME_PARAMETERS_INITIALIZER; double fps; - if (this->buf) free(this->buf); + if (this->buf) free(this->buf); this->buf = 0; this->out[0] = this->out[1] = this->out[2] = 0; - + /* if YUY2 and dimensions changed, we need to re-allocate the * internal YV12 buffer */ if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { int image_size = frame->vo_frame.width * frame->oheight; - this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, + this->out[0] = xine_xmalloc_aligned(16, image_size * 3/2, (void *)&this->buf); - this->out[1] = this->out[0] + image_size; - this->out[2] = this->out[1] + image_size/4; + this->out[1] = this->out[0] + image_size; + this->out[2] = this->out[1] + image_size/4; /* fill with black (yuv 16,128,128) */ memset(this->out[0], 16, image_size); memset(this->out[1], 128, image_size/4); memset(this->out[2], 128, image_size/4); - lprintf("Using YUY2->YV12 conversion\n"); + lprintf("Using YUY2->YV12 conversion\n"); } if (this->context) { @@ -363,18 +363,18 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) fame_close(this->context); this->context = 0; } - + this->context = fame_open(); if (!this->context) { - xprintf(drv->class->xine, XINE_VERBOSITY_LOG, + xprintf(drv->class->xine, XINE_VERBOSITY_LOG, _("dxr3_mpeg_encoder: Couldn't start the FAME library\n")); return 0; } - + if (!this->buffer) this->buffer = (unsigned char *)malloc(DEFAULT_BUFFER_SIZE); if (!this->buffer) { - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: Couldn't allocate temp buffer for mpeg data\n"); return 0; } @@ -406,23 +406,23 @@ static int fame_on_update_format(dxr3_driver_t *drv, dxr3_frame_t *frame) if (fps < 23.988) { /* NTSC-FILM */ lprintf("setting mpeg output framerate to NTSC-FILM (23.976 Hz)\n"); this->fp.frame_rate_num = 24000; - this->fp.frame_rate_den = 1001; + this->fp.frame_rate_den = 1001; } else if (fps < 24.5) { /* FILM */ lprintf("setting mpeg output framerate to FILM (24 Hz)\n"); this->fp.frame_rate_num = 24; - this->fp.frame_rate_den = 1; + this->fp.frame_rate_den = 1; } else if (fps < 27.485) { /* PAL */ lprintf("setting mpeg output framerate to PAL (25 Hz)\n"); this->fp.frame_rate_num = 25; - this->fp.frame_rate_den = 1; + this->fp.frame_rate_den = 1; } else { /* NTSC */ lprintf("setting mpeg output framerate to NTSC (29.97 Hz)\n"); this->fp.frame_rate_num = 30000; this->fp.frame_rate_den = 1001; } - + fame_init (this->context, &this->fp, this->buffer, DEFAULT_BUFFER_SIZE); - + return 1; } @@ -448,17 +448,17 @@ static int fame_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) size = fame_encode_frame(this->context, &this->yuv, NULL); #endif - frame->vo_frame.free(&frame->vo_frame); - + frame->vo_frame.free(&frame->vo_frame); + written = write(drv->fd_video, this->buffer, size); if (written < 0) { - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: video device write failed (%s)\n", strerror(errno)); return 0; } if (written != size) - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: Could only write %d of %d mpeg bytes.\n", written, size); return 1; @@ -467,7 +467,7 @@ static int fame_on_display_frame(dxr3_driver_t *drv, dxr3_frame_t *frame) static int fame_on_unneeded(dxr3_driver_t *drv) { fame_data_t *this = (fame_data_t *)drv->enc; - + if (this->context) { fame_close(this->context); this->context = 0; @@ -494,7 +494,7 @@ static int fame_prepare_frame(fame_data_t *this, dxr3_driver_t *drv, dxr3_frame_ if (frame->vo_frame.format == XINE_IMGFMT_YUY2) { /* need YUY2->YV12 conversion */ if (!(this->out[0] && this->out[1] && this->out[2]) ) { - xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(drv->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_mpeg_encoder: Internal YV12 buffer not created.\n"); return 0; } @@ -544,13 +544,13 @@ int dxr3_lavc_init(dxr3_driver_t *drv, plugin_node_t *node) void *ffmpeg; int (*init)(dxr3_driver_t *); int result; - + ffmpeg = dlopen(node->file->filename, RTLD_LAZY); if (!ffmpeg) return 0; - + init = dlsym(ffmpeg, "dxr3_encoder_init"); if (!init) return 0; - + result = init(drv); /* the close function is implemented here, because it will call dlclose() * and that should not be done be the library we are closing... */ diff --git a/src/dxr3/dxr3_scr.c b/src/dxr3/dxr3_scr.c index 8fb049656..dd0ea5840 100644 --- a/src/dxr3/dxr3_scr.c +++ b/src/dxr3/dxr3_scr.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -55,11 +55,11 @@ static void dxr3_scr_update_priority(void *this_gen, xine_cfg_entry_t *entry) static inline int dxr3_mvcommand(int fd_control, int command) { em8300_register_t reg; - + reg.microcode_register = 1; reg.reg = 0; reg.val = command; - + return ioctl(fd_control, EM8300_IOCTL_WRITEREG, ®); } @@ -69,21 +69,21 @@ dxr3_scr_t *dxr3_scr_init(xine_t *xine) dxr3_scr_t *this; int devnum; char tmpstr[128]; - - this = (dxr3_scr_t *)xine_xmalloc(sizeof(dxr3_scr_t)); - + + this = calloc(1, sizeof(dxr3_scr_t)); + devnum = xine->config->register_num(xine->config, CONF_KEY, 0, CONF_NAME, CONF_HELP, 10, NULL, NULL); snprintf(tmpstr, sizeof(tmpstr), "/dev/em8300-%d", devnum); if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "dxr3_scr: Failed to open control device %s (%s)\n", tmpstr, strerror(errno)); free(this); return NULL; } - + this->xine = xine; - + this->scr_plugin.interface_version = 3; this->scr_plugin.get_priority = dxr3_scr_get_priority; this->scr_plugin.start = dxr3_scr_start; @@ -91,7 +91,7 @@ dxr3_scr_t *dxr3_scr_init(xine_t *xine) this->scr_plugin.adjust = dxr3_scr_adjust; this->scr_plugin.set_fine_speed = dxr3_scr_set_speed; this->scr_plugin.exit = dxr3_scr_exit; - + this->priority = xine->config->register_num( xine->config, "dxr3.scr_priority", 10, _("SCR plugin priority"), _("Priority of the DXR3 SCR plugin. Values less than 5 mean that the " @@ -102,9 +102,9 @@ dxr3_scr_t *dxr3_scr_init(xine_t *xine) this->last_pts = 0; this->scanning = 0; this->sync = 0; - + pthread_mutex_init(&this->mutex, NULL); - + lprintf("init complete\n"); return this; } @@ -120,7 +120,7 @@ static void dxr3_scr_start(scr_plugin_t *scr, int64_t vpts) { dxr3_scr_t *this = (dxr3_scr_t *)scr; uint32_t vpts32 = vpts >> 1; - + pthread_mutex_lock(&this->mutex); this->last_pts = vpts32; this->offset = vpts - ((int64_t)vpts32 << 1); @@ -140,7 +140,7 @@ static int64_t dxr3_scr_get_current(scr_plugin_t *scr) dxr3_scr_t *this = (dxr3_scr_t *)scr; uint32_t pts; int64_t current; - + pthread_mutex_lock(&this->mutex); if (ioctl(this->fd_control, EM8300_IOCTL_SCR_GET, &pts)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "dxr3_scr: get current failed (%s)\n", strerror(errno)); @@ -152,7 +152,7 @@ static int64_t dxr3_scr_get_current(scr_plugin_t *scr) this->last_pts = pts; current = ((int64_t)pts << 1) + this->offset; pthread_mutex_unlock(&this->mutex); - + return current; } @@ -161,7 +161,7 @@ static void dxr3_scr_adjust(scr_plugin_t *scr, int64_t vpts) dxr3_scr_t *this = (dxr3_scr_t *)scr; uint32_t current_pts32; int32_t offset32; - + pthread_mutex_lock(&this->mutex); if (ioctl(this->fd_control, EM8300_IOCTL_SCR_GET, ¤t_pts32)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "dxr3_scr: adjust get failed (%s)\n", strerror(errno)); @@ -187,7 +187,7 @@ static int dxr3_scr_set_speed(scr_plugin_t *scr, int speed) int playmode; pthread_mutex_lock(&this->mutex); - + em_speed = 0x900LL * (int64_t)speed / XINE_FINE_SPEED_NORMAL; switch (em_speed) { case 0: @@ -200,24 +200,24 @@ static int dxr3_scr_set_speed(scr_plugin_t *scr, int speed) playmode = MVCOMMAND_SYNC; else playmode = MVCOMMAND_START; - break; + break; default: playmode = MVCOMMAND_START; } - + if (dxr3_mvcommand(this->fd_control, playmode)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "dxr3_scr: failed to playmode (%s)\n", strerror(errno)); - + if(em_speed > 0x900) this->scanning = 1; else this->scanning = 0; - + if (ioctl(this->fd_control, EM8300_IOCTL_SCR_SETSPEED, &em_speed)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "dxr3_scr: failed to set speed (%s)\n", strerror(errno)); - + pthread_mutex_unlock(&this->mutex); - + lprintf("speed set to mode %d\n", speed); return speed; } @@ -225,7 +225,7 @@ static int dxr3_scr_set_speed(scr_plugin_t *scr, int speed) static void dxr3_scr_exit(scr_plugin_t *scr) { dxr3_scr_t *this = (dxr3_scr_t *)scr; - + close(this->fd_control); pthread_mutex_destroy(&this->mutex); free(this); @@ -237,8 +237,8 @@ static void dxr3_scr_exit(scr_plugin_t *scr) static void dxr3_scr_update_priority(void *this_gen, xine_cfg_entry_t *entry) { dxr3_scr_t *this = (dxr3_scr_t *)this_gen; - + this->priority = entry->num_value; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "dxr3_scr: setting scr priority to %d\n", entry->num_value); } diff --git a/src/dxr3/dxr3_scr.h b/src/dxr3/dxr3_scr.h index d0e155c27..612f16ccb 100644 --- a/src/dxr3/dxr3_scr.h +++ b/src/dxr3/dxr3_scr.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -25,11 +25,11 @@ typedef struct dxr3_scr_s { scr_plugin_t scr_plugin; pthread_mutex_t mutex; - + xine_t *xine; - + int fd_control; /* to access the dxr3 control device */ - + int priority; int64_t offset; /* difference between real scr and internal dxr3 clock */ uint32_t last_pts; /* last known value of internal dxr3 clock to detect wrap around */ diff --git a/src/dxr3/dxr3_spu_encoder.c b/src/dxr3/dxr3_spu_encoder.c index 2517063ac..4eb506e8c 100644 --- a/src/dxr3/dxr3_spu_encoder.c +++ b/src/dxr3/dxr3_spu_encoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -68,7 +68,7 @@ static void write_nibble(spu_encoder_t *this, int *offset, int *higher_nibble spu_encoder_t *dxr3_spu_encoder_init(void) { spu_encoder_t *this; - + this = (spu_encoder_t *)malloc(sizeof(spu_encoder_t)); this->target = NULL; this->need_reencode = 0; @@ -94,7 +94,7 @@ void dxr3_spu_encode(spu_encoder_t *this) static void convert_palette(spu_encoder_t *this) { int i, y, cb, cr, r, g, b; - + if (!this->overlay->rgb_clut) { for (i = 0; i < OVL_PALETTE_SIZE; i++) { y = (this->overlay->color[i] >> 16) & 0xff; @@ -137,7 +137,7 @@ static void create_histogram(spu_encoder_t *this) { rle_elem_t *rle; int i, x, y, len, part; - + for (i = 0; i < OVL_PALETTE_SIZE; i++) this->map[i] = this->clip_map[i] = 0; x = y = 0; @@ -180,14 +180,14 @@ static void generate_clut(spu_encoder_t *this) { int i, max, spu_color; double dist, diff; - + /* find first maximum -> first spu color */ max = 0; for (i = 1; i < OVL_PALETTE_SIZE; i++) if (this->map[i] > this->map[max]) max = i; this->color[0] = this->overlay->color[max]; this->trans[0] = this->overlay->trans[max]; - + for (spu_color = 1; spu_color < 4; spu_color++) { /* modify histogram and find next maximum -> next spu color */ max = 0; @@ -221,7 +221,7 @@ static void generate_clut(spu_encoder_t *this) if (this->clip_map[i] > this->clip_map[max]) max = i; this->hili_color[0] = this->overlay->hili_color[max]; this->hili_trans[0] = this->overlay->hili_trans[max]; - + for (spu_color = 1; spu_color < 4; spu_color++) { /* modify histogram and find next maximum -> next spu color */ max = 0; @@ -252,7 +252,7 @@ static void map_colors(spu_encoder_t *this) { int i, min, spu_color; double dist, diff, min_dist; - + /* for all colors in overlay palette find closest spu color */ for (i = 0; i < OVL_PALETTE_SIZE; i++) { min = 0; @@ -299,7 +299,7 @@ static void map_colors(spu_encoder_t *this) static void convert_clut(spu_encoder_t *this) { int i, r, g, b, y, cb, cr; - + for (i = 0; i < 4; i++) { r = (this->color[i] >> 16) & 0xff; g = (this->color[i] >> 8) & 0xff; @@ -311,7 +311,7 @@ static void convert_clut(spu_encoder_t *this) } for (i = 4; i < 16; i++) this->color[i] = 0x00008080; - + for (i = 0; i < 4; i++) { r = (this->hili_color[i] >> 16) & 0xff; g = (this->hili_color[i] >> 8) & 0xff; @@ -330,15 +330,15 @@ static void convert_overlay(spu_encoder_t *this) int offset = 0, field_start[2]; rle_elem_t *rle; int field, i, len, part, x, y, higher_nibble = 1; - + /* size will be determined later */ write_byte(this, &offset, 0x00); write_byte(this, &offset, 0x00); - + /* control sequence pointer will be determined later */ write_byte(this, &offset, 0x00); write_byte(this, &offset, 0x00); - + for (field = 0; field < 2; field++) { write_byte(this, &offset, 0x00); write_byte(this, &offset, 0x00); @@ -373,10 +373,10 @@ static void convert_overlay(spu_encoder_t *this) } } } - + /* we should be byte aligned here */ _x_assert(higher_nibble); - + /* control sequence starts here */ this->target[2] = offset >> 8; this->target[3] = offset & 0xff; diff --git a/src/dxr3/em8300.h b/src/dxr3/em8300.h index 44fd8cac3..b862f1d49 100644 --- a/src/dxr3/em8300.h +++ b/src/dxr3/em8300.h @@ -186,7 +186,7 @@ typedef struct { #define IRQSTATUS_AUDIO_FIFO 0x8 #define ENCODER_UNKNOWN 0 -#define ENCODER_ADV7175 1 +#define ENCODER_ADV7175 1 #define ENCODER_ADV7170 2 #define ENCODER_BT865 3 @@ -235,21 +235,21 @@ struct em8300_audio_s { struct em8300_s { char name[40]; - + int chip_revision; int pci_revision; - + int inuse[4]; int nonblock[4]; int ucodeloaded; - + struct pci_dev *dev; ulong adr; volatile unsigned *mem; ulong memsize; - + int playmode; - + /* Sysfs */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,46) struct class_device classdev; @@ -263,7 +263,7 @@ struct em8300_s struct fifo_s *mafifo; struct fifo_s *spfifo; int mtrr_reg; - + /* DICOM */ int dicom_vertoffset; int dicom_horizoffset; @@ -272,47 +272,47 @@ struct em8300_s int dicom_saturation; int dicom_tvout; struct displaybuffer_info_s dbuf_info; - + /* I2C */ int i2c_pin_reg; int i2c_oe_reg; - + /* different between revision 1 and revision 2 boards */ int mystery_divisor; - + /* I2C bus 1*/ struct i2c_algo_bit_data i2c_data_1; struct i2c_adapter i2c_ops_1; - + /* I2C bus 2*/ struct i2c_algo_bit_data i2c_data_2; struct i2c_adapter i2c_ops_2; - + /* I2C clients */ int encoder_type; struct i2c_client *encoder; - + /* Microcode registers */ unsigned ucode_regs[MAX_UCODE_REGISTER]; int var_ucode_reg1; /* These are registers that differ */ int var_ucode_reg2; /* between versions 1 and 2 of the board */ int var_ucode_reg3; /* " */ - + /* Interrupt */ unsigned irqmask; - + /* Clockgenerator */ int clockgen; int clockgen_overlaymode; int clockgen_tvmode; - + /* Timing measurement */ struct timeval tv, last_status_time; long irqtimediff; int irqcount; int frames; int scr; - + /* Audio */ struct em8300_audio_s audio; int audio_mode; @@ -321,7 +321,7 @@ struct em8300_s /* */ int dword_DB4; unsigned char byte_D90[24]; - + /* Video */ int video_mode; int video_playmode; @@ -330,7 +330,7 @@ struct em8300_s uint32_t video_lastpts; int video_ptsvalid,video_offset,video_count; int video_ptsfifo_ptr; -#if LINUX_VERSION_CODE < 0x020314 +#if LINUX_VERSION_CODE < 0x020314 struct wait_queue *video_ptsfifo_wait; struct wait_queue *vbi_wait; #else @@ -340,20 +340,20 @@ struct em8300_s int video_ptsfifo_waiting; int video_first; int var_video_value; - + /* Sub Picture */ int sp_pts, sp_ptsvalid, sp_count; int sp_ptsfifo_ptr; -#if LINUX_VERSION_CODE < 0x020314 +#if LINUX_VERSION_CODE < 0x020314 struct wait_queue *sp_ptsfifo_wait; #else wait_queue_head_t sp_ptsfifo_wait; #endif int sp_ptsfifo_waiting; int sp_mode; - + int linecounter; - + /* EM9010 overlay processor */ int overlay_enabled; int overlay_mode; @@ -373,7 +373,7 @@ struct em8300_s #if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) /* Memory exported via mmap() */ struct list_head memory; -#endif +#endif /* To support different options for different cards */ unsigned int card_nr; diff --git a/src/dxr3/video_out_dxr3.c b/src/dxr3/video_out_dxr3.c index c51354157..3d38e6640 100644 --- a/src/dxr3/video_out_dxr3.c +++ b/src/dxr3/video_out_dxr3.c @@ -1,28 +1,28 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - -/* mpeg1 encoding video out plugin for the dxr3. + +/* mpeg1 encoding video out plugin for the dxr3. * - * modifications to the original dxr3 video out plugin by - * Mike Lampard <mike at web2u.com.au> - * this first standalone version by + * modifications to the original dxr3 video out plugin by + * Mike Lampard <mlampard at users.sourceforge.net> + * this first standalone version by * Harm van der Heijden <hrm at users.sourceforge.net> */ @@ -90,7 +90,7 @@ static const vo_info_t vo_info_dxr3_aa = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ #ifdef HAVE_X11 { PLUGIN_VIDEO_OUT, 21, "dxr3", XINE_VERSION_CODE, &vo_info_dxr3_x11, &dxr3_x11_init_plugin }, #endif @@ -149,7 +149,7 @@ static void dxr3_update_enhanced_mode(void *this_gen, xine_cfg_entry_t *e static void *dxr3_x11_init_plugin(xine_t *xine, void *visual_gen) { dxr3_driver_class_t *this = dxr3_vo_init_plugin(xine, visual_gen); - + if (!this) return NULL; this->visual_type = XINE_VISUAL_TYPE_X11; return &this->video_driver_class; @@ -159,7 +159,7 @@ static void *dxr3_x11_init_plugin(xine_t *xine, void *visual_gen) static void *dxr3_aa_init_plugin(xine_t *xine, void *visual_gen) { dxr3_driver_class_t *this = dxr3_vo_init_plugin(xine, visual_gen); - + if (!this) return NULL; this->visual_type = XINE_VISUAL_TYPE_AA; return &this->video_driver_class; @@ -168,10 +168,10 @@ static void *dxr3_aa_init_plugin(xine_t *xine, void *visual_gen) static dxr3_driver_class_t *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) { dxr3_driver_class_t *this; - - this = (dxr3_driver_class_t *)xine_xmalloc(sizeof(dxr3_driver_class_t)); + + this = calloc(1, sizeof(dxr3_driver_class_t)); if (!this) return NULL; - + this->devnum = xine->config->register_num(xine->config, CONF_KEY, 0, CONF_NAME, CONF_HELP, 10, NULL, NULL); @@ -179,13 +179,13 @@ static dxr3_driver_class_t *dxr3_vo_init_plugin(xine_t *xine, void *visual_gen) this->video_driver_class.get_identifier = dxr3_vo_get_identifier; this->video_driver_class.get_description = dxr3_vo_get_description; this->video_driver_class.dispose = dxr3_vo_class_dispose; - + this->xine = xine; - + this->instance = 0; - + this->scr = dxr3_scr_init(xine); - + return this; } @@ -202,7 +202,7 @@ static char *dxr3_vo_get_description(video_driver_class_t *class_gen) static void dxr3_vo_class_dispose(video_driver_class_t *class_gen) { dxr3_driver_class_t *class = (dxr3_driver_class_t *)class_gen; - + if(class->scr) class->scr->scr_plugin.exit(&class->scr->scr_plugin); free(class_gen); @@ -229,12 +229,12 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v static const char const *tv_modes[] = { "ntsc", "pal", "pal60" , "default", NULL }; int list_id, list_size; xine_sarray_t *plugin_list; - + if (class->instance) return NULL; - - this = (dxr3_driver_t *)xine_xmalloc(sizeof(dxr3_driver_t)); + + this = calloc(1, sizeof(dxr3_driver_t)); if (!this) return NULL; - + this->vo_driver.get_capabilities = dxr3_get_capabilities; this->vo_driver.alloc_frame = dxr3_alloc_frame; this->vo_driver.update_frame_format = dxr3_update_frame_format; @@ -248,13 +248,13 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v this->vo_driver.get_property_min_max = dxr3_get_property_min_max; this->vo_driver.gui_data_exchange = dxr3_gui_data_exchange; this->vo_driver.dispose = dxr3_dispose; - + pthread_mutex_init(&this->video_device_lock, NULL); pthread_mutex_init(&this->spu_device_lock, NULL); - + _x_vo_scale_init(&this->scale, 0, 0, config); _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->class = class; this->swap_fields = config->register_bool(config, "dxr3.encoding.swap_fields", 0, _("swap odd and even lines"), @@ -271,7 +271,7 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v _("use smooth play mode for mpeg encoder playback"), _("Enabling this option will utilise a smoother play mode for non-MPEG content."), 20, dxr3_update_enhanced_mode, this); - + snprintf(tmpstr, sizeof(tmpstr), "/dev/em8300-%d", class->devnum); llprintf(LOG_VID, "Entering video init, devname = %s.\n", tmpstr); if ((this->fd_control = open(tmpstr, O_WRONLY)) < 0) { @@ -281,10 +281,10 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v return 0; } - + snprintf (tmpstr, sizeof(tmpstr), "/dev/em8300_mv-%d", class->devnum); if ((this->fd_video = open (tmpstr, O_WRONLY | O_SYNC )) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: Failed to open video device %s (%s)\n"), tmpstr, strerror(errno)); return 0; } @@ -342,45 +342,45 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v "but xine support for them is outdated, so these might fail to work."), 0, NULL, NULL); if ((strcmp(available_encoders[encoder], "libavcodec") == 0) && !dxr3_lavc_init(this, node)) { - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: Mpeg encoder libavcodec failed to init.\n")); return 0; } #ifdef HAVE_LIBRTE if ((strcmp(available_encoders[encoder], "rte") == 0) && !dxr3_rte_init(this)) { - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: Mpeg encoder rte failed to init.\n")); return 0; } #endif #ifdef HAVE_LIBFAME if ((strcmp(available_encoders[encoder], "fame") == 0) && !dxr3_fame_init(this)) { - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: Mpeg encoder fame failed to init.\n")); return 0; } #endif if (strcmp(available_encoders[encoder], "none") == 0) - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: Mpeg encoding disabled.\n" "video_out_dxr3: that's ok, you don't need it for mpeg video like DVDs, but\n" "video_out_dxr3: you will not be able to play non-mpeg content using this video out\n" "video_out_dxr3: driver. See the README.dxr3 for details on configuring an encoder.\n")); } else - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: No mpeg encoder compiled in.\n" "video_out_dxr3: that's ok, you don't need it for mpeg video like DVDs, but\n" "video_out_dxr3: you will not be able to play non-mpeg content using this video out\n" "video_out_dxr3: driver. See the README.dxr3 for details on configuring an encoder.\n")); - + /* init aspect */ this->aspect = dxr3_set_property(&this->vo_driver, VO_PROP_ASPECT_RATIO, XINE_VO_ASPECT_4_3); - + /* init brightness/contrast/saturation */ dxr3_set_property(&this->vo_driver, VO_PROP_BRIGHTNESS, 500); dxr3_set_property(&this->vo_driver, VO_PROP_CONTRAST , 500); dxr3_set_property(&this->vo_driver, VO_PROP_SATURATION, 500); - + /* overlay or tvout? */ confnum = config->register_enum(config, "dxr3.output.mode", 0, videoout_modes, _("video output mode (TV or overlay)"), @@ -446,7 +446,7 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v _("Removes one pixel line from the top and bottom of the overlay. Enable this, if " "you see green lines at the top or bottom of the overlay."), 10, NULL, NULL); } else { - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: please run autocal, overlay disabled\n")); this->overlay_enabled = 0; this->tv_switchable = 0; @@ -454,7 +454,7 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v } #endif } - + /* init tvmode */ confnum = config->register_enum(config, "dxr3.output.tvmode", 3, tv_modes, _("preferred tv mode"), _("Selects the TV mode to be used by the DXR3. The values mean:\n\n" @@ -478,50 +478,50 @@ static vo_driver_t *dxr3_vo_open_plugin(video_driver_class_t *class_gen, const v } if (this->tv_mode != EM8300_VIDEOMODE_DEFAULT) if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &this->tv_mode)) - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: setting video mode failed.\n")); - + #ifdef HAVE_X11 /* initialize overlay */ if (this->overlay_enabled) { em8300_overlay_screen_t scr; int value; XColor dummy; - + this->overlay.fd_control = this->fd_control; - + /* allocate keycolor */ this->key.red = ((this->overlay.colorkey >> 16) & 0xff) * 256; this->key.green = ((this->overlay.colorkey >> 8) & 0xff) * 256; this->key.blue = ((this->overlay.colorkey ) & 0xff) * 256; XAllocColor(this->display, DefaultColormap(this->display, 0), &this->key); - + /* allocate black for output area borders */ XAllocNamedColor(this->display, DefaultColormap(this->display, 0), "black", &this->black, &dummy); - + /* set the screen */ scr.xsize = this->overlay.screen_xres; scr.ysize = this->overlay.screen_yres; if (ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETSCREEN, &scr)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting the overlay screen failed.\n"); - + if (dxr3_overlay_set_keycolor(&this->overlay) != 0) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting the overlay key colour failed.\n"); if (dxr3_overlay_set_attributes(&this->overlay) != 0) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting an overlay attribute failed.\n"); - + /* finally switch to overlay mode */ value = EM8300_OVERLAY_MODE_OVERLAY; if (ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETMODE, &value) != 0) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: switching to overlay mode failed.\n"); } #endif - + return &this->vo_driver; } @@ -535,9 +535,9 @@ static vo_frame_t *dxr3_alloc_frame(vo_driver_t *this_gen) { dxr3_frame_t *frame; dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - - frame = (dxr3_frame_t *)xine_xmalloc(sizeof(dxr3_frame_t)); - + + frame = calloc(1, sizeof(dxr3_frame_t)); + pthread_mutex_init(&frame->vo_frame.mutex, NULL); if (this->enc && this->enc->on_frame_copy) { @@ -559,7 +559,7 @@ static void dxr3_frame_proc_frame(vo_frame_t *frame_gen) /* we reduce the vpts to give the card some extra decoding time */ if (frame_gen->format != XINE_IMGFMT_DXR3 && !frame_gen->proc_called) frame_gen->vpts -= DECODE_PIPE_PREBUFFER; - + frame_gen->proc_called = 1; } @@ -567,11 +567,11 @@ static void dxr3_frame_proc_slice(vo_frame_t *frame_gen, uint8_t **src) { dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; dxr3_driver_t *this = (dxr3_driver_t *)frame_gen->driver; - + /* we reduce the vpts to give the card some extra decoding time */ if (frame_gen->format != XINE_IMGFMT_DXR3 && !frame_gen->proc_called) frame_gen->vpts -= DECODE_PIPE_PREBUFFER; - + frame_gen->proc_called = 1; if (frame_gen->format != XINE_IMGFMT_DXR3 && this->enc && this->enc->on_frame_copy) @@ -586,7 +586,7 @@ static void dxr3_frame_field(vo_frame_t *vo_img, int which_field) static void dxr3_frame_dispose(vo_frame_t *frame_gen) { dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; - + if (frame->mem) free(frame->mem); pthread_mutex_destroy(&frame_gen->mutex); free(frame); @@ -595,8 +595,8 @@ static void dxr3_frame_dispose(vo_frame_t *frame_gen) static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, double ratio, int format, int flags) { - dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; + dxr3_driver_t *this = (dxr3_driver_t *)this_gen; + dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; uint32_t oheight; if (format == XINE_IMGFMT_DXR3) { /* talking to dxr3 decoder */ @@ -605,7 +605,7 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge pthread_mutex_lock(&this->video_device_lock); if (this->fd_video >= 0) { metronom_clock_t *clock = this->class->xine->clock; - + clock->unregister_scr(clock, &this->class->scr->scr_plugin); close(this->fd_video); this->fd_video = -1; @@ -613,10 +613,10 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge this->need_update = 1; } pthread_mutex_unlock(&this->video_device_lock); - + /* for mpeg source, we don't have to do much. */ this->video_width = 0; - + frame->vo_frame.width = width; frame->vo_frame.height = height; frame->vo_frame.ratio = ratio; @@ -626,23 +626,23 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge else frame->aspect = XINE_VO_ASPECT_ANAMORPHIC; frame->pan_scan = flags & VO_PAN_SCAN_FLAG; - + if (frame->mem) { free(frame->mem); frame->mem = NULL; frame->real_base[0] = frame->real_base[1] = frame->real_base[2] = NULL; frame_gen->base[0] = frame_gen->base[1] = frame_gen->base[2] = NULL; } - + return; } /* the following is for the mpeg encoding part only */ - + if (!this->add_bars) /* don't add black bars; assume source is in 4:3 */ ratio = 4.0/3.0; - + frame->vo_frame.ratio = ratio; frame->pan_scan = 0; frame->aspect = this->video_aspect; @@ -653,18 +653,18 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge metronom_clock_t *clock = this->class->xine->clock; char tmpstr[128]; int64_t time; - + /* open the device for the encoder */ snprintf(tmpstr, sizeof(tmpstr), "/dev/em8300_mv-%d", this->class->devnum); if ((this->fd_video = open(tmpstr, O_WRONLY)) < 0) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: Failed to open video device %s (%s)\n", tmpstr, strerror(errno)); - + /* start the scr plugin */ time = clock->get_current_time(clock); this->class->scr->scr_plugin.start(&this->class->scr->scr_plugin, time); clock->register_scr(clock, &this->class->scr->scr_plugin); - + this->scale.force_redraw = 1; } pthread_mutex_unlock(&this->video_device_lock); @@ -684,20 +684,20 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge /* still too high, use full height */ oheight = height; } - + /* use next multiple of 16 */ oheight = ((oheight - 1) | 15) + 1; /* Tell the viewers about the aspect ratio stuff. */ if (oheight - height > 0) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: adding %d black lines to get %s aspect ratio.\n", oheight - height, frame->aspect == XINE_VO_ASPECT_4_3 ? "4:3" : "16:9"); - /* make top black bar multiple of 16, - * so old and new macroblocks overlap */ + /* make top black bar multiple of 16, + * so old and new macroblocks overlap */ this->top_bar = ((oheight - height) / 32) * 16; - + this->video_width = width; this->video_iheight = height; this->video_oheight = oheight; @@ -708,27 +708,27 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge if (!this->enc) { /* no encoder plugin! Let's bug the user! */ - xprintf(this->class->xine, XINE_VERBOSITY_LOG, + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: Need an mpeg encoder to play non-mpeg videos on dxr3\n" "video_out_dxr3: Read the README.dxr3 for details.\n")); } } /* if dimensions changed, we need to re-allocate frame memory */ - if ((frame->vo_frame.width != width) || (frame->vo_frame.height != height) || + if ((frame->vo_frame.width != width) || (frame->vo_frame.height != height) || (frame->oheight != oheight) || (frame->vo_frame.format != format)) { if (frame->mem) { free (frame->mem); frame->mem = NULL; } - + if (format == XINE_IMGFMT_YUY2) { int i, image_size; - + /* calculate pitch and size including black bars */ frame->vo_frame.pitches[0] = 32 * ((width + 15) / 16); image_size = frame->vo_frame.pitches[0] * oheight; - + /* planar format, only base[0] */ /* add one extra line for field swap stuff */ frame->real_base[0] = xine_xmalloc_aligned(16, image_size + frame->vo_frame.pitches[0], @@ -749,7 +749,7 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge } else { /* XINE_IMGFMT_YV12 */ int image_size_y, image_size_u, image_size_v; - + /* calculate pitches and sizes including black bars */ frame->vo_frame.pitches[0] = 16*((width + 15) / 16); frame->vo_frame.pitches[1] = 8*((width + 15) / 16); @@ -771,7 +771,7 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge frame->vo_frame.base[0] = frame->real_base[0] + frame->vo_frame.pitches[0] * this->top_bar; frame->vo_frame.base[1] = frame->real_base[1] + frame->vo_frame.pitches[1] * this->top_bar / 2; frame->vo_frame.base[2] = frame->real_base[2] + frame->vo_frame.pitches[2] * this->top_bar / 2; - + /* fill with black (yuv 16,128,128) */ memset(frame->real_base[0], 16, image_size_y); memset(frame->real_base[1], 128, image_size_u); @@ -780,12 +780,12 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge } if (this->swap_fields != frame->swap_fields) { - if (this->swap_fields) + if (this->swap_fields) frame->vo_frame.base[0] -= frame->vo_frame.pitches[0]; - else + else frame->vo_frame.base[0] += frame->vo_frame.pitches[0]; } - + frame->vo_frame.width = width; frame->vo_frame.height = height; frame->oheight = oheight; @@ -795,20 +795,20 @@ static void dxr3_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_ge static void dxr3_overlay_begin(vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - + /* special treatment is only necessary for mpeg frames */ if (frame_gen->format != XINE_IMGFMT_DXR3) return; - + if (!this->spu_enc) this->spu_enc = dxr3_spu_encoder_init(); - + if (!changed) { this->spu_enc->need_reencode = 0; return; } - + this->spu_enc->need_reencode = 1; this->spu_enc->overlay = NULL; - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -817,10 +817,10 @@ static void dxr3_overlay_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { dxr3_driver_t *this = (dxr3_driver_t *)this_gen; - + if (frame_gen->format != XINE_IMGFMT_DXR3) { dxr3_frame_t *frame = (dxr3_frame_t *)frame_gen; - + if (overlay->rle) { if (frame_gen->format == XINE_IMGFMT_YV12) _x_blend_yuv(frame->vo_frame.base, overlay, @@ -844,26 +844,26 @@ static void dxr3_overlay_end(vo_driver_t *this_gen, vo_frame_t *frame_gen) em8300_button_t btn; char tmpstr[128]; ssize_t written; - + if (frame_gen->format != XINE_IMGFMT_DXR3) return; if (!this->spu_enc->need_reencode) return; - + dxr3_spu_encode(this->spu_enc); pthread_mutex_lock(&this->spu_device_lock); - + /* try to open the dxr3 spu device */ if (!this->fd_spu) { snprintf (tmpstr, sizeof(tmpstr), "/dev/em8300_sp-%d", this->class->devnum); if ((this->fd_spu = open (tmpstr, O_WRONLY)) < 0) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: Failed to open spu device %s (%s)\n" "video_out_dxr3: Overlays are not available\n", tmpstr, strerror(errno)); pthread_mutex_unlock(&this->spu_device_lock); return; } } - + if (!this->spu_enc->overlay) { uint8_t empty_spu[] = { 0x00, 0x26, 0x00, 0x08, 0x80, 0x00, 0x00, 0x80, @@ -877,7 +877,7 @@ static void dxr3_overlay_end(vo_driver_t *this_gen, vo_frame_t *frame_gen) pthread_mutex_unlock(&this->spu_device_lock); return; } - + /* copy clip palette */ this->spu_enc->color[4] = this->spu_enc->hili_color[0]; this->spu_enc->color[5] = this->spu_enc->hili_color[1]; @@ -885,16 +885,16 @@ static void dxr3_overlay_end(vo_driver_t *this_gen, vo_frame_t *frame_gen) this->spu_enc->color[7] = this->spu_enc->hili_color[3]; /* set palette */ if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_SETPALETTE, this->spu_enc->color)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: failed to set CLUT (%s)\n", strerror(errno)); this->clut_cluttered = 1; /* write spu */ written = write(this->fd_spu, this->spu_enc->target, this->spu_enc->size); if (written < 0) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: spu device write failed (%s)\n", strerror(errno)); else if (written != this->spu_enc->size) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: Could only write %zd of %d spu bytes.\n", written, this->spu_enc->size); /* set clipping */ btn.color = 0x7654; @@ -908,9 +908,9 @@ static void dxr3_overlay_end(vo_driver_t *this_gen, vo_frame_t *frame_gen) btn.top = this->spu_enc->overlay->y + this->spu_enc->overlay->hili_top; btn.bottom = this->spu_enc->overlay->y + this->spu_enc->overlay->hili_bottom - 2; if (ioctl(this->fd_spu, EM8300_IOCTL_SPU_BUTTON, &btn)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "dxr3_decode_spu: failed to set spu button (%s)\n", strerror(errno)); - + pthread_mutex_unlock(&this->spu_device_lock); } @@ -968,22 +968,22 @@ static void dxr3_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) } } #endif - + if (frame_gen->format != XINE_IMGFMT_DXR3 && this->enc && this->enc->on_display_frame) { - + pthread_mutex_lock(&this->video_device_lock); if (this->fd_video < 0) { /* no need to encode, when the device is already reserved for the decoder */ frame_gen->free(frame_gen); } else { uint32_t vpts32 = (uint32_t)(frame_gen->vpts + DECODE_PIPE_PREBUFFER); - + if (this->need_update) { /* we cannot do this earlier, because vo_frame.duration is only valid here */ if (this->enc && this->enc->on_update_format) { /* set the dxr3 playmode */ if (this->enc->on_update_format(this, frame) && this->enhanced_mode) { - em8300_register_t reg; + em8300_register_t reg; reg.microcode_register = 1; reg.reg = 0; reg.val = MVCOMMAND_SYNC; @@ -995,19 +995,19 @@ static void dxr3_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) } this->need_update = 0; } - + /* inform the card on the timing */ if (ioctl(this->fd_video, EM8300_IOCTL_VIDEO_SETPTS, &vpts32)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: set video pts failed (%s)\n", strerror(errno)); - /* for non-mpeg, the encoder plugin is responsible for calling + /* for non-mpeg, the encoder plugin is responsible for calling * frame_gen->free(frame_gen) ! */ this->enc->on_display_frame(this, frame); } pthread_mutex_unlock(&this->video_device_lock); - + } else { - + if (this->need_update) { /* we do not need the mpeg encoders any more */ if (this->enc && this->enc->on_unneeded) @@ -1015,7 +1015,7 @@ static void dxr3_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) this->need_update = 0; } frame_gen->free(frame_gen); - + } } @@ -1023,11 +1023,11 @@ static int dxr3_redraw_needed(vo_driver_t *this_gen) { dxr3_driver_t *this = (dxr3_driver_t *)this_gen; -#ifdef HAVE_X11 +#ifdef HAVE_X11 if (this->overlay_enabled) dxr3_overlay_update(this); #endif - + return 0; } @@ -1055,7 +1055,7 @@ static int dxr3_get_property(vo_driver_t *this_gen, int property) case VO_PROP_WINDOW_HEIGHT: return this->scale.gui_height; } - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: property %d not implemented.\n", property); return 0; } @@ -1086,7 +1086,7 @@ static int dxr3_set_property(vo_driver_t *this_gen, int property, int value) /* We should send an anamorphic hint to widescreen tvs, so they * can switch to 16:9 mode. But the dxr3 cannot do this. */ break; - + switch(value) { case XINE_VO_ASPECT_SQUARE: case XINE_VO_ASPECT_4_3: @@ -1102,13 +1102,13 @@ static int dxr3_set_property(vo_driver_t *this_gen, int property, int value) } if (ioctl(this->fd_control, EM8300_IOCTL_SET_ASPECTRATIO, &val)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: failed to set aspect ratio (%s)\n", strerror(errno)); - + this->scale.force_redraw = 1; break; case VO_PROP_COLORKEY: - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: VO_PROP_COLORKEY not implemented!"); this->overlay.colorkey = value; break; @@ -1143,16 +1143,16 @@ static int dxr3_set_property(vo_driver_t *this_gen, int property, int value) } #endif if (ioctl(this->fd_control, EM8300_IOCTL_SET_VIDEOMODE, &this->tv_mode)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting video mode failed (%s)\n", strerror(errno)); break; } if (bcs_changed) if (ioctl(this->fd_control, EM8300_IOCTL_SETBCS, &this->bcs)) - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: bcs set failed (%s)\n", strerror(errno)); - + return value; } @@ -1261,7 +1261,7 @@ static void dxr3_dispose(vo_driver_t *this_gen) pthread_mutex_destroy(&this->spu_device_lock); _x_alphablend_free(&this->alphablend_extra_data); - + free(this); } @@ -1297,7 +1297,7 @@ static void gather_screen_vars(dxr3_driver_t *this, const x11_visual_t *vis) this->overlay.screen_depth = DisplayPlanes(this->display, scrn); this->scale.frame_output_cb = (void *)vis->frame_output_cb; - + llprintf(LOG_OVR, "xres: %d, yres: %d, depth: %d\n", this->overlay.screen_xres, this->overlay.screen_yres, this->overlay.screen_depth); } @@ -1309,9 +1309,9 @@ static void gather_screen_vars(dxr3_driver_t *this, const x11_visual_t *vis) #define TYPE_FLOAT 4 struct lut_entry { - char *name; - int type; - void *ptr; + char *name; + int type; + void *ptr; }; /* dxr3_overlay_read_state helper function */ @@ -1319,7 +1319,7 @@ static int lookup_parameter(struct lut_entry *lut, char *name, void **ptr, int *type) { int i; - + for (i = 0; lut[i].name; i++) if (strcmp(name, lut[i].name) == 0) { *ptr = lut[i].ptr; @@ -1334,7 +1334,7 @@ static int lookup_parameter(struct lut_entry *lut, char *name, static int dxr3_overlay_read_state(dxr3_overlay_t *this) { char *loc; - char fname[256], tmp[128], line[256]; + char *fname, line[256]; FILE *fp; struct lut_entry lut[] = { {"xoffset", TYPE_INT, &this->xoffset}, @@ -1359,18 +1359,16 @@ static int dxr3_overlay_read_state(dxr3_overlay_t *this) * (used by .overlay/res file) */ setlocale(LC_NUMERIC, "C"); - snprintf(tmp, sizeof(tmp), "/res_%dx%dx%d", + asprintf(&fname, "%s/.overlay/res_%dx%dx%d", getenv("HOME"), this->screen_xres, this->screen_yres, this->screen_depth); - strncpy(fname, getenv("HOME"), sizeof(fname) - strlen(tmp) - sizeof("/.overlay")); - fname[sizeof(fname) - strlen(tmp) - sizeof("/.overlay")] = '\0'; - strcat(fname, "/.overlay"); - strcat(fname, tmp); llprintf(LOG_OVR, "attempting to open %s\n", fname); if (!(fp = fopen(fname, "r"))) { - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_dxr3: ERROR Reading overlay init file. Run autocal!\n")); + free(fname); return -1; } + free(fname); while (!feof(fp)) { if (!fgets(line, 256, fp)) @@ -1404,11 +1402,11 @@ static int dxr3_overlay_read_state(dxr3_overlay_t *this) } } } - + fclose(fp); /* restore original locale */ setlocale(LC_NUMERIC, loc); - + return 0; } @@ -1443,7 +1441,7 @@ static int dxr3_overlay_set_keycolor(dxr3_overlay_t *this) attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_LOWER; attr.value = overlay_limit; if ((ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)) < 0) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: WARNING: error setting overlay lower limit attribute\n"); return ret; } @@ -1456,7 +1454,7 @@ static int dxr3_overlay_set_keycolor(dxr3_overlay_t *this) attr.attribute = EM9010_ATTRIBUTE_KEYCOLOR_UPPER; attr.value = overlay_limit; if ((ret = ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr)) < 0) - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: WARNING: error setting overlay upper limit attribute\n"); return ret; } @@ -1464,7 +1462,7 @@ static int dxr3_overlay_set_keycolor(dxr3_overlay_t *this) static int dxr3_overlay_set_attributes(dxr3_overlay_t *this) { em8300_attribute_t attr; - + attr.attribute = EM9010_ATTRIBUTE_XOFFSET; attr.value = this->xoffset; if(ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SET_ATTRIBUTE, &attr) == -1) @@ -1491,9 +1489,9 @@ static void dxr3_overlay_update(dxr3_driver_t *this) { if (_x_vo_scale_redraw_needed(&this->scale)) { em8300_overlay_window_t win; - + _x_vo_scale_compute_output_size(&this->scale); - + /* fill video window with keycolor */ XLockDisplay(this->display); XSetForeground(this->display, this->gc, this->black.pixel); @@ -1506,24 +1504,24 @@ static void dxr3_overlay_update(dxr3_driver_t *this) this->scale.output_width, this->scale.output_height - 2 * this->overlay.shrink); XFlush(this->display); XUnlockDisplay(this->display); - + win.xpos = this->scale.output_xoffset + this->scale.gui_win_x; win.ypos = this->scale.output_yoffset + this->scale.gui_win_y; win.width = this->scale.output_width; win.height = this->scale.output_height; - + if (this->pan_scan) { win.xpos -= win.width / 6; win.width *= 4; win.width /= 3; } - + /* is some part of the picture visible? */ if (win.xpos + win.width < 0) return; if (win.ypos + win.height < 0) return; if (win.xpos > this->overlay.screen_xres) return; if (win.ypos > this->overlay.screen_yres) return; - + ioctl(this->fd_control, EM8300_IOCTL_OVERLAY_SETWINDOW, &win); } } @@ -1532,20 +1530,20 @@ static void dxr3_overlay_update(dxr3_driver_t *this) static void dxr3_zoomTV(dxr3_driver_t *this) { em8300_register_t frame, visible, update; - + /* change left bound */ frame.microcode_register = 1; frame.reg = 93; // dicom frame left frame.val = 0x10; - + visible.microcode_register = 1; visible.reg = 97; // dicom visible left visible.val = 0x10; - + update.microcode_register = 1; update.reg = 65; // dicom_update update.val = 1; - + ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame); ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible); ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update); @@ -1554,15 +1552,15 @@ static void dxr3_zoomTV(dxr3_driver_t *this) frame.microcode_register = 1; frame.reg = 94; // dicom frame right frame.val = 0x10; - + visible.microcode_register = 1; visible.reg = 98; // dicom visible right visible.val = 968; - + update.microcode_register = 1; update.reg = 65; // dicom_update update.val = 1; - + ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &frame); ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &visible); ioctl(this->fd_control, EM8300_IOCTL_WRITEREG, &update); @@ -1573,7 +1571,7 @@ static void dxr3_update_add_bars(void *data, xine_cfg_entry_t *entry) { dxr3_driver_t *this = (dxr3_driver_t *)data; this->add_bars = entry->num_value; - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting add_bars to correct aspect ratio to %s\n", (this->add_bars ? "on" : "off")); } @@ -1581,7 +1579,7 @@ static void dxr3_update_swap_fields(void *data, xine_cfg_entry_t *entry) { dxr3_driver_t *this = (dxr3_driver_t *)data; this->swap_fields = entry->num_value; - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting swap fields to %s\n", (this->swap_fields ? "on" : "off")); } @@ -1589,6 +1587,6 @@ static void dxr3_update_enhanced_mode(void *data, xine_cfg_entry_t *entry) { dxr3_driver_t *this = (dxr3_driver_t *)data; this->enhanced_mode = entry->num_value; - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "video_out_dxr3: setting enhanced encoding playback to %s\n", (this->enhanced_mode ? "on" : "off")); } diff --git a/src/dxr3/video_out_dxr3.h b/src/dxr3/video_out_dxr3.h index 0297204dd..4dce49f4d 100644 --- a/src/dxr3/video_out_dxr3.h +++ b/src/dxr3/video_out_dxr3.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2001 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -48,7 +48,7 @@ struct coeff { typedef struct dxr3_overlay_s { xine_t *xine; - + int fd_control; int xoffset; @@ -70,12 +70,12 @@ typedef struct dxr3_overlay_s { typedef struct dxr3_driver_class_s { video_driver_class_t video_driver_class; xine_t *xine; - + int visual_type; int instance; /* we allow only one instance of this plugin */ - + int devnum; - + dxr3_scr_t *scr; /* to provide dxr3 clocking */ } dxr3_driver_class_t; @@ -89,11 +89,11 @@ typedef struct dxr3_driver_s { pthread_mutex_t spu_device_lock; int fd_spu; /* to access the relevant dxr3 devices */ int clut_cluttered; /* to tell spu decoder that it has to restore the palette */ - + int enhanced_mode; int swap_fields; /* swap fields */ int add_bars; /* add black bars to correct a.r. */ - + int aspect; int tv_mode; int pan_scan; @@ -105,14 +105,14 @@ typedef struct dxr3_driver_s { encoder_data_t *enc; /* mpeg encoder data */ spu_encoder_t *spu_enc; /* spu encoder */ int need_update; /* the mpeg encoder needs to be updated */ - + uint32_t video_iheight; /* input height (before adding black bars) */ uint32_t video_oheight; /* output height (after adding black bars) */ uint32_t video_width; double video_ratio; int video_aspect; int top_bar; /* the height of the upper black bar */ - + vo_scale_t scale; alphablend_t alphablend_extra_data; @@ -143,10 +143,10 @@ struct encoder_data_s { int (*on_display_frame)(dxr3_driver_t *, dxr3_frame_t *); int (*on_unneeded)(dxr3_driver_t *); int (*on_close)(dxr3_driver_t *); - + /* this is only used by the libavcodec encoder */ void *handle; -}; +}; struct spu_encoder_s { vo_overlay_t *overlay; diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 81dd62eca..0748c8f29 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = input_dvd.c input_vcd.c input_gnome_vfs.c input_rtp.c @@ -45,7 +46,10 @@ endif if WIN32 else in_rtp = xineplug_inp_rtp.la -in_dvb = xineplug_inp_dvb.la +endif + +if DVB +in_dvb = xineplug_inp_dvb.la endif AM_CFLAGS = -D_LARGEFILE64_SOURCE $(GNOME_VFS_CFLAGS) $(ALSA_CFLAGS) $(DVD_CFLAGS) diff --git a/src/input/base64.c b/src/input/base64.c index ffb039802..17fa6f48a 100644 --- a/src/input/base64.c +++ b/src/input/base64.c @@ -25,17 +25,17 @@ MusicBrainz -- The Internet music metadatabase Copyright (C) 2000 Robert Kaye - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/input/base64.h b/src/input/base64.h index 5cc94d7f0..107704a6a 100644 --- a/src/input/base64.h +++ b/src/input/base64.h @@ -25,17 +25,17 @@ MusicBrainz -- The Internet music metadatabase Copyright (C) 2000 Robert Kaye - + This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/input/dvb/Makefile.am b/src/input/dvb/Makefile.am index 229ac21bf..84310507c 100644 --- a/src/input/dvb/Makefile.am +++ b/src/input/dvb/Makefile.am @@ -2,4 +2,4 @@ include $(top_srcdir)/misc/Makefile.common noinst_HEADERS = \ dmx.h \ - frontend.h + frontend.h diff --git a/src/input/dvb/dmx.h b/src/input/dvb/dmx.h index 51d3c48cd..018c7de59 100644 --- a/src/input/dvb/dmx.h +++ b/src/input/dvb/dmx.h @@ -1,4 +1,4 @@ -/* +/* * dmx.h * * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de> @@ -149,7 +149,7 @@ struct dmx_event typedef struct dmx_caps { uint32_t caps; - int num_decoders; + int num_decoders; } dmx_caps_t; typedef enum { @@ -164,7 +164,7 @@ typedef enum { } dmx_source_t; -#define DMX_START _IO('o',41) +#define DMX_START _IO('o',41) #define DMX_STOP _IO('o',42) #define DMX_SET_FILTER _IOW('o',43,struct dmx_sct_filter_params) #define DMX_SET_PES_FILTER _IOW('o',44,struct dmx_pes_filter_params) diff --git a/src/input/http_helper.c b/src/input/http_helper.c index 4883763b0..eb28140ff 100644 --- a/src/input/http_helper.c +++ b/src/input/http_helper.c @@ -29,8 +29,18 @@ #include "xine_internal.h" #include "http_helper.h" + +const char *_x_url_user_agent (const char *url) +{ + if (!strncasecmp (url, "qthttp://", 9)) + return "QuickTime"; /* needed for Apple trailers */ + return NULL; +} + int _x_parse_url (char *url, char **proto, char** host, int *port, - char **user, char **password, char **uri) { + char **user, char **password, char **uri, + const char **user_agent) +{ char *start = NULL; char *authcolon = NULL; char *at = NULL; @@ -55,14 +65,17 @@ int _x_parse_url (char *url, char **proto, char** host, int *port, *password = NULL; *uri = NULL; - /* proto */ + /* proto */ start = strstr(url, "://"); if (!start || (start == url)) goto error; - + end = start + strlen(start) - 1; *proto = strndup(url, start - url); + if (user_agent) + *user_agent = _x_url_user_agent (url); + /* user:password */ start += 3; at = strchr(start, '@'); @@ -72,10 +85,10 @@ int _x_parse_url (char *url, char **proto, char** host, int *port, semicolon = strchr(start, ';'); if (semicolon && (!slash || (semicolon < slash))) slash = semicolon; - + if (at && slash && (at > slash)) at = NULL; - + if (at) { authcolon = strchr(start, ':'); if(authcolon && authcolon < at) { @@ -166,7 +179,7 @@ int _x_parse_url (char *url, char **proto, char** host, int *port, escapechars++; it++; } - + if ( escapechars == 0 ) *uri = strdup(start); else { @@ -185,14 +198,15 @@ int _x_parse_url (char *url, char **proto, char** host, int *port, } else *it = start[i]; } + *it = '\0'; } } } else { *uri = strdup("/"); } - + return 1; - + error: if (*proto) { free (*proto); @@ -217,7 +231,7 @@ error: free (*uri); *uri = NULL; } - return 0; + return 0; } char *_x_canonicalise_url (const char *base, const char *url) { @@ -240,8 +254,7 @@ char *_x_canonicalise_url (const char *base, const char *url) { ++cut; } base_length = cut ? (size_t)(cut - base) : strlen (base); - ret = malloc (base_length + strlen (url) + 1); - sprintf (ret, "%.*s%s", (int)base_length, base, url); + asprintf (&ret, "%.*s%s", (int)base_length, base, url); return ret; } @@ -254,11 +267,11 @@ static int check_url(char *url, int ok) { char *proto, *host, *user, *password, *uri; int port; int res; - + printf("--------------------------------\n"); printf("url=%s\n", url); res = _x_parse_url (url, - &proto, &host, &port, &user, &password, &uri); + &proto, &host, &port, &user, &password, &uri, NULL); if (res) { printf("proto=%s, host=%s, port=%d, user=%s, password=%s, uri=%s\n", proto, host, port, user, password, uri); @@ -297,7 +310,7 @@ static int check_paste(const char *base, const char *url, const char *ok) { int main(int argc, char** argv) { char *proto, host, port, user, password, uri; int res = 0; - + res += check_url("http://www.toto.com/test1.asx", 1); res += check_url("http://www.toto.com:8080/test2.asx", 1); res += check_url("http://titi:pass@www.toto.com:8080/test3.asx", 1); diff --git a/src/input/http_helper.h b/src/input/http_helper.h index 3ce3f2b7c..68299a2ea 100644 --- a/src/input/http_helper.h +++ b/src/input/http_helper.h @@ -24,6 +24,16 @@ #define HTTP_HELPER_H /* + * user agent finder, using modified protcol names + * {proto}://... + * e.g. "qthttp://example.com/foo.mov" → "QuickTime" + * + * return: + * NULL or user agent prefix + */ +const char *_x_url_user_agent (const char *url); + +/* * url parser * {proto}://{user}:{password}@{host}:{port}{uri} * {proto}://{user}:{password}@{[host]}:{port}{uri} @@ -33,7 +43,8 @@ * 1 valid url */ int _x_parse_url (char *url, char **proto, char** host, int *port, - char **user, char **password, char **uri); + char **user, char **password, char **uri, + const char **user_agent); /* * canonicalise url, given base diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index fd4dd1fa9..1751f031c 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2005 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * Compact Disc Digital Audio (CDDA) Input Plugin + * Compact Disc Digital Audio (CDDA) Input Plugin * by Mike Melanson (melanson@pcisys.net) */ @@ -44,6 +44,7 @@ # include <sys/ioctl.h> #else /* for WIN32 */ +# include <windef.h> # include <winioctl.h> #endif @@ -70,6 +71,8 @@ #define DEFAULT_CDDA_DEVICE "/vol/dev/aliases/cdrom0" #elif defined(WIN32) #define DEFAULT_CDDA_DEVICE "d:\\" +#elif defined(__OpenBSD__) +#define DEFAULT_CDDA_DEVICE "/dev/rcd0c" #else #define DEFAULT_CDDA_DEVICE "/dev/cdrom" #endif @@ -110,7 +113,7 @@ typedef struct _cdrom_toc { *************************************************************************/ #define MAX_TRACKS 99 -#define CACHED_FRAMES 500 +#define CACHED_FRAMES 100 typedef struct { int start; @@ -126,8 +129,8 @@ typedef struct { int enabled; char *server; int port; - char *cache_dir; - + char *cache_dir; + char *cdiscid; char *disc_title; char *disc_year; @@ -135,7 +138,7 @@ typedef struct { char *disc_category; int fd; - unsigned long disc_id; + uint32_t disc_id; int disc_length; trackinfo_t *track; @@ -175,7 +178,7 @@ typedef struct { char *cdda_device; int cddb_error; - + cdda_input_plugin_t *ip; int show_hidden_files; @@ -183,7 +186,7 @@ typedef struct { int mrls_allocated_entries; xine_mrl_t **mrls; - + char *autoplaylist[MAX_TRACKS]; } cdda_input_class_t; @@ -315,54 +318,54 @@ struct SRB_ExecSCSICmd #ifdef LOG static void print_cdrom_toc(cdrom_toc *toc) { - + int i; int time1; int time2; int timediff; - + printf("\ntoc:\n"); printf("\tfirst track = %d\n", toc->first_track); printf("\tlast track = %d\n", toc->last_track); printf("\ttotal tracks = %d\n", toc->total_tracks); printf("\ntoc entries:\n"); - - + + printf("leadout track: Control: %d MSF: %02d:%02d:%04d, first frame = %d\n", toc->leadout_track.track_mode, toc->leadout_track.first_frame_minute, toc->leadout_track.first_frame_second, toc->leadout_track.first_frame_frame, toc->leadout_track.first_frame); - + /* fetch each toc entry */ - if (toc->first_track > 0) { - for (i = toc->first_track; i <= toc->last_track; i++) { + if (toc->first_track > 0) { + for (i = toc->first_track; i <= toc->last_track; i++) { printf("\ttrack mode = %d", toc->toc_entries[i-1].track_mode); - printf("\ttrack %d, audio, MSF: %02d:%02d:%02d, first frame = %d\n", - i, + printf("\ttrack %d, audio, MSF: %02d:%02d:%02d, first frame = %d\n", + i, toc->toc_entries[i-1].first_frame_minute, toc->toc_entries[i-1].first_frame_second, toc->toc_entries[i-1].first_frame_frame, toc->toc_entries[i-1].first_frame); - - time1 = ((toc->toc_entries[i-1].first_frame_minute * 60) + + + time1 = ((toc->toc_entries[i-1].first_frame_minute * 60) + toc->toc_entries[i-1].first_frame_second); - + if (i == toc->last_track) { time2 = ((toc->leadout_track.first_frame_minute * 60) + toc->leadout_track.first_frame_second); } else { - time2 = ((toc->toc_entries[i].first_frame_minute * 60) + + time2 = ((toc->toc_entries[i].first_frame_minute * 60) + toc->toc_entries[i].first_frame_second); } - + timediff = time2 - time1; - + printf("\t time: %02d:%02d\n", timediff/60, timediff%60); } - } + } } #endif @@ -370,7 +373,7 @@ static cdrom_toc * init_cdrom_toc(void) { cdrom_toc *toc; - toc = (cdrom_toc *) xine_xmalloc(sizeof (cdrom_toc)); + toc = calloc(1, sizeof (cdrom_toc)); toc->first_track = toc->last_track = toc->total_tracks = 0; toc->toc_entries = NULL; @@ -416,12 +419,11 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { toc->ignore_last_track = 0; } toc->total_tracks = toc->last_track - toc->first_track + 1; - + /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -529,10 +531,9 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -612,7 +613,7 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f return 0; } -#elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) +#elif defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) #include <sys/cdio.h> @@ -625,7 +626,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { struct ioc_toc_header tochdr; #if defined(__FreeBSD_kernel__) struct ioc_read_toc_single_entry tocentry; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) struct ioc_read_toc_entry tocentry; struct cd_toc_entry data; #endif @@ -642,10 +643,9 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -661,7 +661,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { perror("CDIOREADTOCENTRY"); return -1; } -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) memset(&data, 0, sizeof(data)); tocentry.data_len = sizeof(data); tocentry.data = &data; @@ -682,7 +682,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { (tocentry.entry.addr.msf.minute * CD_SECONDS_PER_MINUTE * CD_FRAMES_PER_SECOND) + (tocentry.entry.addr.msf.second * CD_FRAMES_PER_SECOND) + tocentry.entry.addr.msf.frame; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) toc->toc_entries[i-1].track_mode = (tocentry.data->control & 0x04) ? 1 : 0; toc->toc_entries[i-1].first_frame_minute = tocentry.data->addr.msf.minute; toc->toc_entries[i-1].first_frame_second = tocentry.data->addr.msf.second; @@ -704,7 +704,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { perror("CDIOREADTOCENTRY"); return -1; } -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) memset(&data, 0, sizeof(data)); tocentry.data_len = sizeof(data); tocentry.data = &data; @@ -725,7 +725,7 @@ static int read_cdrom_toc(int fd, cdrom_toc *toc) { (tocentry.entry.addr.msf.minute * CD_SECONDS_PER_MINUTE * CD_FRAMES_PER_SECOND) + (tocentry.entry.addr.msf.second * CD_FRAMES_PER_SECOND) + tocentry.entry.addr.msf.frame; -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) toc->leadout_track.track_mode = (tocentry.data->control & 0x04) ? 1 : 0; toc->leadout_track.first_frame_minute = tocentry.data->addr.msf.minute; toc->leadout_track.first_frame_second = tocentry.data->addr.msf.second; @@ -763,7 +763,7 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f perror("CDIOCREADAUDIO"); return -1; } -#elif defined(__NetBSD__) +#elif defined(__NetBSD__) || defined(__OpenBSD__) scsireq_t req; int nblocks = 1; @@ -790,7 +790,7 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f return -1; } #endif - + data += CD_RAW_FRAME_SIZE; frame++; num_frames--; @@ -807,45 +807,44 @@ static int read_cdrom_toc(cdda_input_plugin_t *this_gen, cdrom_toc *toc) { /* This is for ASPI which obviously isn't supported! */ lprintf("Windows ASPI support is not complete yet!\n"); return -1; - + } else { DWORD dwBytesReturned; CDROM_TOC cdrom_toc; int i; - + if( DeviceIoControl( this_gen->h_device_handle, IOCTL_CDROM_READ_TOC, NULL, 0, &cdrom_toc, sizeof(CDROM_TOC), &dwBytesReturned, NULL ) == 0 ) { #ifdef LOG - DWORD dw; + DWORD dw; printf( "input_cdda: could not read TOCHDR\n" ); dw = GetLastError(); - printf("GetLastError returned %u\n", dw); + printf("GetLastError returned %u\n", dw); #endif return -1; } - + toc->first_track = cdrom_toc.FirstTrack; toc->last_track = cdrom_toc.LastTrack; toc->total_tracks = toc->last_track - toc->first_track + 1; - + /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } - + /* fetch each toc entry */ for (i = toc->first_track; i <= toc->last_track; i++) { - + toc->toc_entries[i-1].track_mode = (cdrom_toc.TrackData[i-1].Control & 0x04) ? 1 : 0; toc->toc_entries[i-1].first_frame_minute = cdrom_toc.TrackData[i-1].Address[1]; toc->toc_entries[i-1].first_frame_second = cdrom_toc.TrackData[i-1].Address[2]; @@ -867,7 +866,7 @@ static int read_cdrom_toc(cdda_input_plugin_t *this_gen, cdrom_toc *toc) { (toc->leadout_track.first_frame_minute * CD_SECONDS_PER_MINUTE * CD_FRAMES_PER_SECOND) + (toc->leadout_track.first_frame_second * CD_FRAMES_PER_SECOND) + toc->leadout_track.first_frame_frame; - } + } return 0; } @@ -884,37 +883,37 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f /* This is for ASPI which obviously isn't supported! */ lprintf("Windows ASPI support is not complete yet!\n"); return -1; - + } else { memset(data, 0, CD_RAW_FRAME_SIZE * num_frames); - + while( num_frames ) { - + #ifdef LOG /*printf("\t Raw read frame %d\n", frame);*/ #endif raw_read_info.DiskOffset.QuadPart = frame * CD_SECTOR_SIZE; raw_read_info.SectorCount = 1; raw_read_info.TrackMode = CDDA; - + /* read a frame */ if( DeviceIoControl( this_gen->h_device_handle, IOCTL_CDROM_RAW_READ, - &raw_read_info, sizeof(RAW_READ_INFO), data, + &raw_read_info, sizeof(RAW_READ_INFO), data, CD_RAW_FRAME_SIZE, &dwBytesReturned, NULL ) == 0 ) { #ifdef LOG - DWORD dw; + DWORD dw; printf( "input_cdda: could not read frame\n" ); dw = GetLastError(); - printf("GetLastError returned %u\n", dw); + printf("GetLastError returned %u\n", dw); #endif return -1; } - + data += CD_RAW_FRAME_SIZE; frame++; num_frames--; @@ -1020,7 +1019,7 @@ network_command( xine_stream_t *stream, int socket, char *data_buf, char *msg, . if( n ) { if( !data_buf ) { if (stream) - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: protocol error, data returned but no buffer provided.\n"); return -1; } @@ -1036,13 +1035,13 @@ network_command( xine_stream_t *stream, int socket, char *data_buf, char *msg, . #ifndef WIN32 -static int network_connect(xine_stream_t *stream, char *url ) +static int network_connect(xine_stream_t *stream, const char *got_url ) { - char *host; + char *host, *url; int port; int fd; - url = strdup(url); + url = strdup(got_url); parse_url(url, &host, &port); if( !host || !strlen(host) || !port ) @@ -1081,10 +1080,9 @@ static int network_read_cdrom_toc(xine_stream_t *stream, int fd, cdrom_toc *toc) toc->total_tracks = toc->last_track - toc->first_track + 1; /* allocate space for the toc entries */ - toc->toc_entries = - (cdrom_toc_entry *)malloc(toc->total_tracks * sizeof(cdrom_toc_entry)); + toc->toc_entries = calloc(toc->total_tracks, sizeof(cdrom_toc_entry)); if (!toc->toc_entries) { - perror("malloc"); + perror("calloc"); return -1; } @@ -1146,12 +1144,12 @@ static int network_read_cdrom_frames(xine_stream_t *stream, int fd, int first_fr */ static void cdda_device_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; - + class->cdda_device = cfg->str_value; } static void enable_cddb_changed_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; - + if(class->ip) { cdda_input_plugin_t *this = class->ip; @@ -1162,7 +1160,7 @@ static void enable_cddb_changed_cb(void *data, xine_cfg_entry_t *cfg) { } static void server_changed_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; - + if(class->ip) { cdda_input_plugin_t *this = class->ip; @@ -1173,7 +1171,7 @@ static void server_changed_cb(void *data, xine_cfg_entry_t *cfg) { } static void port_changed_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; - + if(class->ip) { cdda_input_plugin_t *this = class->ip; @@ -1184,7 +1182,7 @@ static void port_changed_cb(void *data, xine_cfg_entry_t *cfg) { } static void cachedir_changed_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; - + if(class->ip) { cdda_input_plugin_t *this = class->ip; @@ -1194,7 +1192,7 @@ static void cachedir_changed_cb(void *data, xine_cfg_entry_t *cfg) { #ifdef CDROM_SELECT_SPEED static void speed_changed_cb(void *data, xine_cfg_entry_t *cfg) { cdda_input_class_t *class = (cdda_input_class_t *) data; - + if (class->ip) { cdda_input_plugin_t *this = class->ip; if (this->fd != -1) @@ -1211,21 +1209,21 @@ static void speed_changed_cb(void *data, xine_cfg_entry_t *cfg) { static int _cdda_is_cd_changed(cdda_input_plugin_t *this) { #ifdef CDROM_MEDIA_CHANGED int err, cd_changed=0; - + if(this == NULL || this->fd < 0) return -1; - + if((err = ioctl(this->fd, CDROM_MEDIA_CHANGED, cd_changed)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: ioctl(CDROM_MEDIA_CHANGED) failed: %s.\n", strerror(errno)); return -1; } - + switch(err) { case 1: return 1; break; - + default: return 0; break; @@ -1235,7 +1233,7 @@ static int _cdda_is_cd_changed(cdda_input_plugin_t *this) { #else /* * At least on solaris, CDROM_MEDIA_CHANGED does not exist. Just return an - * error for now + * error for now */ return -1; #endif @@ -1245,18 +1243,18 @@ static int _cdda_is_cd_changed(cdda_input_plugin_t *this) { * create a directory, in safe mode */ static void _cdda_mkdir_safe(xine_t *xine, char *path) { - + if(path == NULL) return; - + #ifndef WIN32 { struct stat pstat; - + if((stat(path, &pstat)) < 0) { /* file or directory no exist, create it */ if(mkdir(path, 0755) < 0) { - xprintf(xine, XINE_VERBOSITY_DEBUG, + xprintf(xine, XINE_VERBOSITY_DEBUG, "input_cdda: mkdir(%s) failed: %s.\n", path, strerror(errno)); return; } @@ -1273,10 +1271,10 @@ static void _cdda_mkdir_safe(xine_t *xine, char *path) { HANDLE hList; TCHAR szDir[MAX_PATH+3]; WIN32_FIND_DATA FileData; - + // Get the proper directory path sprintf(szDir, "%s\\*", path); - + // Get the first file hList = FindFirstFile(szDir, &FileData); if (hList == INVALID_HANDLE_VALUE) @@ -1284,9 +1282,9 @@ static void _cdda_mkdir_safe(xine_t *xine, char *path) { if(_mkdir(path) != 0) { xprintf(xine, XINE_VERBOSITY_DEBUG, "input_cdda: mkdir(%s) failed.\n", path); return; - } + } } - + FindClose(hList); } #endif /* WIN32 */ @@ -1312,18 +1310,15 @@ static void _cdda_mkdir_recursive_safe(xine_t *xine, char *path) { if(p && strlen(p)) { #ifdef WIN32 - if (*buf2 != '\0') { + if (*buf2 != '\0') { #endif - - int size = strlen(buf2); - snprintf(buf2 + size, sizeof(buf2) - size, "/%s", p); - + size_t size = strlen(buf2); + snprintf(buf2 + size, sizeof(buf2) - size, "/%s", p); #ifdef WIN32 - } - else { - snprintf(buf2, sizeof(buf2), "%s", p); - } - + } + else { + snprintf(buf2, sizeof(buf2), "%s", p); + } #endif /* WIN32 */ _cdda_mkdir_safe(xine, buf2); @@ -1336,10 +1331,10 @@ static void _cdda_mkdir_recursive_safe(xine_t *xine, char *path) { */ static char *_cdda_cddb_get_default_location(void) { static char buf[XINE_PATH_MAX + XINE_NAME_MAX + 1]; - + memset(&buf, 0, sizeof(buf)); snprintf(buf, sizeof(buf), "%s/.xine/cddbcache", (xine_get_homedir())); - + return buf; } @@ -1359,12 +1354,12 @@ static int _cdda_cddb_socket_read(cdda_input_plugin_t *this, char *str, int size * Send a command to socket */ static int _cdda_cddb_send_command(cdda_input_plugin_t *this, char *cmd) { - + if((this == NULL) || (this->cddb.fd < 0) || (cmd == NULL)) return -1; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, ">>> %s\n", cmd); - + return (int)_x_io_tcp_write(this->stream, this->cddb.fd, cmd, strlen(cmd)); } @@ -1434,37 +1429,102 @@ static int _cdda_cddb_handle_code(char *buf) { break; } } - + return err; } +static inline char *_cdda_append (/*const*/ char *first, const char *second) +{ + if (!first) + return strdup (second); + + char *result = (char *) realloc (first, strlen (first) + strlen (second) + 1); + strcat (result, second); + return result; +} + +static void _cdda_parse_cddb_info (cdda_input_plugin_t *this, char *buffer, char **dtitle) +{ + /* buffer should be no more than 2048 bytes... */ + char buf[2048]; + int track_no; + + if (sscanf (buffer, "DTITLE=%s", &buf[0]) == 1) { + char *pt = strchr (buffer, '='); + if (pt) { + ++pt; + + *dtitle = _cdda_append (*dtitle, pt); + pt = strdup (*dtitle); + + char *title = strstr (pt, " / "); + if (title) + { + *title = 0; + title += 3; + free (this->cddb.disc_artist); + this->cddb.disc_artist = strdup (pt); + } + else + title = pt; + + free (this->cddb.disc_title); + this->cddb.disc_title = strdup (title); + + free (pt); + } + } + else if (sscanf (buffer, "DYEAR=%s", &buf[0]) == 1) { + char *pt = strchr (buffer, '='); + if (pt && strlen (pt) == 5) + this->cddb.disc_year = strdup (pt + 1); + } + else if(sscanf(buffer, "DGENRE=%s", &buf[0]) == 1) { + char *pt = strchr(buffer, '='); + if (pt) + this->cddb.disc_category = strdup (pt + 1); + } + else if (sscanf (buffer, "TTITLE%d=%s", &track_no, &buf[0]) == 2) { + char *pt = strchr(buffer, '='); + this->cddb.track[track_no].title = _cdda_append (this->cddb.track[track_no].title, pt + 1); + } + else if (!strncmp (buffer, "EXTD=", 5)) + { + if (!this->cddb.disc_year) + { + int nyear; + char *y = strstr (buffer, "YEAR:"); + if (y && sscanf (y + 5, "%4d", &nyear) == 1) + asprintf (&this->cddb.disc_year, "%d", nyear); + } + } +} + /* * Try to load cached cddb infos */ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { char cdir[XINE_PATH_MAX + XINE_NAME_MAX + 1]; + size_t cdir_size = 0; DIR *dir; if(this == NULL) return 0; - - memset(&cdir, 0, sizeof(cdir)); - snprintf(cdir, sizeof(cdir), "%s", this->cddb.cache_dir); - + + cdir_size = snprintf(cdir, sizeof(cdir), "%s", this->cddb.cache_dir); + if((dir = opendir(cdir)) != NULL) { struct dirent *pdir; - + while((pdir = readdir(dir)) != NULL) { char discid[9]; - - memset(&discid, 0, sizeof(discid)); - snprintf(discid, sizeof(discid), "%08lx", this->cddb.disc_id); - + + snprintf(discid, sizeof(discid), "%08" PRIx32, this->cddb.disc_id); + if(!strcasecmp(pdir->d_name, discid)) { FILE *fd; - int size = strlen(cdir); - - snprintf(cdir + size, sizeof(cdir) - size, "/%s", discid); + + cdir_size += snprintf(cdir + cdir_size, sizeof(cdir) - cdir_size, "/%s", discid); if((fd = fopen(cdir, "r")) == NULL) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: fopen(%s) failed: %s.\n", cdir, strerror(errno)); @@ -1472,101 +1532,30 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { return 0; } else { - char buffer[256], *ln; - char buf[256]; - int tnum; + char buffer[2048], *ln; char *dtitle = NULL; - - while ((ln = fgets(buffer, 255, fd)) != NULL) { - - buffer[strlen(buffer) - 1] = '\0'; - - if (sscanf(buffer, "DTITLE=%s", &buf[0]) == 1) { - char *pt, *artist, *title; - - pt = strrchr(buffer, '='); - if (pt) { - pt++; - - if (dtitle != NULL) - { - dtitle = (char *) realloc(dtitle, strlen(dtitle) + strlen(pt) + 1); - strcat(dtitle, pt); - pt = dtitle; - } - dtitle = strdup(pt); - - artist = pt; - title = strstr(pt, " / "); - if (title) { - *title++ = '\0'; - title += 2; - } - else { - title = artist; - artist = NULL; - } - - if (artist) - this->cddb.disc_artist = strdup(artist); - - this->cddb.disc_title = strdup(title); - } - } - else if (sscanf(buffer, "DYEAR=%s", &buf[0]) == 1) { - char *pt; - pt = strrchr(buffer, '='); - pt++; - if (pt != NULL && strlen(pt) == 4) - this->cddb.disc_year = strdup(pt); - } - else if (sscanf(buffer, "TTITLE%d=%s", &tnum, &buf[0]) == 2) { - char *pt; - - pt = strrchr(buffer, '='); - if (pt) - pt++; - if (this->cddb.track[tnum].title == NULL) - this->cddb.track[tnum].title = strdup(pt); - else - { - this->cddb.track[tnum].title - = (char *) realloc(this->cddb.track[tnum].title, strlen(this->cddb.track[tnum].title) + strlen(pt) + 1); - strcat(this->cddb.track[tnum].title, pt); - } - } - else { - if (!strncmp(buffer, "EXTD=", 5)) { - char *y; - int nyear; - - y = strstr(buffer, "YEAR:"); - if(y) { - if (sscanf(y+5, "%4d", &nyear) == 1) { - char year[5]; - - snprintf(year, 5, "%d", nyear); - if (this->cddb.disc_year == NULL) - this->cddb.disc_year = strdup(year); - } - } - } - } + while ((ln = fgets(buffer, sizeof (buffer) - 1, fd)) != NULL) { + + int length = strlen (buffer); + if (length && buffer[length - 1] == '\n') + buffer[length - 1] = '\0'; + + _cdda_parse_cddb_info (this, buffer, &dtitle); } fclose(fd); free(dtitle); } - + closedir(dir); return 1; } } xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "input_cdda: cached entry for disc ID %08lx not found.\n", this->cddb.disc_id); + "input_cdda: cached entry for disc ID %08" PRIx32 " not found.\n", this->cddb.disc_id); closedir(dir); } - + return 0; } @@ -1576,19 +1565,19 @@ static int _cdda_load_cached_cddb_infos(cdda_input_plugin_t *this) { static void _cdda_save_cached_cddb_infos(cdda_input_plugin_t *this, char *filecontent) { char cfile[XINE_PATH_MAX + XINE_NAME_MAX + 1]; FILE *fd; - + if((this == NULL) || (filecontent == NULL)) return; - + memset(&cfile, 0, sizeof(cfile)); /* Ensure "~/.xine/cddbcache" exist */ snprintf(cfile, sizeof(cfile), "%s", this->cddb.cache_dir); - + _cdda_mkdir_recursive_safe(this->stream->xine, cfile); - - snprintf(cfile, sizeof(cfile), "%s/%08lx", this->cddb.cache_dir, this->cddb.disc_id); - + + snprintf(cfile, sizeof(cfile), "%s/%08" PRIx32 , this->cddb.cache_dir, this->cddb.disc_id); + if((fd = fopen(cfile, "w")) == NULL) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: fopen(%s) failed: %s.\n", cfile, strerror(errno)); @@ -1598,7 +1587,7 @@ static void _cdda_save_cached_cddb_infos(cdda_input_plugin_t *this, char *fileco fprintf(fd, "%s", filecontent); fclose(fd); } - + } /* @@ -1626,7 +1615,7 @@ static int _cdda_cddb_socket_open(cdda_input_plugin_t *this) { * Close the socket */ static void _cdda_cddb_socket_close(cdda_input_plugin_t *this) { - + if((this == NULL) || (this->cddb.fd < 0)) return; @@ -1646,7 +1635,7 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { if(this == NULL) { return 0; } - + if(_cdda_load_cached_cddb_infos(this)) { this->cddb.have_cddb_info = 1; return 1; @@ -1726,22 +1715,21 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { /* Send query command */ memset(&buffer, 0, sizeof(buffer)); - sprintf(buffer, "cddb query %08lx %d ", this->cddb.disc_id, this->cddb.num_tracks); + size_t size = sprintf(buffer, "cddb query %08" PRIx32 " %d ", this->cddb.disc_id, this->cddb.num_tracks); for (i = 0; i < this->cddb.num_tracks; i++) { - int size = strlen(buffer); - snprintf(buffer + size, sizeof(buffer) - size, "%d ", this->cddb.track[i].start); + size += snprintf(buffer + size, sizeof(buffer) - size, "%d ", this->cddb.track[i].start); } - snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%d\n", this->cddb.disc_length); + snprintf(buffer + strlen(buffer), sizeof(buffer) - size, "%d\n", this->cddb.disc_length); if ((err = _cdda_cddb_send_command(this, buffer)) <= 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: error while sending cddb query command.\n"); _cdda_cddb_socket_close(this); - return 0; + return 0; } memset(&buffer, 0, sizeof(buffer)); err = _cdda_cddb_socket_read(this, buffer, sizeof(buffer) - 1); - if (err < 0 || (((err = _cdda_cddb_handle_code(buffer)) != 200) && (err != 210))) { + if (err < 0 || (((err = _cdda_cddb_handle_code(buffer)) != 200) && (err != 210) && (err != 211))) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_cdda: cddb query command returned error code '%03d'.\n", err); _cdda_cddb_socket_close(this); @@ -1761,8 +1749,8 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { i++; } } - - if (err == 210) { + + if ((err == 210) || (err == 211)) { memset(&buffer, 0, sizeof(buffer)); err = _cdda_cddb_socket_read(this, buffer, sizeof(buffer) - 1); if (err < 0) { @@ -1792,7 +1780,7 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { return 0; } } - } + } /* Send read command */ memset(&buffer, 0, sizeof(buffer)); snprintf(buffer, sizeof(buffer), "cddb read %s %s\n", this->cddb.disc_category, this->cddb.cdiscid); @@ -1811,95 +1799,21 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { _cdda_cddb_socket_close(this); return 0; } - + this->cddb.have_cddb_info = 1; memset(&buffercache, 0, sizeof(buffercache)); while (strcmp(buffer, ".")) { - char buf[2048]; - int tnum; - int bufsize = strlen(buffercache); + size_t bufsize = strlen(buffercache); memset(&buffer, 0, sizeof(buffer)); _cdda_cddb_socket_read(this, buffer, sizeof(buffer) - 1); snprintf(buffercache + bufsize, sizeof(buffercache) - bufsize, "%s\n", buffer); - if (sscanf(buffer, "DTITLE=%s", &buf[0]) == 1) { - char *pt, *artist, *title; - - pt = strrchr(buffer, '='); - if (pt) { - pt++; - - if (dtitle != NULL) - { - dtitle = (char *) realloc(dtitle, strlen(dtitle) + strlen(pt) + 1); - strcat(dtitle, pt); - pt = dtitle; - } - dtitle = strdup(pt); - - artist = pt; - title = strstr(pt, " / "); - if (title) { - *title++ = '\0'; - title += 2; - } - else { - title = artist; - artist = NULL; - } - - if (artist) { - this->cddb.disc_artist = strdup(artist); - } - this->cddb.disc_title = strdup(title); - } - } - else if(sscanf(buffer, "DYEAR=%s", &buf[0]) == 1) { - char *pt; - - pt = strrchr(buffer, '='); - pt++; - if (pt != NULL && strlen(pt) == 4) - this->cddb.disc_year = strdup(pt); - } - else if (sscanf(buffer, "TTITLE%d=%s", &tnum, &buf[0]) == 2) { - char *pt; - - pt = strrchr(buffer, '='); - if (pt) { - pt++; - if (this->cddb.track[tnum].title == NULL) - this->cddb.track[tnum].title = strdup(pt); - else - { - this->cddb.track[tnum].title - = (char *) realloc(this->cddb.track[tnum].title, strlen(this->cddb.track[tnum].title) + strlen(pt) + 1); - strcat(this->cddb.track[tnum].title, pt); - } - } - } - else { - if (!strncmp(buffer, "EXTD=", 5)) { - char *y; - int nyear; - - y = strstr(buffer, "YEAR:"); - if (y) { - if (sscanf(y+5, "%4d", &nyear) == 1) { - char year[5]; - - snprintf(year, 5, "%d", nyear); - if (this->cddb.disc_year == NULL) - this->cddb.disc_year = strdup(year); - } - } - } - } + _cdda_parse_cddb_info (this, buffer, &dtitle); } free(dtitle); - + /* Save cddb info and close socket */ _cdda_save_cached_cddb_infos(this, buffercache); _cdda_cddb_socket_close(this); @@ -1915,24 +1829,24 @@ static int _cdda_cddb_retrieve(cdda_input_plugin_t *this) { */ static unsigned int _cdda_cddb_sum(int n) { unsigned int ret = 0; - + while(n > 0) { ret += (n % 10); n /= 10; } return ret; } -static unsigned long _cdda_calc_cddb_id(cdda_input_plugin_t *this) { +static uint32_t _cdda_calc_cddb_id(cdda_input_plugin_t *this) { int i, tsum = 0; - + if(this == NULL || (this->cddb.num_tracks <= 0)) return 0; - + for(i = 0; i < this->cddb.num_tracks; i++) tsum += _cdda_cddb_sum((this->cddb.track[i].start / CD_FRAMES_PER_SECOND)); - + return ((tsum % 0xff) << 24 - | (this->cddb.disc_length - (this->cddb.track[0].start / CD_FRAMES_PER_SECOND)) << 8 + | (this->cddb.disc_length - (this->cddb.track[0].start / CD_FRAMES_PER_SECOND)) << 8 | this->cddb.num_tracks); } @@ -1979,7 +1893,7 @@ static void _cdda_cdindex(cdda_input_plugin_t *this, cdrom_toc *toc) { /* * return cbbd disc id. */ -static unsigned long _cdda_get_cddb_id(cdda_input_plugin_t *this) { +static uint32_t _cdda_get_cddb_id(cdda_input_plugin_t *this) { if(this == NULL || (this->cddb.num_tracks <= 0)) return 0; @@ -2001,22 +1915,22 @@ static void _cdda_free_cddb_info(cdda_input_plugin_t *this) { } free(this->cddb.track); - + if(this->cddb.cdiscid) free(this->cddb.cdiscid); - + if(this->cddb.disc_title) free(this->cddb.disc_title); - + if(this->cddb.disc_artist) free(this->cddb.disc_artist); if(this->cddb.disc_category) free(this->cddb.disc_category); - + if(this->cddb.disc_year) free(this->cddb.disc_year); - + } } /* @@ -2024,12 +1938,12 @@ static void _cdda_free_cddb_info(cdda_input_plugin_t *this) { */ static int cdda_open(cdda_input_plugin_t *this_gen, - char *cdda_device, cdrom_toc *toc, int *fdd) { + const char *cdda_device, cdrom_toc *toc, int *fdd) { #ifndef WIN32 int fd = -1; if ( !cdda_device ) return -1; - + *fdd = -1; if (this_gen) @@ -2044,7 +1958,7 @@ static int cdda_open(cdda_input_plugin_t *this_gen, if (this_gen) this_gen->fd = fd; - + #ifdef CDROM_SELECT_SPEED if (this_gen->stream) { int speed; @@ -2074,17 +1988,17 @@ static int cdda_open(cdda_input_plugin_t *this_gen, else return -1; - /* We are going to assume that we are opening a + /* We are going to assume that we are opening a * device and not a file! */ if( WIN_NT ) { char psz_win32_drive[7]; - + lprintf( "using winNT/2K/XP ioctl layer" ); - + sprintf( psz_win32_drive, "\\\\.\\%c:", cdda_device[0] ); - + this_gen->h_device_handle = CreateFile( psz_win32_drive, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, @@ -2100,89 +2014,89 @@ static int cdda_open(cdda_input_plugin_t *this_gen, DWORD dwSupportInfo; int i, j, i_hostadapters; char c_drive = cdda_device[0]; - + hASPI = LoadLibrary( "wnaspi32.dll" ); if( hASPI != NULL ) { - (FARPROC) lpGetSupport = GetProcAddress( hASPI, + lpGetSupport = GetProcAddress( hASPI, "GetASPI32SupportInfo" ); - (FARPROC) lpSendCommand = GetProcAddress( hASPI, + lpSendCommand = GetProcAddress( hASPI, "SendASPI32Command" ); } - + if( hASPI == NULL || lpGetSupport == NULL || lpSendCommand == NULL ) { lprintf( "unable to load aspi or get aspi function pointers" ); - + if( hASPI ) FreeLibrary( hASPI ); return -1; } - + /* ASPI support seems to be there */ - + dwSupportInfo = lpGetSupport(); - + if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) { lprintf( "no host adapters found (aspi)" ); FreeLibrary( hASPI ); return -1; } - + if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) { lprintf( "unable to initalize aspi layer" ); - + FreeLibrary( hASPI ); return -1; } - + i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); if( i_hostadapters == 0 ) { FreeLibrary( hASPI ); return -1; } - + c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A'; - + for( i = 0; i < i_hostadapters; i++ ) { for( j = 0; j < 15; j++ ) { struct SRB_GetDiskInfo srbDiskInfo; - + srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; srbDiskInfo.SRB_HaId = i; srbDiskInfo.SRB_Flags = 0; srbDiskInfo.SRB_Hdr_Rsvd = 0; srbDiskInfo.SRB_Target = j; srbDiskInfo.SRB_Lun = 0; - + lpSendCommand( (void*) &srbDiskInfo ); - + if( (srbDiskInfo.SRB_Status == SS_COMP) && (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) { /* Make sure this is a cdrom device */ struct SRB_GDEVBlock srbGDEVBlock; - + memset( &srbGDEVBlock, 0, sizeof(struct SRB_GDEVBlock) ); srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; srbGDEVBlock.SRB_HaId = i; srbGDEVBlock.SRB_Target = j; - + lpSendCommand( (void*) &srbGDEVBlock ); - + if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) { this_gen->i_sid = MAKEWORD( i, j ); this_gen->hASPI = (long)hASPI; this_gen->lpSendCommand = lpSendCommand; - + lprintf( "using aspi layer" ); - + return 0; } else @@ -2194,12 +2108,12 @@ static int cdda_open(cdda_input_plugin_t *this_gen, } } } - + FreeLibrary( hASPI ); - + lprintf( "unable to get haid and target (aspi)" ); } - + #endif /* WIN32 */ return -1; @@ -2244,26 +2158,18 @@ static int cdda_close(cdda_input_plugin_t *this_gen) { static uint32_t cdda_plugin_get_capabilities (input_plugin_t *this_gen) { - return INPUT_CAP_SEEKABLE | INPUT_CAP_BLOCK; + return INPUT_CAP_SEEKABLE; } static off_t cdda_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { - /* only allow reading in block-sized chunks */ - - return 0; -} - -static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, - off_t nlen) { - cdda_input_plugin_t *this = (cdda_input_plugin_t *) this_gen; - buf_element_t *buf; - unsigned char frame_data[CD_RAW_FRAME_SIZE]; int err = 0; - if (nlen != CD_RAW_FRAME_SIZE) + /* only allow reading in block-sized chunks */ + + if (len != CD_RAW_FRAME_SIZE) return 0; if (this->current_frame > this->last_frame) @@ -2278,9 +2184,9 @@ static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buf this->cache_last = this->current_frame + CACHED_FRAMES - 1; if( this->cache_last > this->last_frame ) this->cache_last = this->last_frame; - -#ifndef WIN32 - if ( this->fd != -1 ) + +#ifndef WIN32 + if ( this->fd != -1 ) #else if ( this->h_device_handle ) #endif /* WIN32 */ @@ -2296,15 +2202,27 @@ static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buf if( err < 0 ) return 0; - - memcpy(frame_data, this->cache[this->current_frame-this->cache_first], CD_RAW_FRAME_SIZE); + + memcpy(buf, this->cache[this->current_frame-this->cache_first], CD_RAW_FRAME_SIZE); this->current_frame++; + return CD_RAW_FRAME_SIZE; +} + +static buf_element_t *cdda_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, + off_t nlen) { + + buf_element_t *buf; + buf = fifo->buffer_pool_alloc(fifo); buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; - buf->size = CD_RAW_FRAME_SIZE; - memcpy(buf->mem, frame_data, CD_RAW_FRAME_SIZE); + + buf->size = cdda_plugin_read(this_gen, buf->content, nlen); + if (buf->size == 0) { + buf->free_buffer(buf); + buf = NULL; + } return buf; } @@ -2342,7 +2260,7 @@ static off_t cdda_plugin_get_length (input_plugin_t *this_gen) { static uint32_t cdda_plugin_get_blocksize (input_plugin_t *this_gen) { - return CD_RAW_FRAME_SIZE; + return 0; } static const char* cdda_plugin_get_mrl (input_plugin_t *this_gen) { @@ -2383,7 +2301,7 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { int fd = -1; char *cdda_device; int err = -1; - + lprintf("cdda_plugin_open\n"); /* get the CD TOC */ @@ -2394,7 +2312,7 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { else cdda_device = class->cdda_device; -#ifndef WIN32 +#ifndef WIN32 if( strchr(cdda_device,':') ) { fd = network_connect(this->stream, cdda_device); if( fd != -1 ) { @@ -2412,7 +2330,7 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { return 0; } -#ifndef WIN32 +#ifndef WIN32 err = read_cdrom_toc(this->fd, toc); #else err = read_cdrom_toc(this, toc); @@ -2424,18 +2342,18 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { } - - if ( (err < 0) || (toc->first_track > (this->track + 1)) || + + if ( (err < 0) || (toc->first_track > (this->track + 1)) || (toc->last_track < (this->track + 1))) { cdda_close(this); - + free_cdrom_toc(toc); return 0; } /* set up the frame boundaries for this particular track */ - this->first_frame = this->current_frame = + this->first_frame = this->current_frame = toc->toc_entries[this->track].first_frame; if (this->track + 1 == toc->last_track) this->last_frame = toc->leadout_track.first_frame - 1; @@ -2446,8 +2364,8 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { this->cache_first = this->cache_last = -1; /* get the Musicbrainz CDIndex */ - _cdda_cdindex (this, toc); - + _cdda_cdindex (this, toc); + /* * CDDB */ @@ -2458,26 +2376,26 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { if(this->cddb.num_tracks) { int t; - this->cddb.track = (trackinfo_t *) xine_xmalloc(sizeof(trackinfo_t) * this->cddb.num_tracks); + this->cddb.track = (trackinfo_t *) calloc(this->cddb.num_tracks, sizeof(trackinfo_t)); for(t = 0; t < this->cddb.num_tracks; t++) { - int length = (toc->toc_entries[t].first_frame_minute * CD_SECONDS_PER_MINUTE + + int length = (toc->toc_entries[t].first_frame_minute * CD_SECONDS_PER_MINUTE + toc->toc_entries[t].first_frame_second); - - this->cddb.track[t].start = (length * CD_FRAMES_PER_SECOND + + + this->cddb.track[t].start = (length * CD_FRAMES_PER_SECOND + toc->toc_entries[t].first_frame_frame); this->cddb.track[t].title = NULL; } - + } - this->cddb.disc_length = (toc->leadout_track.first_frame_minute * CD_SECONDS_PER_MINUTE + + this->cddb.disc_length = (toc->leadout_track.first_frame_minute * CD_SECONDS_PER_MINUTE + toc->leadout_track.first_frame_second); this->cddb.disc_id = _cdda_get_cddb_id(this); if((this->cddb.have_cddb_info == 0) || (_cdda_is_cd_changed(this) == 1)) _cdda_cddb_retrieve(this); - + if(this->cddb.disc_title) { lprintf("Disc Title: %s\n", this->cddb.disc_title); @@ -2485,17 +2403,36 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { } if(this->cddb.track[this->track].title) { - lprintf("Track %d Title: %s\n", this->track+1, this->cddb.track[this->track].title); + /* Check for track 'titles' of the form <artist> / <title>. */ + char *pt; + pt = strstr(this->cddb.track[this->track].title, " / "); + if (pt != NULL) { + char *track_artist; + track_artist = strdup(this->cddb.track[this->track].title); + track_artist[pt - this->cddb.track[this->track].title] = 0; + lprintf("Track %d Artist: %s\n", this->track+1, track_artist); + + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_ARTIST, track_artist); + free(track_artist); + pt += 3; + } + else { + if(this->cddb.disc_artist) { + lprintf("Disc Artist: %s\n", this->cddb.disc_artist); - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->cddb.track[this->track].title); - } - - if(this->cddb.disc_artist) { - lprintf("Disc Artist: %s\n", this->cddb.disc_artist); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_ARTIST, this->cddb.disc_artist); + } + + pt = this->cddb.track[this->track].title; + } + lprintf("Track %d Title: %s\n", this->track+1, pt); - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_ARTIST, this->cddb.disc_artist); + char tracknum[4]; + snprintf(tracknum, 4, "%d", this->track+1); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TRACK_NUMBER, tracknum); + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, pt); } - + if(this->cddb.disc_category) { lprintf("Disc Category: %s\n", this->cddb.disc_category); @@ -2513,13 +2450,140 @@ static int cdda_plugin_open (input_plugin_t *this_gen ) { return 1; } -static char ** cdda_class_get_autoplay_list (input_class_t *this_gen, +static xine_mrl_t** cdda_class_get_dir(input_class_t *this_gen, + const char *filename, + int *num_files) { + cdda_input_class_t *this = (cdda_input_class_t *) this_gen; + cdda_input_plugin_t *ip; + cdrom_toc *toc; + char *base_mrl; + int len, frame; + const char * device; + int fd, i, err = -1; + int num_tracks; + + if (filename && *filename) { + device = filename; + if (strncasecmp(device,"cdda:/",6) == 0) { + device += 6; + while ('/' == *device) + device++; + device--; + } + } + else { + device = this->cdda_device; + } + lprintf("cdda_class_get_dir for >%s<\n", device); + + /* get the CD TOC */ + toc = init_cdrom_toc(); + + fd = -1; + + /* we create a new instance because getting a directory of a cd + * should not affect another cd that might be playing. */ + ip = (cdda_input_plugin_t *)xine_xmalloc(sizeof(cdda_input_plugin_t)); + ip->stream = NULL; + ip->fd = -1; + ip->net_fd = -1; + +#ifndef WIN32 + if( strchr(device,':') ) { + fd = network_connect(ip->stream, device); + if( fd != -1 ) { + err = network_read_cdrom_toc(ip->stream, fd, toc); + } + } +#endif + + if (fd == -1) { + if (cdda_open(ip, device, toc, &fd) == -1) { + lprintf("cdda_class_get_dir: opening >%s< failed %s\n", + device, strerror(errno)); + free(ip); + return NULL; + } + +#ifndef WIN32 + err = read_cdrom_toc(fd, toc); +#else + err = read_cdrom_toc(ip, toc); +#endif /* WIN32 */ + } + +#ifdef LOG + print_cdrom_toc(toc); +#endif + + cdda_close(ip); + + if ( err < 0 ) { + free(ip); + return NULL; + } + + num_tracks = toc->last_track - toc->first_track + 1; + + /* this could be done in read_cdrom_toc, but it seems other code doesn't use it */ + frame = toc->leadout_track.first_frame; + for ( i = num_tracks-1 ; i >= 0 ; i--) { + toc->toc_entries[i].total_frames = frame - toc->toc_entries[i].first_frame; + frame = toc->toc_entries[i].first_frame; + } + + if (toc->ignore_last_track) + num_tracks--; + + len = strlen(device) + 5; + base_mrl = xine_xmalloc(len+1); + sprintf(base_mrl, "cdda:%s", device); + + /* allocate space for the mrls's if needed. */ + if (num_tracks+1 > this->mrls_allocated_entries) { + this->mrls = realloc(this->mrls, (num_tracks+1) * sizeof(xine_mrl_t*)); + } + for (i = 0 ; i < num_tracks ; i++) { + if (i < this->mrls_allocated_entries) { + if (this->mrls[i]->origin) + free(this->mrls[i]->origin); + if (this->mrls[i]->mrl) + free(this->mrls[i]->mrl); + if (this->mrls[i]->link) { + free(this->mrls[i]->link); + this->mrls[i]->link = NULL; + } + } + else { + this->mrls[i] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[i]->link = NULL; + this->mrls_allocated_entries++; + } + this->mrls[i]->origin = strdup(base_mrl); + this->mrls[i]->mrl = xine_xmalloc(len+4); + sprintf( this->mrls[i]->mrl, "%s/%d", base_mrl, i+toc->first_track); + this->mrls[i]->type = mrl_cda | mrl_file_blockdev; + this->mrls[i]->size = toc->toc_entries[i].total_frames * CD_RAW_FRAME_SIZE; + } + /* Clean up */ + while(this->mrls_allocated_entries > num_tracks) { + MRL_ZERO(this->mrls[this->mrls_allocated_entries - 1]); + free(this->mrls[this->mrls_allocated_entries--]); + } + free_cdrom_toc(toc); + free(ip); + + this->mrls[num_tracks] = NULL; + *num_files = num_tracks; + return this->mrls; +} + +static char ** cdda_class_get_autoplay_list (input_class_t *this_gen, int *num_files) { cdda_input_class_t *this = (cdda_input_class_t *) this_gen; cdda_input_plugin_t *ip = this->ip; cdrom_toc *toc; - char trackmrl[20]; int fd, i, err = -1; int num_tracks; @@ -2528,8 +2592,8 @@ static char ** cdda_class_get_autoplay_list (input_class_t *this_gen, /* free old playlist */ for( i = 0; this->autoplaylist[i]; i++ ) { free( this->autoplaylist[i] ); - this->autoplaylist[i] = NULL; - } + this->autoplaylist[i] = NULL; + } /* get the CD TOC */ toc = init_cdrom_toc(); @@ -2541,7 +2605,7 @@ static char ** cdda_class_get_autoplay_list (input_class_t *this_gen, * device we are going to open; but it is possible that this function * gets called, before a plugin instance has been created; * let's create a dummy instance in such a condition */ - ip = (cdda_input_plugin_t *)xine_xmalloc(sizeof(cdda_input_plugin_t)); + ip = calloc(1, sizeof(cdda_input_plugin_t)); ip->stream = NULL; ip->fd = -1; ip->net_fd = -1; @@ -2575,20 +2639,18 @@ static char ** cdda_class_get_autoplay_list (input_class_t *this_gen, print_cdrom_toc(toc); #endif - cdda_close(ip); - + cdda_close(ip); + if ( err < 0 ) { if (ip != this->ip) free(ip); return NULL; } - + num_tracks = toc->last_track - toc->first_track; if (toc->ignore_last_track) num_tracks--; - for ( i = 0; i <= num_tracks; i++ ) { - sprintf(trackmrl,"cdda:/%d",i+toc->first_track); - this->autoplaylist[i] = strdup(trackmrl); - } + for ( i = 0; i <= num_tracks; i++ ) + asprintf(&this->autoplaylist[i],"cdda:/%d",i+toc->first_track); *num_files = toc->last_track - toc->first_track + 1; @@ -2642,20 +2704,20 @@ static input_plugin_t *cdda_class_get_instance (input_class_t *cls_gen, xine_str } else return NULL; - this = (cdda_input_plugin_t *) xine_xmalloc (sizeof (cdda_input_plugin_t)); - + this = calloc(1, sizeof (cdda_input_plugin_t)); + class->ip = this; this->stream = stream; this->mrl = strdup(mrl); this->cdda_device = cdda_device; - + /* CD tracks start from 1; internal data structure indexes from 0 */ this->track = track - 1; this->cddb.track = NULL; this->fd = -1; this->net_fd = -1; this->class = (input_class_t *) class; - + this->input_plugin.open = cdda_plugin_open; this->input_plugin.get_capabilities = cdda_plugin_get_capabilities; this->input_plugin.read = cdda_plugin_read; @@ -2668,24 +2730,24 @@ static input_plugin_t *cdda_class_get_instance (input_class_t *cls_gen, xine_str this->input_plugin.get_optional_data = cdda_plugin_get_optional_data; this->input_plugin.dispose = cdda_plugin_dispose; this->input_plugin.input_class = cls_gen; - + /* * Lookup config entries. */ - if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.use_cddb", - &enable_entry)) + if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.use_cddb", + &enable_entry)) enable_cddb_changed_cb(class, &enable_entry); - if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_server", - &server_entry)) + if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_server", + &server_entry)) server_changed_cb(class, &server_entry); - - if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_port", - &port_entry)) + + if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_port", + &port_entry)) port_changed_cb(class, &port_entry); - if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_cachedir", - &cachedir_entry)) + if(xine_config_lookup_entry(this->stream->xine, "media.audio_cd.cddb_cachedir", + &cachedir_entry)) cachedir_changed_cb(class, &cachedir_entry); class->cddb_error = cddb_error; @@ -2731,7 +2793,7 @@ static void *init_plugin (xine_t *xine, void *data) { cdda_input_class_t *this; config_values_t *config; - this = (cdda_input_class_t *) xine_xmalloc (sizeof (cdda_input_class_t)); + this = calloc(1, sizeof (cdda_input_class_t)); this->xine = xine; this->config = xine->config; @@ -2740,8 +2802,7 @@ static void *init_plugin (xine_t *xine, void *data) { this->input_class.get_instance = cdda_class_get_instance; this->input_class.get_identifier = cdda_class_get_identifier; this->input_class.get_description = cdda_class_get_description; - /* this->input_class.get_dir = cdda_class_get_dir; */ - this->input_class.get_dir = NULL; + this->input_class.get_dir = cdda_class_get_dir; this->input_class.get_autoplay_list = cdda_class_get_autoplay_list; this->input_class.dispose = cdda_class_dispose; this->input_class.eject_media = cdda_class_eject_media; @@ -2749,15 +2810,15 @@ static void *init_plugin (xine_t *xine, void *data) { this->mrls = NULL; this->mrls_allocated_entries = 0; this->ip = NULL; - - this->cdda_device = config->register_filename(config, "media.audio_cd.device", + + this->cdda_device = config->register_filename(config, "media.audio_cd.device", DEFAULT_CDDA_DEVICE, XINE_CONFIG_STRING_IS_DEVICE_NAME, _("device used for CD audio"), _("The path to the device, usually a " "CD or DVD drive, which you intend to use " "for playing audio CDs."), 10, cdda_device_cb, (void *) this); - + config->register_bool(config, "media.audio_cd.use_cddb", 1, _("query CDDB"), _("Enables CDDB queries, which will give you " "convenient title and track names for your audio CDs.\n" @@ -2765,7 +2826,7 @@ static void *init_plugin (xine_t *xine, void *data) { "is retrieved from an internet server which might collect a profile " "of your listening habits."), 10, enable_cddb_changed_cb, (void *) this); - + config->register_string(config, "media.audio_cd.cddb_server", CDDB_SERVER, _("CDDB server name"), _("The CDDB server used to retrieve the " "title and track information from.\nThis setting is security critical, " @@ -2773,18 +2834,18 @@ static void *init_plugin (xine_t *xine, void *data) { "and could answer the queries with malicious replies. Be sure to enter " "a server you can trust."), XINE_CONFIG_SECURITY, server_changed_cb, (void *) this); - + config->register_num(config, "media.audio_cd.cddb_port", CDDB_PORT, _("CDDB server port"), _("The server port used to retrieve the " "title and track information from."), XINE_CONFIG_SECURITY, port_changed_cb, (void *) this); - - config->register_filename(config, "media.audio_cd.cddb_cachedir", + + config->register_filename(config, "media.audio_cd.cddb_cachedir", (_cdda_cddb_get_default_location()), XINE_CONFIG_STRING_IS_DIRECTORY_NAME, _("CDDB cache directory"), _("The replies from the CDDB server will be " "cached in this directory.\nThis setting is security critical, because files " "with uncontrollable names will be created in this directory. Be sure to use " - "a dedicated directory not used for anything but CDDB caching."), XINE_CONFIG_SECURITY, + "a dedicated directory not used for anything but CDDB caching."), XINE_CONFIG_SECURITY, cachedir_changed_cb, (void *) this); #ifdef CDROM_SELECT_SPEED diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c index 795b843c5..e6abfd3d5 100644 --- a/src/input/input_dvb.c +++ b/src/input/input_dvb.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2005 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -30,7 +30,7 @@ * 01-Feb-2005 Pekka Jääskeläinen <poj@iki.fi> * * - This history log started. - * - Disabled the automatic EPG updater thread until EPG demuxer + * - Disabled the automatic EPG updater thread until EPG demuxer * is done (it caused pausing of video stream), now EPG is * updated only on demand when the EPG OSD is displayed and * no data is in cache. @@ -39,10 +39,10 @@ * - Now tuning to an erroneus channel shouldn't hang but stop * the playback and output a log describing the error. * - Style cleanups here and there. - * + * * 06-Apr-2006 Jack Steven Kelliher * - Add ATSC support - * + * * TODO/Wishlist: (not in any order) * - Parse all Administrative PIDs - NIT,SDT,CAT etc * - As per James' suggestion, we need a way for the demuxer @@ -52,7 +52,7 @@ * Alevtd can read it. * - Allow the user to view one set of PIDs (channel) while * recording another on the same transponder - this will require either remuxing or - * perhaps bypassing the TS demuxer completely - we could easily have access to the + * perhaps bypassing the TS demuxer completely - we could easily have access to the * individual audio/video streams via seperate read calls, so send them to the decoders * and save the TS output to disk instead of passing it to the demuxer. * This also gives us full control over the streams being played..hmm..control... @@ -60,20 +60,20 @@ * - Allow the user to find and tune new stations from within xine, and * do away with the need for dvbscan & channels.conf file. * - Enable use of Conditional Access devices for scrambled content. - * - if multiple cards are available, optionally use these to record/gather si info, + * - if multiple cards are available, optionally use these to record/gather si info, * and leave primary card for viewing. * - allow for handing off of EPG data to specialised frontends, instead of displaying via * OSD - this will allow for filtering/searching of epg data - useful for automatic recording :) */ -/* pthread.h must be included first so rest of the headers are imported - thread safely (on some systems). */ -#include <pthread.h> - #ifdef HAVE_CONFIG_H #include "config.h" #endif +/* pthread.h must be included first so rest of the headers are imported + thread safely (on some systems). */ +#include <pthread.h> + #include <assert.h> #include <stdio.h> #include <stdlib.h> @@ -117,7 +117,7 @@ #define DVB_NOPID 0xffff -/* define stream types +/* define stream types * administrative/system PIDs first */ #define INTERNAL_FILTER 0 #define PATFILTER 1 @@ -190,7 +190,7 @@ #define EPG_PIXELS_BETWEEN_TEXT_ROWS 2 #define EPG_PIXELS_BETWEEN_PROGRAM_ENTRIES 2 -/* How many pixels the background of the OSD is bigger than the text area? +/* How many pixels the background of the OSD is bigger than the text area? The margin is for each side of the background box. */ #define EPG_BACKGROUND_MARGIN 5 @@ -201,10 +201,10 @@ /* How many seconds an EPG entry with the running flag on can be "late" according to the system time before discarding it as an old program? - - This margin is needed because in channel list OSD some EPG entries of + + This margin is needed because in channel list OSD some EPG entries of some channels may be updated a very long ago (if user has watched another - channel in different mux) so we have to resort to system clock for + channel in different mux) so we have to resort to system clock for figuring out the current program. */ #define MAX_EPG_ENTRY_LATENESS 5*60.0 @@ -226,13 +226,13 @@ typedef struct { int fd_subfilter[MAX_SUBTITLES]; struct dvb_frontend_info feinfo; - + int adapter_num; char frontend_device[100]; - char dvr_device[100]; + char dvr_device[100]; char demux_device[100]; - + struct dmx_pes_filter_params pesFilterParams[MAX_FILTERS]; struct dmx_pes_filter_params subFilterParams[MAX_SUBTITLES]; struct dmx_sct_filter_params sectFilterParams[MAX_FILTERS]; @@ -244,16 +244,16 @@ typedef struct { typedef struct { /* Program's name. */ - char *progname; + char *progname; /* Textual description of the program. */ char *description; /* The content type string. */ - char *content; + char *content; /* Age recommendation. 0 if not available. */ - int rating; + int rating; time_t starttime; @@ -262,7 +262,7 @@ typedef struct { char duration_minutes; /* Is this program running currently according to EPG data? */ - char running; + char running; } epg_entry_t; @@ -286,11 +286,12 @@ typedef struct { xine_t *xine; - char *mrls[5]; + char *mrls[6]; - int numchannels; + int numchannels; char *autoplaylist[MAX_AUTOCHANNELS]; + char *default_channels_conf_filename; } dvb_input_class_t; typedef struct { @@ -320,22 +321,25 @@ typedef struct { osd_object_t *rec_osd; osd_object_t *name_osd; osd_object_t *paused_osd; - osd_object_t *proginfo_osd; + osd_object_t *proginfo_osd; osd_object_t *channel_osd; osd_object_t *background; - + xine_event_queue_t *event_queue; /* CRC table for PAT rebuilding */ unsigned long crc32_table[256]; - + /* scratch buffer for forward seeking */ char seek_buf[BUFSIZE]; + /* Is the GUI enabled at all? */ + int dvb_gui_enabled; + /* simple vcr-like functionality */ int record_fd; int record_paused; /* centre cutout zoom */ - int zoom_ok; + int zoom_ok; /* Is EPG displaying? */ int epg_displaying; @@ -344,8 +348,8 @@ typedef struct { pthread_t epg_updater_thread; /* buffer for EIT data */ - /*char *eitbuffer;*/ - int num_streams_in_this_ts; + /*char *eitbuffer;*/ + int num_streams_in_this_ts; /* number of timedout reads in plugin_read */ int read_failcount; #ifdef DVB_NO_BUFFERING @@ -369,6 +373,7 @@ static const Param bw_list [] = { { "BANDWIDTH_6_MHZ", BANDWIDTH_6_MHZ }, { "BANDWIDTH_7_MHZ", BANDWIDTH_7_MHZ }, { "BANDWIDTH_8_MHZ", BANDWIDTH_8_MHZ }, + { "BANDWIDTH_AUTO", BANDWIDTH_AUTO }, { NULL, 0 } }; @@ -391,6 +396,7 @@ static const Param guard_list [] = { {"GUARD_INTERVAL_1_32", GUARD_INTERVAL_1_32}, {"GUARD_INTERVAL_1_4", GUARD_INTERVAL_1_4}, {"GUARD_INTERVAL_1_8", GUARD_INTERVAL_1_8}, + {"GUARD_INTERVAL_AUTO", GUARD_INTERVAL_AUTO}, { NULL, 0 } }; @@ -399,6 +405,7 @@ static const Param hierarchy_list [] = { { "HIERARCHY_2", HIERARCHY_2 }, { "HIERARCHY_4", HIERARCHY_4 }, { "HIERARCHY_NONE", HIERARCHY_NONE }, + { "HIERARCHY_AUTO", HIERARCHY_AUTO }, { NULL, 0 } }; @@ -417,12 +424,14 @@ static const Param qam_list [] = { { "QAM_256", QAM_256 }, { "QAM_32", QAM_32 }, { "QAM_64", QAM_64 }, + { "QAM_AUTO", QAM_AUTO }, { NULL, 0 } }; static const Param transmissionmode_list [] = { { "TRANSMISSION_MODE_2K", TRANSMISSION_MODE_2K }, { "TRANSMISSION_MODE_8K", TRANSMISSION_MODE_8K }, + { "TRANSMISSION_MODE_AUTO", TRANSMISSION_MODE_AUTO }, { NULL, 0 } }; @@ -455,7 +464,7 @@ static void ts_build_crc32_table(dvb_input_plugin_t *this) { } } -static uint32_t ts_compute_crc32(dvb_input_plugin_t *this, uint8_t *data, +static uint32_t ts_compute_crc32(dvb_input_plugin_t *this, uint8_t *data, uint32_t length, uint32_t crc32) { uint32_t i; @@ -479,7 +488,7 @@ static unsigned int getbits(unsigned char *buffer, unsigned int bitpos, unsigned } -static int find_descriptor(uint8_t tag, const unsigned char *buf, int descriptors_loop_len, +static int find_descriptor(uint8_t tag, const unsigned char *buf, int descriptors_loop_len, const unsigned char **desc, int *desc_len) { @@ -513,11 +522,11 @@ time_t dvb_mjdtime (char *buf) int i; unsigned int year, month, day, hour, min, sec; unsigned long int mjd; - struct tm *tma = xine_xmalloc(sizeof(struct tm)); + struct tm *tma = calloc(1, sizeof(struct tm)); time_t t; _x_assert(tma != NULL); - + mjd = (unsigned int)(buf[0] & 0xff) << 8; mjd +=(unsigned int)(buf[1] & 0xff); hour =(unsigned char)bcdtoint(buf[2] & 0xff); @@ -526,14 +535,14 @@ time_t dvb_mjdtime (char *buf) year =(unsigned long)((mjd - 15078.2)/365.25); month=(unsigned long)((mjd - 14956.1 - (unsigned long)(year * 365.25))/30.6001); day = mjd - 14956 - (unsigned long)(year * 365.25) - (unsigned long)(month * 30.6001); - + if (month == 14 || month == 15) i = 1; else i = 0; year += i; month = month - 1 - i * 12; - + tma->tm_sec=sec; tma->tm_min=min; tma->tm_hour=hour; @@ -543,7 +552,7 @@ time_t dvb_mjdtime (char *buf) t = timegm(tma); - + free(tma); return t; } @@ -565,39 +574,38 @@ static void tuner_dispose(tuner_t * this) for (x = 0; x < MAX_SUBTITLES; x++) if (this->fd_subfilter[x] >= 0) close(this->fd_subfilter[x]); - + if(this) free(this); } -static tuner_t *tuner_init(xine_t * xine, int adapter) +static tuner_t *XINE_MALLOC tuner_init(xine_t * xine, int adapter) { tuner_t *this; int x; int test_video; - char *video_device=xine_xmalloc(200); + char *video_device=malloc(100); _x_assert(video_device != NULL); - - this = (tuner_t *) xine_xmalloc(sizeof(tuner_t)); + + this = calloc(1, sizeof(tuner_t)); _x_assert(this != NULL); xprintf(this->xine, XINE_VERBOSITY_DEBUG, "tuner_init adapter=%d\n", adapter); this->fd_frontend = -1; - for (x = 0; x < MAX_FILTERS; x++) - this->fd_pidfilter[x] = 0; + memset(this->fd_pidfilter, 0, sizeof(this->fd_pidfilter)); this->xine = xine; this->adapter_num = adapter; - + snprintf(this->frontend_device,100,"/dev/dvb/adapter%i/frontend0",this->adapter_num); snprintf(this->demux_device,100,"/dev/dvb/adapter%i/demux0",this->adapter_num); snprintf(this->dvr_device,100,"/dev/dvb/adapter%i/dvr0",this->adapter_num); snprintf(video_device,100,"/dev/dvb/adapter%i/video0",this->adapter_num); - + if ((this->fd_frontend = open(this->frontend_device, O_RDWR)) < 0) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "FRONTEND DEVICE: %s\n", strerror(errno)); tuner_dispose(this); @@ -633,7 +641,7 @@ static tuner_t *tuner_init(xine_t * xine, int adapter) xprintf(this->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't set INTERNAL to nonblock: %s\n",strerror(errno)); /* and the frontend */ fcntl(this->fd_frontend, F_SETFL, O_NONBLOCK); - + xprintf(this->xine,XINE_VERBOSITY_DEBUG,"input_dvb: Frontend is <%s> ",this->feinfo.name); if(this->feinfo.type==FE_QPSK) xprintf(this->xine,XINE_VERBOSITY_DEBUG,"SAT Card\n"); if(this->feinfo.type==FE_QAM) xprintf(this->xine,XINE_VERBOSITY_DEBUG,"CAB Card\n"); @@ -648,7 +656,7 @@ static tuner_t *tuner_init(xine_t * xine, int adapter) } free(video_device); - + return this; } @@ -660,7 +668,7 @@ static int dvb_set_pidfilter(dvb_input_plugin_t * this, int filter, ushort pid, if(this->channels[this->channel].pid [filter] !=DVB_NOPID) { ioctl(tuner->fd_pidfilter[filter], DMX_STOP); } - + this->channels[this->channel].pid [filter] = pid; tuner->pesFilterParams[filter].pid = pid; tuner->pesFilterParams[filter].input = DMX_IN_FRONTEND; @@ -683,7 +691,7 @@ static int dvb_set_sectfilter(dvb_input_plugin_t * this, int filter, ushort pid, if(this->channels[this->channel].pid [filter] !=DVB_NOPID) { ioctl(tuner->fd_pidfilter[filter], DMX_STOP); } - + this->channels[this->channel].pid [filter] = pid; tuner->sectFilterParams[filter].pid = pid; memset(&tuner->sectFilterParams[filter].filter.filter,0,DMX_FILTER_SIZE); @@ -717,14 +725,14 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f <bw>:<fec_hp>:<fec_lp>:<qam>: <transmissionm>:<guardlist>:<hierarchinfo>:<vpid>:<apid> (DVBA) ATSC: <channel name>:<frequency>:<qam>:<vpid>:<apid> - + <channel name> = any string not containing ':' <frequency> = unsigned long <polarisation> = 'v' or 'h' <sat_no> = unsigned long, usually 0 :D <sym_rate> = symbol rate in MSyms/sec - - + + <inversion> = INVERSION_ON | INVERSION_OFF | INVERSION_AUTO <fec> = FEC_1_2, FEC_2_3, FEC_3_4 .... FEC_AUTO ... FEC_NONE <qam> = QPSK, QAM_128, QAM_16, ATSC ... @@ -741,7 +749,7 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f char *field, *tmp; tmp = str; - + /* find the channel name */ if(!(field = strsep(&tmp,":")))return -1; channel->name = strdup(field); @@ -762,8 +770,8 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f channel->tone = 0; } channel->front_param.inversion = INVERSION_AUTO; - - /* find out the polarisation */ + + /* find out the polarisation */ if(!(field = strsep(&tmp, ":")))return -1; channel->pol = (field[0] == 'h' ? 0 : 1); @@ -779,7 +787,7 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f break; case FE_QAM: channel->front_param.frequency = freq; - + /* find out the inversion */ if(!(field = strsep(&tmp, ":")))return -1; channel->front_param.inversion = find_param(inversion_list, field); @@ -797,10 +805,10 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f channel->front_param.u.qam.modulation = find_param(qam_list, field); break; case FE_OFDM: - /* DVB-T frequency is in kHz - workaround broken channels.confs */ - if (freq < 1000000) - freq*=1000; - + /* DVB-T frequency is in kHz - workaround broken channels.confs */ + if (freq < 1000000) + freq*=1000; + channel->front_param.frequency = freq; /* find out the inversion */ @@ -836,7 +844,7 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f break; case FE_ATSC: channel->front_param.frequency = freq; - + /* find out the qam */ if(!(field = strsep(&tmp, ":")))return -1; channel->front_param.u.vsb.modulation = find_param(atsc_list, field); @@ -862,9 +870,9 @@ static int extract_channel_from_string_internal(channel_t * channel,char * str,f /* some channel.conf files are generated with the service ID 1 to the right this needs investigation */ if ((field = strsep(&tmp, ":"))) - if(strtoul(field,NULL,0)>0) + if(strtoul(field,NULL,0)>0) channel->service_id = strtoul(field, NULL, 0); - + return 0; } @@ -881,14 +889,15 @@ static channel_t *load_channels(xine_t *xine, xine_stream_t *stream, int *num_ch FILE *f; char str[BUFSIZE]; - char filename[BUFSIZE]; channel_t *channels = NULL; int num_channels = 0; int num_alloc = 0; - int i; struct stat st; - - snprintf(filename, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir()); + xine_cfg_entry_t channels_conf; + char *filename; + + xine_config_lookup_entry(xine, "media.dvb.channels_conf", &channels_conf); + filename = channels_conf.str_value; f = fopen(filename, "r"); if (!f) { @@ -904,25 +913,25 @@ static channel_t *load_channels(xine_t *xine, xine_stream_t *stream, int *num_ch } /* - * load channel list + * load channel list */ while ( fgets (str, BUFSIZE, f)) { channel_t channel = {0}; - /* lose trailing spaces & control characters */ - i = strlen (str); + /* lose trailing spaces & control characters */ + size_t i = strlen (str); while (i && str[i - 1] <= ' ') --i; if (i == 0) continue; str[i] = 0; - if (extract_channel_from_string(&channel,str,fe_type) < 0) + if (extract_channel_from_string(&channel,str,fe_type) < 0) continue; if (num_channels >= num_alloc) { - channel_t *new_channels = xine_xmalloc((num_alloc += 32) * sizeof (channel_t)); + channel_t *new_channels = calloc((num_alloc += 32), sizeof (channel_t)); _x_assert(new_channels != NULL); memcpy(new_channels, channels, num_channels * sizeof (channel_t)); free(channels); @@ -933,8 +942,7 @@ static channel_t *load_channels(xine_t *xine, xine_stream_t *stream, int *num_ch /* Initially there's no EPG data in the EPG structs. */ channels[num_channels].epg_count = 0; - for (i = 0; i < MAX_EPG_ENTRIES_PER_CHANNEL; ++i) - channels[num_channels].epg[i] = NULL; + memset(channels[num_channels].epg, 0, sizeof(channels[num_channels].epg)); num_channels++; } @@ -943,14 +951,14 @@ static channel_t *load_channels(xine_t *xine, xine_stream_t *stream, int *num_ch /* free any trailing unused entries */ channels = realloc (channels, num_channels * sizeof (channel_t)); - if(num_channels > 0) + if(num_channels > 0) xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: found %d channels...\n", num_channels); else { xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: no channels found in the file: giving up.\n"); free(channels); return NULL; } - + *num_ch = num_channels; return channels; } @@ -1044,7 +1052,7 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters } xprintf(this->xine, XINE_VERBOSITY_DEBUG, "input_dvb: tuner_tune_it - waiting for lock...\n" ); - + do { status = 0; if (ioctl(this->fd_frontend, FE_READ_STATUS, &status) < 0) { @@ -1071,25 +1079,25 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters usleep(10000); xprintf(this->xine, XINE_VERBOSITY_DEBUG, "Trying to get lock..."); } while (!(status & FE_TIMEDOUT)); - - /* inform the user of frontend status */ + + /* inform the user of frontend status */ xprintf(this->xine,XINE_VERBOSITY_LOG,"input_dvb: Tuner status: "); /* if (ioctl(this->fd_frontend, FE_READ_STATUS, &status) >= 0){ */ - if (status & FE_HAS_SIGNAL) + if (status & FE_HAS_SIGNAL) xprintf(this->xine,XINE_VERBOSITY_LOG," FE_HAS_SIGNAL"); - if (status & FE_TIMEDOUT) + if (status & FE_TIMEDOUT) xprintf(this->xine,XINE_VERBOSITY_LOG," FE_TIMEDOUT"); - if (status & FE_HAS_LOCK) + if (status & FE_HAS_LOCK) xprintf(this->xine,XINE_VERBOSITY_LOG," FE_HAS_LOCK"); - if (status & FE_HAS_CARRIER) + if (status & FE_HAS_CARRIER) xprintf(this->xine,XINE_VERBOSITY_LOG," FE_HAS_CARRIER"); - if (status & FE_HAS_VITERBI) + if (status & FE_HAS_VITERBI) xprintf(this->xine,XINE_VERBOSITY_LOG," FE_HAS_VITERBI"); - if (status & FE_HAS_SYNC) + if (status & FE_HAS_SYNC) xprintf(this->xine,XINE_VERBOSITY_LOG," FE_HAS_SYNC"); /* } */ xprintf(this->xine,XINE_VERBOSITY_LOG,"\n"); - + strength=0; if(ioctl(this->fd_frontend,FE_READ_BER,&strength) >= 0) xprintf(this->xine,XINE_VERBOSITY_LOG,"input_dvb: Bit error rate: %i\n",strength); @@ -1101,9 +1109,9 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters strength=0; if(ioctl(this->fd_frontend,FE_READ_SNR,&strength) >= 0) xprintf(this->xine,XINE_VERBOSITY_LOG,"input_dvb: Signal/Noise Ratio: %u\n",strength); - + if (status & FE_HAS_LOCK && !(status & FE_TIMEDOUT)) { - xprintf(this->xine,XINE_VERBOSITY_LOG,"input_dvb: Lock achieved at %lu Hz\n",(unsigned long)front_param->frequency); + xprintf(this->xine,XINE_VERBOSITY_LOG,"input_dvb: Lock achieved at %lu Hz\n",(unsigned long)front_param->frequency); return 1; } else { xprintf(this->xine,XINE_VERBOSITY_LOG,"input_dvb: Unable to achieve lock at %lu Hz\n",(unsigned long)front_param->frequency); @@ -1112,13 +1120,13 @@ static int tuner_tune_it (tuner_t *this, struct dvb_frontend_parameters } -/* Parse the PMT, and add filters for all stream types associated with - * the 'channel'. We leave it to the demuxer to sort out which PIDs to +/* Parse the PMT, and add filters for all stream types associated with + * the 'channel'. We leave it to the demuxer to sort out which PIDs to * use. to simplify things slightly, (and because the demuxer can't handle it) * allow only one of each media type */ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int section_length) { - + int program_info_len; int pcr_pid; int has_video=0; @@ -1144,29 +1152,33 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se switch (buf[0]) { case 0x01: case 0x02: + case 0x10: + case 0x1b: if(!has_video) { xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"input_dvb: Adding VIDEO : PID 0x%04x\n", elementary_pid); dvb_set_pidfilter(this, VIDFILTER, elementary_pid, DMX_PES_VIDEO, DMX_OUT_TS_TAP); has_video=1; - } + } break; - + case 0x03: case 0x04: + case 0x0f: + case 0x11: if(!has_audio) { xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"input_dvb: Adding AUDIO : PID 0x%04x\n", elementary_pid); dvb_set_pidfilter(this, AUDFILTER, elementary_pid, DMX_PES_AUDIO, DMX_OUT_TS_TAP); has_audio=1; } break; - + case 0x06: if (find_descriptor(0x56, buf + 5, descriptor_len, NULL, NULL)) { if(!has_text) { xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"input_dvb: Adding TELETEXT : PID 0x%04x\n", elementary_pid); dvb_set_pidfilter(this,TXTFILTER, elementary_pid, DMX_PES_OTHER,DMX_OUT_TS_TAP); has_text=1; - } + } break; } else if (find_descriptor (0x59, buf + 5, descriptor_len, NULL, NULL)) { /* Note: The subtitling descriptor can also signal @@ -1187,7 +1199,7 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se this->tuner->subFilterParams[has_subs].flags = DMX_IMMEDIATE_START; if (ioctl(this->tuner->fd_subfilter[has_subs], DMX_SET_PES_FILTER, &this->tuner->subFilterParams[has_subs]) < 0) { - xprintf(this->tuner->xine, XINE_VERBOSITY_DEBUG, "input_dvb: set_pid: %s\n", strerror(errno)); + xprintf(this->tuner->xine, XINE_VERBOSITY_DEBUG, "input_dvb: set_pid: %s\n", strerror(errno)); break; } has_subs++; @@ -1195,7 +1207,7 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se break; } else if (find_descriptor (0x6a, buf + 5, descriptor_len, NULL, NULL)) { if(!has_ac3) { - dvb_set_pidfilter(this, AC3FILTER, elementary_pid, DMX_PES_OTHER,DMX_OUT_TS_TAP); + dvb_set_pidfilter(this, AC3FILTER, elementary_pid, DMX_PES_OTHER,DMX_OUT_TS_TAP); xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"input_dvb: Adding AC3 : PID 0x%04x\n", elementary_pid); has_ac3=1; } @@ -1203,7 +1215,7 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se } break; case 0x81: /* AC3 audio */ - fprintf(stderr, " pid type 0x%x, has audio %d\n",buf[0],has_audio); + fprintf(stderr, " pid type 0x%x, has audio %d\n",buf[0],has_audio); if(!has_audio) { xprintf(this->stream->xine,XINE_VERBOSITY_LOG,"input_dvb: Adding AUDIO : PID 0x%04x\n", elementary_pid); dvb_set_pidfilter(this, AUDFILTER, elementary_pid, DMX_PES_AUDIO, DMX_OUT_TS_TAP); @@ -1211,7 +1223,7 @@ static void parse_pmt(dvb_input_plugin_t *this, const unsigned char *buf, int se } break; - }; + }; buf += descriptor_len + 5; section_length -= descriptor_len + 5; @@ -1222,14 +1234,14 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { char *tmpbuffer; char *bufptr; - int service_id; + int service_id; int result; - int section_len; - int x; + int section_len; + int x; struct pollfd pfd; - + tuner_t *tuner = this->tuner; - tmpbuffer = xine_xmalloc (8192); + tmpbuffer = calloc(1, 8192); _x_assert(tmpbuffer != NULL); @@ -1241,8 +1253,8 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: Setting up Internal PAT filter\n"); xine_usec_sleep(500000); - - /* first - the PAT. retrieve the entire section...*/ + + /* first - the PAT. retrieve the entire section...*/ dvb_set_sectfilter(this, INTERNAL_FILTER, 0, DMX_PES_OTHER, 0, 0xff); /* wait for up to 15 seconds */ @@ -1255,13 +1267,13 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { return; } result = read (tuner->fd_pidfilter[INTERNAL_FILTER], tmpbuffer, 3); - + if(result!=3) xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: error reading PAT table - no data!\n"); section_len = getbits(tmpbuffer,12,12); result = read (tuner->fd_pidfilter[INTERNAL_FILTER], tmpbuffer+5,section_len); - + if(result!=section_len) xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: error reading in the PAT table\n"); @@ -1269,7 +1281,7 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { bufptr+=10; this->num_streams_in_this_ts=0; - section_len-=5; + section_len-=5; while(section_len>4){ service_id = getbits (bufptr,0,16); @@ -1281,7 +1293,7 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { section_len-=4; bufptr+=4; if(service_id>0) /* ignore NIT table for now */ - this->num_streams_in_this_ts++; + this->num_streams_in_this_ts++; } bufptr = tmpbuffer; @@ -1306,7 +1318,7 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { ioctl(tuner->fd_pidfilter[INTERNAL_FILTER], DMX_STOP); parse_pmt(this,tmpbuffer+8,section_len); - + /* dvb_set_pidfilter(this, TSDTFILTER, 0x02,DMX_PES_OTHER,DMX_OUT_TS_TAP); dvb_set_pidfilter(this, RSTFILTER, 0x13,DMX_PES_OTHER,DMX_OUT_TS_TAP); @@ -1319,8 +1331,8 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { /* we use the section filter for EIT because we are guarenteed a complete section */ if(ioctl(tuner->fd_pidfilter[EITFILTER],DMX_SET_BUFFER_SIZE,8192*this->num_streams_in_this_ts)<0) - xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't increase buffer size for EIT: %s \n",strerror(errno)); - dvb_set_sectfilter(this, EITFILTER, 0x12,DMX_PES_OTHER,0x4e, 0xff); + xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: couldn't increase buffer size for EIT: %s \n",strerror(errno)); + dvb_set_sectfilter(this, EITFILTER, 0x12,DMX_PES_OTHER,0x4e, 0xff); xprintf(this->stream->xine,XINE_VERBOSITY_DEBUG,"input_dvb: Setup of PID filters complete\n"); @@ -1332,7 +1344,7 @@ static void dvb_parse_si(dvb_input_plugin_t *this) { static int channel_index(dvb_input_plugin_t* this, unsigned int service_id) { unsigned int n; for (n=0; n < this->num_channels; n++) - if (this->channels[n].service_id == service_id) + if (this->channels[n].service_id == service_id) return n; return -1; @@ -1347,7 +1359,7 @@ static int compare_epg_by_starttime(const void* a, const void* b) { return -1; } else if ((*epg_a)->starttime > (*epg_b)->starttime) { return 1; - } + } return 0; } @@ -1370,7 +1382,7 @@ static void pthread_sleep(int seconds) { struct timespec timeout; /* Create a dummy mutex which doesn't unlock for sure while waiting. */ - pthread_mutex_init(&dummy_mutex, NULL); + pthread_mutex_init(&dummy_mutex, NULL); pthread_mutex_lock(&dummy_mutex); /* Create a dummy condition variable. */ @@ -1410,7 +1422,7 @@ static void* epg_data_updater(void *t) { } #endif -/* This function parses the EIT table and saves the data used in +/* This function parses the EIT table and saves the data used in EPG OSD of all channels found in the currently tuned stream. */ static void load_epg_data(dvb_input_plugin_t *this) { @@ -1419,7 +1431,7 @@ static void load_epg_data(dvb_input_plugin_t *this) int descriptor_id; int section_len = 0; unsigned int service_id=-1; - int n; + int n; char *eit = NULL; char *foo = NULL; char *seen_channels = NULL; @@ -1434,21 +1446,18 @@ static void load_epg_data(dvb_input_plugin_t *this) pthread_mutex_lock(&this->channel_change_mutex); /* seen_channels array is used to store information of channels that were - already "found" in the stream. This information is used to initialize the - channel's EPG structs when the EPG information for the channel is seen in + already "found" in the stream. This information is used to initialize the + channel's EPG structs when the EPG information for the channel is seen in the stream the first time. */ - seen_channels = xine_xmalloc(this->num_channels*sizeof(char)); + seen_channels = calloc(this->num_channels, sizeof(char)); _x_assert(seen_channels != NULL); - for (i = 0; i < this->num_channels; i++) { - seen_channels[i] = 0; - } - foo = xine_xmalloc(8192); + foo = calloc(1, 8192); _x_assert(foo != NULL); fd.fd = this->tuner->fd_pidfilter[EITFILTER]; fd.events = POLLPRI; - + for (loops = 0; loops <= this->num_streams_in_this_ts*2; loops++) { eit = foo; @@ -1457,7 +1466,7 @@ static void load_epg_data(dvb_input_plugin_t *this) pthread_mutex_unlock(&this->channel_change_mutex); free(seen_channels); free(foo); - return; + return; } n = read(this->tuner->fd_pidfilter[EITFILTER], eit, 3); table_id = getbits(eit, 0, 8); @@ -1470,8 +1479,8 @@ static void load_epg_data(dvb_input_plugin_t *this) xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,"input_dvb: load_epg_data(): unknown service_id: %d!\n", service_id); continue; } - - + + if (section_len > 15) { current_channel = &this->channels[current_channel_index]; @@ -1489,23 +1498,23 @@ static void load_epg_data(dvb_input_plugin_t *this) continue; } - /* Initialize the EPG struct if there's not one we can reuse. + /* Initialize the EPG struct if there's not one we can reuse. Allocate space for the strings. */ if (current_channel->epg[current_channel->epg_count] == NULL) { current_channel->epg[current_channel->epg_count] = - xine_xmalloc(sizeof(epg_entry_t)); + calloc(1, sizeof(epg_entry_t)); _x_assert(current_channel->epg[current_channel->epg_count] != NULL); - current_channel->epg[current_channel->epg_count]->progname = - xine_xmalloc((MAX_EPG_PROGRAM_NAME_LENGTH + 1) * sizeof(char)); + current_channel->epg[current_channel->epg_count]->progname = + malloc(MAX_EPG_PROGRAM_NAME_LENGTH + 1); _x_assert(current_channel->epg[current_channel->epg_count]->progname != NULL); current_channel->epg[current_channel->epg_count]->description = - xine_xmalloc((MAX_EPG_PROGRAM_DESCRIPTION_LENGTH + 1) * sizeof(char)); + malloc(MAX_EPG_PROGRAM_DESCRIPTION_LENGTH + 1); _x_assert(current_channel->epg[current_channel->epg_count]->description != NULL); - current_channel->epg[current_channel->epg_count]->content = - xine_xmalloc((MAX_EPG_CONTENT_TYPE_LENGTH + 1) * sizeof(char)); + current_channel->epg[current_channel->epg_count]->content = + malloc(MAX_EPG_CONTENT_TYPE_LENGTH + 1); _x_assert(current_channel->epg[current_channel->epg_count]->content != NULL); current_channel->epg[current_channel->epg_count]->running = 0; @@ -1519,12 +1528,12 @@ static void load_epg_data(dvb_input_plugin_t *this) 1 not running 2 starts in a few seconds 3 pausing - 4 running + 4 running */ if (getbits(foo,192,3) == 4){ - current_epg->running = 1; + current_epg->running = 1; } else { - current_epg->running = 0; + current_epg->running = 0; } @@ -1537,7 +1546,7 @@ static void load_epg_data(dvb_input_plugin_t *this) current_epg->duration_minutes = (char)bcdtoint(eit[22] & 0xff); descriptor_id = eit[26]; - eit += 27; + eit += 27; section_len -= 27; /* run the descriptor loop for the length of section_len */ while (section_len > 1) @@ -1550,23 +1559,23 @@ static void load_epg_data(dvb_input_plugin_t *this) desc_len = getbits(eit, 0, 8); - /* Let's get the EPG data only in the wanted language. */ + /* Let's get the EPG data only in the wanted language. */ if (xine_config_lookup_entry( - this->stream->xine, + this->stream->xine, "media.dvd.language", &language) && - language.str_value && strlen(language.str_value) >= 2 && + language.str_value && strlen(language.str_value) >= 2 && strncasecmp(language.str_value, &eit[1], 2)) { - + #ifdef DEBUG_EPG printf("input_dvb: EPG Skipping language: %C%C%C\n", - eit[1],eit[2],eit[3]); - printf("input_dvb: EPG language.str_value: %s\n", + eit[1],eit[2],eit[3]); + printf("input_dvb: EPG language.str_value: %s\n", language.str_value); -#endif +#endif break; - } + } /* program name */ name_len = (unsigned char)eit[4]; @@ -1575,20 +1584,20 @@ static void load_epg_data(dvb_input_plugin_t *this) break; } - /* the first char of the string contains sometimes the character + /* the first char of the string contains sometimes the character encoding information, which should not be copied to the string. (FIXME - we ought to be using this byte to change charsets)*/ - + if (!isalnum(*(eit + 5))) skip_byte = 1; else skip_byte = 0; - memcpy(current_epg->progname, eit + 5 + skip_byte, - name_len - skip_byte); + memcpy(current_epg->progname, eit + 5 + skip_byte, + name_len - skip_byte); current_epg->progname[name_len - skip_byte] = '\0'; - /* detailed program information (max 256 chars)*/ + /* detailed program information (max 256 chars)*/ text_len = (unsigned char)eit[5 + name_len]; if (text_len == 0) { current_epg->description[0] = '\0'; @@ -1600,7 +1609,7 @@ static void load_epg_data(dvb_input_plugin_t *this) else skip_byte = 0; - memcpy(current_epg->description, eit + 6 + name_len + skip_byte, + memcpy(current_epg->description, eit + 6 + name_len + skip_byte, text_len - skip_byte); current_epg->description[text_len - skip_byte] = '\0'; } @@ -1616,7 +1625,7 @@ static void load_epg_data(dvb_input_plugin_t *this) snprintf(current_epg->content, MAX_EPG_CONTENT_TYPE_LENGTH, "%s", content[content_bits]); } break; - case 0x55: { /* Parental Rating descriptor describes minimum recommened age -3 */ + case 0x55: { /* Parental Rating descriptor describes minimum recommened age -3 */ /* A rating value of 0 means that there is no rating defined. Ratings greater than 0xF are "defined by broadcaster", which is not supported @@ -1626,7 +1635,7 @@ static void load_epg_data(dvb_input_plugin_t *this) else current_epg->rating = 0; } - break; + break; default: break; } @@ -1635,41 +1644,42 @@ static void load_epg_data(dvb_input_plugin_t *this) eit += getbits(eit, 0, 8); descriptor_id = eit[1]; eit += 2; - } + } /* Store the entry if we got enough data. */ - if (current_epg->progname && strlen(current_epg->progname)) + if (current_epg->progname && strlen(current_epg->progname)) current_channel->epg_count++; } } /* Sort the EPG arrays by starttime. */ for (i = 0; i < this->num_channels; ++i) { - if (!seen_channels[i]) + if (!seen_channels[i]) continue; - qsort(this->channels[i].epg, this->channels[i].epg_count, + qsort(this->channels[i].epg, this->channels[i].epg_count, sizeof(epg_entry_t*), compare_epg_by_starttime); } free(seen_channels); - free(foo); + free(foo); pthread_mutex_unlock(&this->channel_change_mutex); } /* Prints text to an area, tries to cut the lines in between words. */ -static void render_text_area(osd_renderer_t* renderer, osd_object_t* osd, char* text, - int x, int y, int row_space, +static void render_text_area(osd_renderer_t* renderer, osd_object_t* osd, const char* text, + int x, int y, int row_space, int max_x, int max_y, int* height, int color_base) { /* The position of the text to be printed. */ - char* cursor = text; + const char* cursor = text; + const char *const text_end = text + strlen(text); /* The line to be printed next. */ char text_line[512]; int text_width, text_height; - int old_line_length, line_cursor; - char* bound, *old_bound; - + size_t old_line_length, line_cursor; + const char* bound, *old_bound; + *height = 0; - while (cursor < text + strlen(text)) { + while (cursor < text_end) { bound = cursor; line_cursor = 0; text_line[0] = '\0'; @@ -1681,12 +1691,12 @@ static void render_text_area(osd_renderer_t* renderer, osd_object_t* osd, char* line_cursor = old_line_length; /* Strip leading white space. */ - while (isspace(*bound)) + while (isspace(*bound)) bound++; - + /* Copy text to the text_line until end of word or end of string. */ while (!isspace(*bound) && *bound != '\0') { - text_line[line_cursor] = *bound; + text_line[line_cursor] = *bound; bound++; line_cursor++; } @@ -1699,13 +1709,13 @@ static void render_text_area(osd_renderer_t* renderer, osd_object_t* osd, char* if (x + text_width > max_x) { /* It didn't fit, restore the old line and stop trying to fit more.*/ text_line[old_line_length] = '\0'; - + /* If no words did fit to the line, fit as many characters as possible in it. */ if (old_line_length == 0) { text_width = 0; bound = bound - line_cursor + 1; /* rewind to the beginning of the word */ line_cursor = 0; - while (!isspace(*bound) && + while (!isspace(*bound) && *bound != '\0') { text_line[line_cursor++] = *bound++; text_line[line_cursor] = '\0'; @@ -1724,10 +1734,10 @@ static void render_text_area(osd_renderer_t* renderer, osd_object_t* osd, char* bound = old_bound; break; } - + /* OK, it did fit, let's try to fit some more. */ - } while (bound < text + strlen(text)); - + } while (bound < text_end); + if (y + text_height + row_space > max_y) { break; } @@ -1738,7 +1748,7 @@ static void render_text_area(osd_renderer_t* renderer, osd_object_t* osd, char* } } -/* Finds the EPG of the ith next program. 0 means the current program, 1 next. +/* Finds the EPG of the ith next program. 0 means the current program, 1 next. If not found, returns NULL. All these functions expect the EPG entries are sorted by starting time. */ static epg_entry_t* ith_next_epg(channel_t* channel, int count) { @@ -1746,14 +1756,14 @@ static epg_entry_t* ith_next_epg(channel_t* channel, int count) { int counter = 0; /* Discard the entries of past programs. */ - while (counter + 1 < channel->epg_count && + while (counter + 1 < channel->epg_count && difftime(channel->epg[counter + 1]->starttime, current_time) < 0.0) counter++; /* Check whether the previous program has still the running bit on, and if it's not more late than the given margin, assume it's still running. */ - if (counter >= 1 && channel->epg[counter - 1]->running && + if (counter >= 1 && channel->epg[counter - 1]->running && difftime(current_time, channel->epg[counter]->starttime) < MAX_EPG_ENTRY_LATENESS) { counter--; } @@ -1768,13 +1778,13 @@ static epg_entry_t* ith_next_epg(channel_t* channel, int count) { ago. In that case do not return any EPG. This fixes the "very last program of the day sticking until morning" bug. */ if (counter == channel->epg_count - 1) { - if (difftime(current_time, - channel->epg[counter]->starttime + + if (difftime(current_time, + channel->epg[counter]->starttime + channel->epg[counter]->duration_hours*60*60 + channel->epg[counter]->duration_minutes*60) > MAX_EPG_ENTRY_LATENESS) { return NULL; } - } + } return channel->epg[counter]; } @@ -1785,7 +1795,7 @@ static epg_entry_t* current_epg(channel_t* channel) { #ifdef DEBUG_EPG if (next != NULL) printf("input_dvb: EPG current: %s (%d)\n", next->progname, next->running); -#endif +#endif return next; } @@ -1795,13 +1805,13 @@ static epg_entry_t* next_epg(channel_t* channel) { #ifdef DEBUG_EPG if (next != NULL) printf("input_dvb: EPG next: %s (%d)\n", next->progname, next->running); -#endif +#endif return next; } /* Displays the program info of an EPG entry in OSD. - + x,y The upper left coordinates of the program information area. max_x, max_y The maximum right coordinate of the program information area. last_y The position of y after printing the entry. @@ -1810,7 +1820,7 @@ static epg_entry_t* next_epg(channel_t* channel) { Returns the height of the entry in the OSD in pixels. */ static void show_program_info(int x, int y, int max_x, int max_y, int* last_y, - epg_entry_t* epg_data, osd_renderer_t* renderer, + epg_entry_t* epg_data, osd_renderer_t* renderer, osd_object_t* osd) { char* buffer; int time_width, text_width, dummy; @@ -1825,7 +1835,7 @@ static void show_program_info(int x, int y, int max_x, int max_y, int* last_y, if (epg_data == NULL || epg_data->progname == NULL) return; - buffer = xine_xmalloc(512); + buffer = calloc(1, 512); _x_assert(buffer != NULL); @@ -1842,15 +1852,14 @@ static void show_program_info(int x, int y, int max_x, int max_y, int* last_y, /*Content type and rating, if any. */ if (strlen(epg_data->content) > 3) { - - snprintf(buffer, 94, "%s", epg_data->content); + strncpy(buffer, epg_data->content, 94-1); prog_rating = epg_data->rating; if (prog_rating > 0) { snprintf(buffer + strlen(buffer), 7, " (%i+)", prog_rating); } if (!renderer->set_font(osd, "sans", EPG_CONTENT_FONT_SIZE)) { - print_error("Setting content type font failed."); + print_error("Setting content type font failed."); } renderer->get_text_size(osd, buffer, &content_width, &dummy); renderer->render_text(osd, max_x - 2 - content_width, y, buffer, OSD_TEXT3); @@ -1858,14 +1867,14 @@ static void show_program_info(int x, int y, int max_x, int max_y, int* last_y, text_width = max_x - x - time_width - content_width - 2; - renderer->set_font(osd, "sans", EPG_TITLE_FONT_SIZE); + renderer->set_font(osd, "sans", EPG_TITLE_FONT_SIZE); render_text_area(renderer, osd, epg_data->progname, - x + time_width, y, EPG_PIXELS_BETWEEN_TEXT_ROWS, - x + text_width + time_width, max_y, &text_height, + x + time_width, y, EPG_PIXELS_BETWEEN_TEXT_ROWS, + x + text_width + time_width, max_y, &text_height, OSD_TEXT4); - if (text_height == 0) + if (text_height == 0) *last_y = y + time_height; else *last_y = y + text_height; @@ -1873,7 +1882,7 @@ static void show_program_info(int x, int y, int max_x, int max_y, int* last_y, /* Print the description. */ if (epg_data->description && strlen(epg_data->description) > 0) { renderer->set_font(osd, "sans", EPG_DESCRIPTION_FONT_SIZE); - sprintf(buffer, "%s", epg_data->description); + strcpy(buffer, epg_data->description); /* If the description is not complete (i.e., there is no comma at the end), add "..." to the end. In my locale they often seem to send incomplete description texts :( */ @@ -1884,15 +1893,15 @@ static void show_program_info(int x, int y, int max_x, int max_y, int* last_y, /* If duration_hours is zero, do not print them. */ if (epg_data->duration_hours > 0) - sprintf(buffer + strlen(buffer), " (%dh%02dmin)", + sprintf(buffer + strlen(buffer), " (%dh%02dmin)", epg_data->duration_hours, epg_data->duration_minutes); else if (epg_data->duration_minutes > 0) - sprintf(buffer + strlen(buffer), " (%dmin)", + sprintf(buffer + strlen(buffer), " (%dmin)", epg_data->duration_minutes); - render_text_area(renderer, osd, buffer, x + time_width, - *last_y + EPG_PIXELS_BETWEEN_TEXT_ROWS, - EPG_PIXELS_BETWEEN_TEXT_ROWS, + render_text_area(renderer, osd, buffer, x + time_width, + *last_y + EPG_PIXELS_BETWEEN_TEXT_ROWS, + EPG_PIXELS_BETWEEN_TEXT_ROWS, max_x, max_y, &text_height, OSD_TEXT3); *last_y += EPG_PIXELS_BETWEEN_TEXT_ROWS + text_height; @@ -1914,7 +1923,7 @@ static void show_eit(dvb_input_plugin_t *this) { if (!this->epg_displaying) { #ifndef EPG_UPDATE_IN_BACKGROUND - if (current_epg(&this->channels[this->channel]) == NULL || + if (current_epg(&this->channels[this->channel]) == NULL || next_epg(&this->channels[this->channel]) == NULL) { load_epg_data(this); } @@ -1924,12 +1933,12 @@ static void show_eit(dvb_input_plugin_t *this) { this->stream->osd_renderer->hide(this->proginfo_osd, 0); this->stream->osd_renderer->clear(this->proginfo_osd); - /* Channel Name */ + /* Channel Name */ if (!this->stream->osd_renderer->set_font( this->proginfo_osd, "sans", EPG_CHANNEL_FONT_SIZE)) { print_error("Error setting channel name font."); } - + this->stream->osd_renderer->render_text( this->proginfo_osd, 0, 0, this->channels[this->channel].name, OSD_TEXT4); @@ -1947,11 +1956,11 @@ static void show_eit(dvb_input_plugin_t *this) { this->proginfo_osd, this->channels[this->channel].name, &temp1, &temp2); this->stream->osd_renderer->render_text( - this->proginfo_osd, EPG_WIDTH - 45, + this->proginfo_osd, EPG_WIDTH - 45, EPG_CHANNEL_FONT_SIZE - EPG_CLOCK_FONT_SIZE, clock, OSD_TEXT4); - + show_program_info(0, EPG_CHANNEL_FONT_SIZE + 2, EPG_WIDTH, EPG_HEIGHT, &y_pos, - current_epg(&this->channels[this->channel]), + current_epg(&this->channels[this->channel]), this->stream->osd_renderer, this->proginfo_osd); y = y_pos; @@ -1962,11 +1971,11 @@ static void show_eit(dvb_input_plugin_t *this) { this->proginfo_osd); y = y_pos; - window_width = + window_width = this->stream->video_out->get_property( this->stream->video_out, VO_PROP_WINDOW_WIDTH); - window_height = + window_height = this->stream->video_out->get_property( this->stream->video_out, VO_PROP_WINDOW_HEIGHT); @@ -1983,8 +1992,8 @@ static void show_eit(dvb_input_plugin_t *this) { this->stream->osd_renderer->set_text_palette( this->background, XINE_TEXTPALETTE_YELLOW_BLACK_TRANSPARENT, OSD_TEXT3); this->stream->osd_renderer->filled_rect( - this->background, 0, 0, - EPG_WIDTH + EPG_BACKGROUND_MARGIN*2, + this->background, 0, 0, + EPG_WIDTH + EPG_BACKGROUND_MARGIN*2, y + EPG_BACKGROUND_MARGIN*2, 4); /* In case video is downscaled and the EPG fits, show it unscaled to make it @@ -1998,8 +2007,8 @@ static void show_eit(dvb_input_plugin_t *this) { centered_y = (centered_y > 0)?(centered_y):(EPG_TOP); this->stream->osd_renderer->set_position( - this->proginfo_osd, - centered_x + EPG_BACKGROUND_MARGIN, + this->proginfo_osd, + centered_x + EPG_BACKGROUND_MARGIN, centered_y + EPG_BACKGROUND_MARGIN); this->stream->osd_renderer->set_position(this->background, centered_x, centered_y); @@ -2015,15 +2024,15 @@ static void show_eit(dvb_input_plugin_t *this) { /* Center the OSD to stream. */ this->stream->osd_renderer->set_position( - this->proginfo_osd, - centered_x + EPG_BACKGROUND_MARGIN, + this->proginfo_osd, + centered_x + EPG_BACKGROUND_MARGIN, centered_y + EPG_BACKGROUND_MARGIN); this->stream->osd_renderer->set_position(this->background, centered_x, centered_y); this->stream->osd_renderer->show(this->background, 0); this->stream->osd_renderer->show(this->proginfo_osd, 0); } - + } else { this->epg_displaying = 0; this->stream->osd_renderer->hide (this->proginfo_osd,0); @@ -2053,7 +2062,7 @@ static int tuner_set_channel (dvb_input_plugin_t *this, channel_t *c) { if (lastchannel.num_value){ /* Remember last watched channel. never show this entry*/ config->update_num(config, "media.dvb.last_channel", this->channel+1); - } + } #ifdef DVB_NO_BUFFERING this->newchannel=1; #endif @@ -2083,14 +2092,14 @@ static void osd_show_channel (dvb_input_plugin_t *this, int channel) { this->channel_osd, 110, 10+i*35, this->channels[channel_to_print].name, (channel_to_print == channel)?(OSD_TEXT4):(OSD_TEXT3)); - + if ((current_program = current_epg(&this->channels[channel_to_print])) && current_program->progname && strlen(current_program->progname) > 0) { this->stream->osd_renderer->set_font(this->channel_osd, "sans", 16); render_text_area(this->stream->osd_renderer, this->channel_osd, - current_program->progname, 400, 10+i*35, + current_program->progname, 400, 10+i*35, -5, CHSEL_WIDTH, 10+i*35+CHSEL_CHANNEL_FONT_SIZE+2, &temp, (channel_to_print == channel)?(OSD_TEXT4):(OSD_TEXT3)); } @@ -2113,19 +2122,19 @@ static void osd_show_channel (dvb_input_plugin_t *this, int channel) { } static int switch_channel(dvb_input_plugin_t *this, int channel) { - + int x; xine_event_t event; xine_pids_data_t data; xine_ui_data_t ui_data; - - /* control_nop appears to stop an occasional (quite long) pause between + + /* control_nop appears to stop an occasional (quite long) pause between channel-changes, which the user may see as a lockup. */ _x_demux_control_nop(this->stream, BUF_FLAG_END_STREAM); - _x_demux_flush_engine(this->stream); + _x_demux_flush_engine(this->stream); pthread_mutex_lock (&this->channel_change_mutex); - + close (this->fd); this->tuned_in = 0; @@ -2133,9 +2142,9 @@ static int switch_channel(dvb_input_plugin_t *this, int channel) { close(this->tuner->fd_pidfilter[x]); this->tuner->fd_pidfilter[x] = open(this->tuner->demux_device, O_RDWR); } - + if (!tuner_set_channel (this, &this->channels[channel])) { - xprintf (this->class->xine, XINE_VERBOSITY_LOG, + xprintf (this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: tuner_set_channel failed\n")); pthread_mutex_unlock (&this->channel_change_mutex); return 0; @@ -2169,7 +2178,7 @@ static int switch_channel(dvb_input_plugin_t *this, int channel) { this->tuned_in = 1; pthread_mutex_unlock (&this->channel_change_mutex); - + /* now read the pat, find all accociated PIDs and add them to the stream */ dvb_parse_si(this); @@ -2181,7 +2190,7 @@ static int switch_channel(dvb_input_plugin_t *this, int channel) { /* show eit for this channel if necessary */ if (this->epg_displaying==1){ - this->epg_displaying=0; + this->epg_displaying=0; show_eit(this); } return 1; @@ -2190,7 +2199,7 @@ static int switch_channel(dvb_input_plugin_t *this, int channel) { static void do_record (dvb_input_plugin_t *this) { struct tm *tma; - time_t *t; + time_t *t; char filename [256]; char dates[64]; int x=0; @@ -2207,7 +2216,7 @@ static void do_record (dvb_input_plugin_t *this) { this->stream->osd_renderer->hide (this->paused_osd, 0); this->record_paused=0; } else { - t=xine_xmalloc(sizeof(time_t)); + t=calloc(1, sizeof(time_t)); _x_assert(t != NULL); @@ -2216,7 +2225,7 @@ static void do_record (dvb_input_plugin_t *this) { free(t); t = NULL; strftime(dates,63,"%Y-%m-%d_%H%M",tma); - + if (xine_config_lookup_entry(this->stream->xine, "media.capture.save_dir", &savedir)){ if(strlen(savedir.str_value)>1){ if((dir = opendir(savedir.str_value))==NULL){ @@ -2242,7 +2251,7 @@ static void do_record (dvb_input_plugin_t *this) { this->record_fd = open (filename, O_CREAT | O_APPEND | O_WRONLY, 0644); this->stream->osd_renderer->clear (this->rec_osd); - + this->stream->osd_renderer->render_text (this->rec_osd, 10, 10, "Recording to:", OSD_TEXT3); @@ -2258,7 +2267,7 @@ static void dvb_event_handler (dvb_input_plugin_t *this) { xine_event_t *event; static int channel_menu_visible = 0; - static int next_channel = -1; + static int next_channel = -1; while ((event = xine_event_get (this->event_queue))) { @@ -2284,7 +2293,7 @@ static void dvb_event_handler (dvb_input_plugin_t *this) { } else this->stream->osd_renderer->hide(this->channel_osd, 0); - } + } #ifdef LEFT_MOUSE_DOES_EPG else { /* show EPG on left click of videowindow */ show_eit(this); @@ -2443,27 +2452,27 @@ static void dvb_event_handler (dvb_input_plugin_t *this) { static void ts_rewrite_packets (dvb_input_plugin_t *this, unsigned char * originalPkt, int len) { #define PKT_SIZE 188 -#define BODY_SIZE (188-4) +#define BODY_SIZE (188-4) unsigned int sync_byte; unsigned int data_offset; unsigned int data_len; - unsigned int pid; + unsigned int pid; while(len>0){ - + sync_byte = originalPkt[0]; pid = ((originalPkt[1] << 8) | originalPkt[2]) & 0x1fff; - + /* * Discard packets that are obviously bad. */ data_offset = 4; originalPkt+=data_offset; - + if (pid == 0 && sync_byte==0x47) { unsigned long crc; - + originalPkt[3]=13; /* section length including CRC - first 3 bytes */ originalPkt[2]=0x80; originalPkt[7]=0; /* section number */ @@ -2474,13 +2483,13 @@ static void ts_rewrite_packets (dvb_input_plugin_t *this, unsigned char * origin originalPkt[12]=this->channels[this->channel].pmtpid & 0xff; crc= ts_compute_crc32 (this, originalPkt+1, 12, 0xffffffff); - + originalPkt[13]=(crc>>24) & 0xff; originalPkt[14]=(crc>>16) & 0xff; originalPkt[15]=(crc>>8) & 0xff; originalPkt[16]=crc & 0xff; memset(originalPkt+17,0xFF,PKT_SIZE-21); /* stuff the remainder */ - + } data_len = PKT_SIZE - data_offset; @@ -2499,44 +2508,42 @@ static off_t dvb_plugin_read (input_plugin_t *this_gen, if (!this->tuned_in) return 0; - dvb_event_handler (this); + if (this->dvb_gui_enabled) + dvb_event_handler (this); #ifdef LOG_READS xprintf(this->class->xine,XINE_VERBOSITY_DEBUG, "input_dvb: reading %" PRIdMAX " bytes...\n", (intmax_t)len); #endif -#ifndef DVB_NO_BUFFERING - nbc_check_buffers (this->nbc); -#endif /* protect against channel changes */ have_mutex = pthread_mutex_lock(&this->channel_change_mutex); total=0; - - while (total<len){ + + while (total<len){ pfd.fd = this->fd; pfd.events = POLLPRI | POLLIN | POLLERR; pfd.revents = 0; - + if (!this->tuned_in) { pthread_mutex_unlock( &this->channel_change_mutex ); xprintf(this->class->xine, XINE_VERBOSITY_LOG, "input_dvb: Channel \"%s\" could not be tuned in. " "Possibly erroneus settings in channels.conf " - "(frequency changed?).\n", + "(frequency changed?).\n", this->channels[this->channel].name); return 0; } - - if (poll(&pfd, 1, 1500) < 1) { + + if (poll(&pfd, 1, 1500) < 1) { xprintf(this->class->xine, XINE_VERBOSITY_LOG, "input_dvb: No data available. Signal Lost?? \n"); - _x_demux_control_end(this->stream, BUF_FLAG_END_USER); + _x_demux_control_end(this->stream, BUF_FLAG_END_USER); this->read_failcount++; break; } - if (this->read_failcount) { - /* signal/stream regained after loss - + if (this->read_failcount) { + /* signal/stream regained after loss - kick the net_buf_control layer. */ this->read_failcount=0; xprintf(this->class->xine,XINE_VERBOSITY_LOG, @@ -2546,22 +2553,22 @@ static off_t dvb_plugin_read (input_plugin_t *this_gen, if (pfd.revents & POLLPRI || pfd.revents & POLLIN) { n = read (this->fd, &buf[total], len-total); - } else + } else if (pfd.revents & POLLERR) { xprintf(this->class->xine, XINE_VERBOSITY_LOG, "input_dvb: No data available. Signal Lost?? \n"); - _x_demux_control_end(this->stream, BUF_FLAG_END_USER); + _x_demux_control_end(this->stream, BUF_FLAG_END_USER); this->read_failcount++; break; - } + } #ifdef LOG_READS xprintf(this->class->xine,XINE_VERBOSITY_DEBUG, - "input_dvb: got %" PRIdMAX " bytes (%" PRIdMAX "/%" PRIdMAX " bytes read)\n", + "input_dvb: got %" PRIdMAX " bytes (%" PRIdMAX "/%" PRIdMAX " bytes read)\n", (intmax_t)n, (intmax_t)total, (intmax_t)len); #endif - - if (n > 0){ + + if (n > 0){ this->curpos += n; total += n; } else if (n < 0 && errno!=EAGAIN) { @@ -2578,7 +2585,7 @@ static off_t dvb_plugin_read (input_plugin_t *this_gen, /* no data for several seconds - tell the user a possible reason */ if(this->read_failcount==5){ - _x_message(this->stream,1,"DVB Signal Lost. Please check connections.", NULL); + _x_message(this->stream,1,"DVB Signal Lost. Please check connections.", NULL); } #ifdef DVB_NO_BUFFERING if(this->newchannel){ @@ -2595,6 +2602,12 @@ static buf_element_t *dvb_plugin_read_block (input_plugin_t *this_gen, buf_element_t *buf = fifo->buffer_pool_alloc (fifo); int total_bytes; + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -2660,7 +2673,7 @@ static void dvb_plugin_dispose (input_plugin_t *this_gen) { } if (this->nbc) { - nbc_close (this->nbc); + nbc_close (this->nbc); this->nbc = NULL; } @@ -2764,7 +2777,12 @@ static int dvb_plugin_open(input_plugin_t * this_gen) xine_cfg_entry_t zoomdvb; xine_cfg_entry_t adapter; xine_cfg_entry_t lastchannel; - + xine_cfg_entry_t gui_enabled; + + xine_config_lookup_entry(this->stream->xine, "media.dvb.gui_enabled", &gui_enabled); + this->dvb_gui_enabled = gui_enabled.num_value; + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: DVB GUI %s\n"), this->dvb_gui_enabled ? "enabled" : "disabled"); + xine_config_lookup_entry(this->stream->xine, "media.dvb.adapter", &adapter); if (!(tuner = tuner_init(this->class->xine,adapter.num_value))) { @@ -2780,7 +2798,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) * and assume that its format is valid for our tuner type */ - if (!(channels = load_channels(this->class->xine, this->stream, &num_channels, tuner->feinfo.type))) + if (!(channels = load_channels(this->class->xine, this->stream, &num_channels, tuner->feinfo.type))) { /* failed to load the channels */ tuner_dispose(tuner); @@ -2816,13 +2834,13 @@ static int dvb_plugin_open(input_plugin_t * this_gen) } else { /* * try a partial match too - * be smart and compare starting from the first char, then from + * be smart and compare starting from the first char, then from * the second etc.. * Yes, this is expensive, but it happens really often * that the channels have really ugly names, sometimes prefixed * by numbers... */ - int chanlen = strlen(channame); + size_t chanlen = strlen(channame); int offset = 0; xprintf(this->class->xine, XINE_VERBOSITY_LOG, @@ -2834,7 +2852,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) if (strlen(channels[idx].name) > offset) { if (strncasecmp(channels[idx].name + offset, channame, chanlen) == 0) { xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: found matching channel %s\n"), channels[idx].name); - break; + break; } } idx++; @@ -2857,6 +2875,8 @@ static int dvb_plugin_open(input_plugin_t * this_gen) if (lastchannel.num_value) { if (xine_config_lookup_entry(this->class->xine, "media.dvb.last_channel", &lastchannel)){ this->channel = lastchannel.num_value -1; + if (this->channel < 0 || this->channel >= num_channels) + this->channel = 0; /* out of range? default */ }else{ xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: invalid channel specification, defaulting to channel 0\n")); this->channel = 0; @@ -2876,7 +2896,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) } ptr = this->mrl; ptr += 7; - channels = xine_xmalloc(sizeof(channel_t)); + channels = calloc(1, sizeof(channel_t)); _x_assert(channels != NULL); if (extract_channel_from_string(channels, ptr, tuner->feinfo.type) < 0) { free(channels); @@ -2896,7 +2916,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) } ptr = this->mrl; ptr += 7; - channels = xine_xmalloc(sizeof(channel_t)); + channels = calloc(1, sizeof(channel_t)); _x_assert(channels != NULL); if (extract_channel_from_string(channels, ptr, tuner->feinfo.type) < 0) { free(channels); @@ -2905,12 +2925,12 @@ static int dvb_plugin_open(input_plugin_t * this_gen) return 0; } this->channel = 0; - } else if (strncasecmp(this->mrl, "dvbc://", 7) == 0) + } else if (strncasecmp(this->mrl, "dvbc://", 7) == 0) { /* * This is dvbc://<channel name>:<qam tuning parameters> */ - if (tuner->feinfo.type != FE_QAM) + if (tuner->feinfo.type != FE_QAM) { xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: dvbc mrl specified but the tuner doesn't appear to be QAM (DVB-C)\n")); @@ -2919,7 +2939,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) } ptr = this->mrl; ptr += 7; - channels = xine_xmalloc(sizeof(channel_t)); + channels = calloc(1, sizeof(channel_t)); _x_assert(channels != NULL); if (extract_channel_from_string(channels, ptr, tuner->feinfo.type) < 0) { @@ -2929,15 +2949,15 @@ static int dvb_plugin_open(input_plugin_t * this_gen) return 0; } this->channel = 0; - } else if (strncasecmp(this->mrl, "dvba://", 7) == 0) + } else if (strncasecmp(this->mrl, "dvba://", 7) == 0) { - fprintf(stderr,"input_dvb: 2a %x\n",tuner->feinfo.type); + fprintf(stderr,"input_dvb: 2a %x\n",tuner->feinfo.type); /* * This is dvba://<channel name>:<atsc tuning parameters> */ - if (tuner->feinfo.type != FE_ATSC) + if (tuner->feinfo.type != FE_ATSC) { - fprintf(stderr,"input_dvb: FAILED 1\n"); + fprintf(stderr,"input_dvb: FAILED 1\n"); xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: dvba mrl specified but the tuner doesn't appear to be ATSC (DVB-A)\n")); tuner_dispose(tuner); @@ -2945,11 +2965,11 @@ static int dvb_plugin_open(input_plugin_t * this_gen) } ptr = this->mrl; ptr += 7; - channels = xine_xmalloc(sizeof(channel_t)); + channels = calloc(1, sizeof(channel_t)); _x_assert(channels != NULL); if (extract_channel_from_string(channels, ptr, tuner->feinfo.type) < 0) { - fprintf(stderr,"input_dvb: FAILED 2\n"); + fprintf(stderr,"input_dvb: FAILED 2\n"); free(channels); channels = NULL; tuner_dispose(tuner); @@ -2965,7 +2985,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) this->tuner = tuner; this->channels = channels; this->num_channels = num_channels; - + if (!tuner_set_channel(this, &this->channels[this->channel])) { xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("input_dvb: tuner_set_channel failed\n")); @@ -2978,7 +2998,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) return 0; } this->tuned_in = 1; - + /* now read the pat, find all accociated PIDs and add them to the stream */ dvb_parse_si(this); @@ -2990,16 +3010,17 @@ static int dvb_plugin_open(input_plugin_t * this_gen) this->event_queue = xine_event_new_queue(this->stream); #ifdef EPG_UPDATE_IN_BACKGROUND - /* Start the EPG updater thread. */ - this->epg_updater_stop = 0; - if (pthread_create(&this->epg_updater_thread, NULL, - epg_data_updater, this) != 0) { - xprintf( - this->class->xine, XINE_VERBOSITY_LOG, - _("input_dvb: cannot create EPG updater thread\n")); - return 0; - - } + if (this->dvb_gui_enabled) { + /* Start the EPG updater thread. */ + this->epg_updater_stop = 0; + if (pthread_create(&this->epg_updater_thread, NULL, + epg_data_updater, this) != 0) { + xprintf( + this->class->xine, XINE_VERBOSITY_LOG, + _("input_dvb: cannot create EPG updater thread\n")); + return 0; + } + } #endif /* * this osd is used to draw the "recording" sign @@ -3018,8 +3039,8 @@ static int dvb_plugin_open(input_plugin_t * this_gen) this->stream->osd_renderer->set_position(this->channel_osd, 20, 10); this->stream->osd_renderer->set_encoding(this->channel_osd, NULL); - /* - * this osd is for displaying currently shown channel name + /* + * this osd is for displaying currently shown channel name */ this->name_osd = this->stream->osd_renderer->new_object(this->stream->osd_renderer, 301, 61); this->stream->osd_renderer->set_position(this->name_osd, 20, 10); @@ -3027,8 +3048,8 @@ static int dvb_plugin_open(input_plugin_t * this_gen) this->stream->osd_renderer->set_encoding(this->name_osd, NULL); this->stream->osd_renderer->set_text_palette(this->name_osd, XINE_TEXTPALETTE_YELLOW_BLACK_TRANSPARENT, OSD_TEXT3); - /* - * this osd is for displaying Recording Paused + /* + * this osd is for displaying Recording Paused */ this->paused_osd = this->stream->osd_renderer->new_object(this->stream->osd_renderer, 301, 161); this->stream->osd_renderer->set_position(this->paused_osd, 10, 50); @@ -3036,10 +3057,10 @@ static int dvb_plugin_open(input_plugin_t * this_gen) this->stream->osd_renderer->set_encoding(this->paused_osd, NULL); this->stream->osd_renderer->set_text_palette(this->paused_osd, XINE_TEXTPALETTE_YELLOW_BLACK_TRANSPARENT, OSD_TEXT3); - /* + /* * This osd is for displaying Program Information (EIT), i.e., EPG. */ - this->proginfo_osd = + this->proginfo_osd = this->stream->osd_renderer->new_object( this->stream->osd_renderer, EPG_WIDTH, EPG_HEIGHT); @@ -3048,10 +3069,10 @@ static int dvb_plugin_open(input_plugin_t * this_gen) this->stream->osd_renderer->set_text_palette(this->proginfo_osd, XINE_TEXTPALETTE_WHITE_NONE_TRANSLUCID, OSD_TEXT3); this->stream->osd_renderer->set_text_palette(this->proginfo_osd, XINE_TEXTPALETTE_YELLOW_BLACK_TRANSPARENT, OSD_TEXT4); - this->background = + this->background = this->stream->osd_renderer->new_object( - this->stream->osd_renderer, - EPG_WIDTH + EPG_BACKGROUND_MARGIN*2, + this->stream->osd_renderer, + EPG_WIDTH + EPG_BACKGROUND_MARGIN*2, EPG_HEIGHT + EPG_BACKGROUND_MARGIN*2); this->epg_displaying = 0; @@ -3085,7 +3106,7 @@ static int dvb_plugin_open(input_plugin_t * this_gen) /* Clear all pids, the pmt will tell us which to use */ for (x = 0; x < MAX_FILTERS; x++){ this->channels[this->channel].pid[x] = DVB_NOPID; - } + } return 1; @@ -3109,7 +3130,7 @@ static input_plugin_t *dvb_class_get_instance (input_class_t *class_gen, fprintf(stderr, "input_dvb: continuing in get_instance\n"); - this = (dvb_input_plugin_t *) xine_xmalloc (sizeof(dvb_input_plugin_t)); + this = calloc(1, sizeof(dvb_input_plugin_t)); _x_assert(this != NULL); @@ -3121,16 +3142,16 @@ static input_plugin_t *dvb_class_get_instance (input_class_t *class_gen, this->fd = -1; this->tuned_in = 0; #ifndef DVB_NO_BUFFERING - this->nbc = nbc_init (this->stream); + this->nbc = nbc_init (this->stream); #else - this->nbc = NULL; + this->nbc = NULL; #endif this->osd = NULL; this->event_queue = NULL; this->record_fd = -1; this->read_failcount = 0; this->epg_updater_stop = 0; - + this->input_plugin.open = dvb_plugin_open; this->input_plugin.get_capabilities = dvb_plugin_get_capabilities; this->input_plugin.read = dvb_plugin_read; @@ -3164,7 +3185,9 @@ static void dvb_class_dispose(input_class_t * this_gen) { dvb_input_class_t *class = (dvb_input_class_t *) this_gen; int x; - + + free(class->default_channels_conf_filename); + for(x=0;x<class->numchannels;x++) free(class->autoplaylist[x]); @@ -3181,7 +3204,6 @@ static char **dvb_class_get_autoplay_list(input_class_t * this_gen, { dvb_input_class_t *class = (dvb_input_class_t *) this_gen; channel_t *channels=NULL; - char foobuffer[BUFSIZE]; int ch, apch, num_channels = 0; int default_channel = -1; xine_cfg_entry_t lastchannel_enable = {0}; @@ -3211,7 +3233,7 @@ static char **dvb_class_get_autoplay_list(input_class_t * this_gen, tuner_dispose(tuner); return class->mrls; } - + tuner_dispose(tuner); if (xine_config_lookup_entry(class->xine, "media.dvb.remember_channel", &lastchannel_enable) @@ -3226,21 +3248,19 @@ static char **dvb_class_get_autoplay_list(input_class_t * this_gen, for (ch = 0, apch = !!lastchannel_enable.num_value; ch < num_channels && ch < MAX_AUTOCHANNELS; ++ch, ++apch) { - snprintf(foobuffer, BUFSIZE, "dvb://%s", channels[ch].name); - free(class->autoplaylist[apch]); - class->autoplaylist[apch] = strdup(foobuffer); - _x_assert(class->autoplaylist[apch] != NULL); + free(class->autoplaylist[apch]); + asprintf(&(class->autoplaylist[apch]), "dvb://%s", channels[ch].name); + _x_assert(class->autoplaylist[apch] != NULL); } if (lastchannel_enable.num_value){ + free(class->autoplaylist[0]); if (default_channel != -1) /* plugin has been used before - channel is valid */ - sprintf (foobuffer, "dvb://%s", channels[default_channel].name); + asprintf (&(class->autoplaylist[0]), "dvb://%s", channels[default_channel].name); else /* set a reasonable default - the first channel */ - sprintf (foobuffer, "dvb://%s", num_channels ? channels[0].name : "0"); - free(class->autoplaylist[0]); - class->autoplaylist[0]=strdup(foobuffer); + asprintf (&(class->autoplaylist[0]), "dvb://%s", num_channels ? channels[0].name : "0"); } free_channel_list(channels, num_channels); @@ -3256,7 +3276,7 @@ static void *init_class (xine_t *xine, void *data) { dvb_input_class_t *this; config_values_t *config = xine->config; - this = (dvb_input_class_t *) xine_xmalloc (sizeof (dvb_input_class_t)); + this = calloc(1, sizeof (dvb_input_class_t)); _x_assert(this != NULL); this->xine = xine; @@ -3276,6 +3296,10 @@ static void *init_class (xine_t *xine, void *data) { this->mrls[4] = "dvba://"; this->mrls[5] = 0; + asprintf(&this->default_channels_conf_filename, + "%s/.xine/channels.conf", + xine_get_homedir()); + xprintf(this->xine,XINE_VERBOSITY_DEBUG,"init class succeeded\n"); /* Enable remembering of last watched channel */ @@ -3307,8 +3331,20 @@ static void *init_class (xine_t *xine, void *data) { "really have more than 1 card " "in your system."), 0, NULL, (void *) this); - + /* set to 0 to turn off the GUI built into this input plugin */ + config->register_bool(config, "media.dvb.gui_enabled", + 1, + _("Enable the DVB GUI"), + _("Enable the DVB GUI, mouse controlled recording and channel switching."), + 21, NULL, NULL); + /* Override the default channels file */ + config->register_filename(config, "media.dvb.channels_conf", + this->default_channels_conf_filename, + XINE_CONFIG_STRING_IS_FILENAME, + _("DVB Channels config file"), + _("DVB Channels config file to use instead of the ~/.xine/channels.conf file."), + 21, NULL, NULL); return this; } diff --git a/src/input/input_dvd.c b/src/input/input_dvd.c index a891b9877..400f82aca 100644 --- a/src/input/input_dvd.c +++ b/src/input/input_dvd.c @@ -1,26 +1,26 @@ -/* - * Copyright (C) 2000-2005 the xine project, +/* + * Copyright (C) 2000-2005 the xine project, * Rich Wareham <richwareham@users.sourceforge.net> - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ /* This file was origninally part of the xine-dvdnav project - * at http://dvd.sf.net/. + * at http://dvd.sf.net/. */ /* TODO: @@ -53,7 +53,9 @@ #include <dlfcn.h> #ifndef WIN32 +#if ! defined(__GNU__) #include <sys/mount.h> +#endif #include <sys/wait.h> #include <sys/poll.h> @@ -115,10 +117,13 @@ /* There really isn't a default on Windows! */ #define DVD_PATH "d:\\" #define RDVD_PATH "d:\\" +#elif defined(__OpenBSD__) +#define DVD_PATH "/dev/rcd0c" +#define RDVD_PATH "/dev/rcd0c" #else #define DVD_PATH "/dev/dvd" #define RDVD_PATH "/dev/rdvd" -#endif +#endif /* Some misc. defines */ #ifdef DVD_VIDEO_LB_LEN @@ -148,7 +153,7 @@ /* Array to hold MRLs returned by get_autoplay_list */ #define MAX_DIR_ENTRIES 1250 -#define MAX_STR_LEN 255 +#define MAX_STR_LEN 255 #if defined (__FreeBSD__) # define off64_t off_t @@ -171,7 +176,7 @@ typedef struct { xine_stream_t *stream; xine_event_queue_t *event_queue; - + int pause_timer; /* Cell still-time timer */ int pause_counter; time_t pause_end_time; @@ -181,7 +186,7 @@ typedef struct { int64_t pg_start; int32_t buttonN; int typed_buttonN;/* for XINE_EVENT_INPUT_NUMBER_* */ - + int32_t mouse_buttonN; int mouse_in; @@ -190,13 +195,13 @@ typedef struct { int seekable; /* are we seekable? */ int mode; /* MODE_NAVIGATE / MODE_TITLE */ int tt, pr; /* title / chapter */ - + /* xine specific variables */ const char *current_dvd_device; /* DVD device currently open */ char *mrl; /* Current MRL */ dvdnav_t *dvdnav; /* Handle for libdvdnav */ const char *dvd_name; - + /* special buffer handling for libdvdnav caching */ pthread_mutex_t buf_mutex; void *source; @@ -235,16 +240,16 @@ static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode); /* Callback on device name change */ static void device_change_cb(void *data, xine_cfg_entry_t *cfg) { dvd_input_class_t *class = (dvd_input_class_t *) data; - + class->dvd_device = cfg->str_value; } static uint32_t dvd_plugin_get_capabilities (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; - + trace_print("Called\n"); - return INPUT_CAP_BLOCK | + return INPUT_CAP_BLOCK | /* TODO: figure out if there is any "allow copying" flag on DVD. * maybe set INPUT_CAP_RIP_FORBIDDEN only for encrypted media? */ @@ -252,7 +257,7 @@ static uint32_t dvd_plugin_get_capabilities (input_plugin_t *this_gen) { #if CAN_SEEK (this->seekable ? INPUT_CAP_SEEKABLE : 0) | #endif - INPUT_CAP_AUDIOLANG | INPUT_CAP_SPULANG | INPUT_CAP_CHAPTERS; + INPUT_CAP_AUDIOLANG | INPUT_CAP_SPULANG | INPUT_CAP_CHAPTERS; } static void read_ahead_cb(void *this_gen, xine_cfg_entry_t *entry) { @@ -269,7 +274,7 @@ static void read_ahead_cb(void *this_gen, xine_cfg_entry_t *entry) { dvdnav_set_readahead_flag(this->dvdnav, entry->num_value); } } - + static void seek_mode_cb(void *this_gen, xine_cfg_entry_t *entry) { dvd_input_class_t *class = (dvd_input_class_t*)this_gen; @@ -284,7 +289,7 @@ static void seek_mode_cb(void *this_gen, xine_cfg_entry_t *entry) { dvdnav_set_PGC_positioning_flag(this->dvdnav, !entry->num_value); } } - + static void region_changed_cb (void *this_gen, xine_cfg_entry_t *entry) { dvd_input_class_t *class = (dvd_input_class_t*)this_gen; @@ -307,10 +312,10 @@ static void language_changed_cb(void *this_gen, xine_cfg_entry_t *entry) { return; class->language = entry->str_value[0] << 8 | entry->str_value[1]; - + if(class->ip) { dvd_input_plugin_t *this = class->ip; - + dvdnav_menu_language_select(this->dvdnav, entry->str_value); dvdnav_audio_language_select(this->dvdnav, entry->str_value); dvdnav_spu_language_select(this->dvdnav, entry->str_value); @@ -337,29 +342,32 @@ static void send_mouse_enter_leave_event(dvd_input_plugin_t *this, int direction spu_event.direction = direction; spu_event.button = this->mouse_buttonN; - + event.type = XINE_EVENT_SPU_BUTTON; event.stream = this->stream; event.data = &spu_event; event.data_length = sizeof(spu_event); xine_event_send(this->stream, &event); - + this->mouse_in = direction; } if(!direction) this->mouse_buttonN = -1; } - + static int update_title_display(dvd_input_plugin_t *this) { - char ui_title[MAX_STR_LEN + 1]; - xine_event_t uevent; xine_ui_data_t data; + xine_event_t uevent = { + .type = XINE_EVENT_UI_SET_TITLE, + .stream = this->stream, + .data = &data, + .data_length = sizeof(data) + }; int tt=-1, pr=-1; - size_t ui_str_length=0; int num_tt = 0; - if(!this || !(this->stream)) + if(!this || !(this->stream)) return 0; /* Set title/chapter display */ @@ -377,24 +385,24 @@ static int update_title_display(dvd_input_plugin_t *this) { dvdnav_get_number_of_titles(this->dvdnav, &num_tt ); - - if(tt >= 1) { + + if(tt >= 1) { int num_angle = 0, cur_angle = 0; int num_part = 0; - /* no menu here */ + /* no menu here */ /* Reflect angle info if appropriate */ dvdnav_get_number_of_parts(this->dvdnav, tt, &num_part); dvdnav_get_angle_info(this->dvdnav, &cur_angle, &num_angle); if(num_angle > 1) { - snprintf(ui_title, MAX_STR_LEN, - "Title %i, Chapter %i, Angle %i of %i", - tt,pr,cur_angle, num_angle); + data.str_len = snprintf(data.str, sizeof(data.str), + "Title %i, Chapter %i, Angle %i of %i", + tt,pr,cur_angle, num_angle); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_NUMBER,cur_angle); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_COUNT,num_angle); } else { - snprintf(ui_title, MAX_STR_LEN, - "Title %i, Chapter %i", - tt,pr); + data.str_len = snprintf(data.str, sizeof(data.str), + "Title %i, Chapter %i", + tt,pr); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_NUMBER,0); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_COUNT,0); } @@ -403,9 +411,9 @@ static int update_title_display(dvd_input_plugin_t *this) { _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_CHAPTER_NUMBER,pr); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_CHAPTER_COUNT,num_part); } else if (tt == 0 && dvdnav_menu_table[pr]) { - snprintf(ui_title, MAX_STR_LEN, - "DVD %s Menu", - dvdnav_menu_table[pr]); + data.str_len = snprintf(data.str, sizeof(data.str), + "DVD %s Menu", + dvdnav_menu_table[pr]); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_TITLE_NUMBER,tt); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_TITLE_COUNT,num_tt); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_CHAPTER_NUMBER,0); @@ -413,7 +421,8 @@ static int update_title_display(dvd_input_plugin_t *this) { _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_NUMBER,0); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_COUNT,0); } else { - strcpy(ui_title, "DVD Menu"); + strcpy(data.str, "DVD Menu"); + data.str_len = strlen(data.str); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_TITLE_NUMBER,0); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_TITLE_COUNT,num_tt); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_CHAPTER_NUMBER,0); @@ -421,22 +430,15 @@ static int update_title_display(dvd_input_plugin_t *this) { _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_NUMBER,0); _x_stream_info_set(this->stream,XINE_STREAM_INFO_DVD_ANGLE_COUNT,0); } - ui_str_length = strlen(ui_title); - + if (this->dvd_name && this->dvd_name[0] && - (ui_str_length + strlen(this->dvd_name) < MAX_STR_LEN)) { - snprintf(ui_title+ui_str_length, MAX_STR_LEN - ui_str_length, - ", %s", this->dvd_name); + (data.str_len + strlen(this->dvd_name) < sizeof(data.str))) { + data.str_len += snprintf(data.str+data.str_len, sizeof(data.str) - data.str_len, + ", %s", this->dvd_name); } #ifdef INPUT_DEBUG - printf("input_dvd: Changing title to read '%s'\n", ui_title); + printf("input_dvd: Changing title to read '%s'\n", data.str); #endif - uevent.type = XINE_EVENT_UI_SET_TITLE; - uevent.stream = this->stream; - uevent.data = &data; - uevent.data_length = sizeof(data);; - memcpy(data.str, ui_title, strlen(ui_title) + 1); - data.str_len = strlen(ui_title) + 1; xine_event_send(this->stream, &uevent); return 1; @@ -444,16 +446,16 @@ static int update_title_display(dvd_input_plugin_t *this) { static void dvd_plugin_dispose (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; - + trace_print("Called\n"); - + if (this->event_queue) xine_event_dispose_queue (this->event_queue); - + ((dvd_input_class_t *)this_gen->input_class)->ip = NULL; if (this->dvdnav) dvdnav_close(this->dvdnav); - + pthread_mutex_lock(&this->buf_mutex); if (this->mem_stack) { /* raise the freeing flag, so that the plugin will be freed as soon @@ -487,11 +489,11 @@ static void dvd_build_mrl_list(dvd_input_plugin_t *this) { this->class->num_mrls = 0; } - if (dvdnav_open(&(this->dvdnav), + if (dvdnav_open(&(this->dvdnav), this->dvd_device) == DVDNAV_STATUS_ERR) { return; } - + this->current_dvd_device = this->dvd_device; this->opened = 1; @@ -513,7 +515,7 @@ static void dvd_build_mrl_list(dvd_input_plugin_t *this) { /* allocate enough memory for: * - a list of pointers to mrls sizeof(xine_mrl_t *) * (num_mrls+1) - * - possible alignment of the mrl array + * - possible alignment of the mrl array * - an array of mrl structures sizeof(xine_mrl_t) * num_mrls * - enough chars for every filename sizeof(char)*25 * num_mrls * - "dvd:/000000.000000\0" = 25 chars @@ -521,7 +523,7 @@ static void dvd_build_mrl_list(dvd_input_plugin_t *this) { if ((this->mrls = (xine_mrl_t **) malloc(sizeof(xine_mrl_t *) + num_mrls * (sizeof(xine_mrl_t*) + sizeof(xine_mrl_t) + 25*sizeof(char)) + xine_mrl_alignment))) { - + /* the first mrl struct comes after the pointer list */ xine_mrl_t *mrl = PTR_ALIGN(&this->mrls[num_mrls+1], xine_mrl_alignment); @@ -554,7 +556,7 @@ static void dvd_build_mrl_list(dvd_input_plugin_t *this) { static void dvd_plugin_free_buffer(buf_element_t *buf) { dvd_input_plugin_t *this = buf->source; - + pthread_mutex_lock(&this->buf_mutex); /* give this buffer back to libdvdnav */ dvdnav_free_cache_block(this->dvdnav, buf->mem); @@ -574,7 +576,7 @@ static void dvd_plugin_free_buffer(buf_element_t *buf) { } } -static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, +static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t nlen) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; buf_element_t *buf; @@ -595,7 +597,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, while(!finished) { dvd_handle_events(this); - + if (block != buf->mem) { /* if we already have a dvdnav cache block, give it back first */ dvdnav_free_cache_block(this->dvdnav, block); @@ -613,17 +615,17 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, } switch(event) { - case DVDNAV_BLOCK_OK: + case DVDNAV_BLOCK_OK: { buf->content = block; buf->type = BUF_DEMUX_BLOCK; /* Make sure we don't think we are still paused */ this->pause_timer = 0; - + /* we got a block, so we might be seekable here */ this->seekable = 1; - + finished = 1; } break; @@ -635,7 +637,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, (dvdnav_still_event_t*)block; buf->type = BUF_CONTROL_NOP; finished = 1; - + /* stills are not seekable */ this->seekable = 0; @@ -656,7 +658,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, xine_usec_sleep(50000); break; } - if ((this->pause_timer != 0xff) && + if ((this->pause_timer != 0xff) && (time(NULL) >= this->pause_end_time)) { this->pause_timer = 0; this->pause_end_time = 0; @@ -676,7 +678,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, break; case DVDNAV_SPU_STREAM_CHANGE: { - dvdnav_spu_stream_change_event_t *stream_event = + dvdnav_spu_stream_change_event_t *stream_event = (dvdnav_spu_stream_change_event_t*) (block); buf->content = block; buf->type = BUF_CONTROL_SPU_CHANNEL; @@ -694,7 +696,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, break; case DVDNAV_AUDIO_STREAM_CHANGE: { - dvdnav_audio_stream_change_event_t *stream_event = + dvdnav_audio_stream_change_event_t *stream_event = (dvdnav_audio_stream_change_event_t*) (block); buf->content = block; buf->type = BUF_CONTROL_AUDIO_CHANNEL; @@ -728,7 +730,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, break; case DVDNAV_CELL_CHANGE: { - dvdnav_cell_change_event_t *cell_event = + dvdnav_cell_change_event_t *cell_event = (dvdnav_cell_change_event_t*) (block); xine_event_t event; @@ -738,14 +740,14 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, event.data = NULL; event.data_length = 0; xine_event_send(this->stream, &event); - + if( !update_title_display(this) ) { if (buf->mem != block) dvdnav_free_cache_block(this->dvdnav, block); buf->free_buffer(buf); /* return NULL to indicate end of stream */ return NULL; } - + this->pg_length = cell_event->pg_length; this->pgc_length = cell_event->pgc_length; this->cell_start = cell_event->cell_start; @@ -797,7 +799,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, break; } } - + if (block != buf->mem) { /* we have received a buffer from the libdvdnav cache, store all * necessary values to reconstruct xine's buffer and modify it according to @@ -833,7 +835,7 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, } pthread_mutex_unlock(&this->buf_mutex); } - + if (this->pg_length && this->pgc_length) { switch (((dvd_input_class_t *)this->input_plugin.input_class)->seek_mode) { case 0: /* PGC based seeking */ @@ -846,13 +848,16 @@ static buf_element_t *dvd_plugin_read_block (input_plugin_t *this_gen, break; } } - + return buf; } static off_t dvd_plugin_read (input_plugin_t *this_gen, char *ch_buf, off_t len) { /* dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; */ + if (len < 4) + return -1; + /* FIXME: Tricking the demux_mpeg_block plugin */ ch_buf[0] = 0; ch_buf[1] = 0; @@ -860,7 +865,7 @@ static off_t dvd_plugin_read (input_plugin_t *this_gen, char *ch_buf, off_t len) ch_buf[3] = 0xba; return 1; } - + static off_t dvd_plugin_get_current_pos (input_plugin_t *this_gen){ dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; uint32_t pos=0; @@ -877,28 +882,28 @@ static off_t dvd_plugin_get_current_pos (input_plugin_t *this_gen){ static off_t dvd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; - + trace_print("Called\n"); if(!this || !this->dvdnav) { return -1; } - + dvdnav_sector_search(this->dvdnav, offset / DVD_BLOCK_SIZE , origin); return dvd_plugin_get_current_pos(this_gen); } static off_t dvd_plugin_seek_time (input_plugin_t *this_gen, int time_offset, int origin) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; - + trace_print("Called\n"); - + if(!this || !this->dvdnav || origin != SEEK_SET) { return -1; } - + dvdnav_time_search(this->dvdnav, time_offset * 90); - + return dvd_plugin_get_current_pos(this_gen); } @@ -907,7 +912,7 @@ static off_t dvd_plugin_get_length (input_plugin_t *this_gen) { uint32_t pos=0; uint32_t length=1; dvdnav_status_t result; - + trace_print("Called\n"); if(!this || !this->dvdnav) { @@ -925,7 +930,7 @@ static uint32_t dvd_plugin_get_blocksize (input_plugin_t *this_gen) { static const char* dvd_plugin_get_mrl (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; - + trace_print("Called\n"); return this->mrl; @@ -937,17 +942,17 @@ static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode) { if (!this || !this->stream || _x_stream_info_get(this->stream,XINE_STREAM_INFO_IGNORE_SPU)) return; - + if (!this->stream->spu_decoder_plugin || this->stream->spu_decoder_streamtype != ((BUF_SPU_DVD >> 16) & 0xFF)) { /* the proper SPU decoder has not been initialized yet, * so we send a dummy buffer to trigger this */ buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); - + buf->size = 0; buf->type = BUF_SPU_DVD; this->stream->video_fifo->insert(this->stream->video_fifo, buf); - + while (!this->stream->spu_decoder_plugin || this->stream->spu_decoder_streamtype != ((BUF_SPU_DVD >> 16) & 0xFF)) xine_usec_sleep(50000); @@ -956,7 +961,7 @@ static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode) { dvdnav_get_current_highlight(this->dvdnav, &button); if (button == this->buttonN && (mode == 0) ) return; - + this->buttonN = button; /* Avoid duplicate sending of button info */ #ifdef INPUT_DEBUG @@ -971,11 +976,11 @@ static void xine_dvd_send_button_update(dvd_input_plugin_t *this, int mode) { static void dvd_handle_events(dvd_input_plugin_t *this) { dvd_input_class_t *class = (dvd_input_class_t*)this->input_plugin.input_class; - config_values_t *config = class->config; /* Pointer to XineRC config file */ + config_values_t *config = class->config; /* Pointer to XineRC config file */ xine_event_t *event; while ((event = xine_event_get(this->event_queue))) { - + if(!this->dvdnav) { xine_event_free(event); return; @@ -1049,7 +1054,7 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { } } break; - case XINE_EVENT_INPUT_ANGLE_NEXT: + case XINE_EVENT_INPUT_ANGLE_NEXT: { int num = 0, current = 0; dvdnav_get_angle_info(this->dvdnav, ¤t, &num); @@ -1066,7 +1071,7 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { update_title_display(this); } break; - case XINE_EVENT_INPUT_ANGLE_PREVIOUS: + case XINE_EVENT_INPUT_ANGLE_PREVIOUS: { int num = 0, current = 0; dvdnav_get_angle_info(this->dvdnav, ¤t, &num); @@ -1095,7 +1100,7 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { } } break; - case XINE_EVENT_INPUT_MOUSE_BUTTON: + case XINE_EVENT_INPUT_MOUSE_BUTTON: { pci_t nav_pci; if(!this->stream || !this->stream->spu_decoder_plugin) { @@ -1103,7 +1108,7 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { } if (this->stream->spu_decoder_plugin->get_interact_info(this->stream->spu_decoder_plugin, &nav_pci) ) { xine_input_data_t *input = event->data; - if((input->button == 1) && dvdnav_mouse_activate(this->dvdnav, + if((input->button == 1) && dvdnav_mouse_activate(this->dvdnav, &nav_pci, input->x, input->y) == DVDNAV_STATUS_OK) { xine_dvd_send_button_update(this, 1); @@ -1129,7 +1134,7 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { dvdnav_button_select(this->dvdnav, &nav_pci, *but); } break; - case XINE_EVENT_INPUT_MOUSE_MOVE: + case XINE_EVENT_INPUT_MOUSE_MOVE: { pci_t nav_pci; if(!this->stream || !this->stream->spu_decoder_plugin) @@ -1139,19 +1144,19 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { /* printf("input_dvd: Mouse move (x,y) = (%i,%i)\n", input->x, input->y); */ if(dvdnav_mouse_select(this->dvdnav, &nav_pci, input->x, input->y) == DVDNAV_STATUS_OK) { int32_t button; - + dvdnav_get_current_highlight(this->dvdnav, &button); - + if(this->mouse_buttonN != button) { this->mouse_buttonN = button; send_mouse_enter_leave_event(this, 1); } - + } else { if(this->mouse_in) send_mouse_enter_leave_event(this, 0); - + } } } @@ -1231,14 +1236,14 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { case XINE_EVENT_INPUT_NUMBER_1: this->typed_buttonN++; case XINE_EVENT_INPUT_NUMBER_0: - { + { pci_t nav_pci; if(!this->stream || !this->stream->spu_decoder_plugin) return; if (this->stream->spu_decoder_plugin->get_interact_info(this->stream->spu_decoder_plugin, &nav_pci) ) { if (dvdnav_button_select_and_activate(this->dvdnav, &nav_pci, this->typed_buttonN) == DVDNAV_STATUS_OK) { xine_dvd_send_button_update(this, 1); - + if(this->mouse_in) send_mouse_enter_leave_event(this, 0); } @@ -1250,23 +1255,23 @@ static void dvd_handle_events(dvd_input_plugin_t *this) { case XINE_EVENT_INPUT_NUMBER_10_ADD: this->typed_buttonN += 10; } - + xine_event_free(event); } return; } -static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, +static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { - dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; - + dvd_input_plugin_t *this = (dvd_input_plugin_t *) this_gen; + switch(data_type) { case INPUT_OPTIONAL_DATA_AUDIOLANG: { uint16_t lang; int channel = *((int *)data); int8_t dvd_channel; - + /* Be paranoid */ if(this && this->stream && this->dvdnav) { @@ -1277,7 +1282,7 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, else return INPUT_OPTIONAL_UNSUPPORTED; } - + if (channel == -1) dvd_channel = dvdnav_get_audio_logical_stream(this->dvdnav, this->stream->audio_channel_auto); else @@ -1285,7 +1290,7 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, if(dvd_channel != -1) { lang = dvdnav_audio_stream_to_lang(this->dvdnav, dvd_channel); - + if(lang != 0xffff) sprintf(data, " %c%c", lang >> 8, lang & 0xff); /* TODO: provide long version in XINE_META_INFO_FULL_LANG */ @@ -1298,7 +1303,7 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, return INPUT_OPTIONAL_SUCCESS; } } - } + } return INPUT_OPTIONAL_UNSUPPORTED; } break; @@ -1308,12 +1313,12 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, uint16_t lang; int channel = *((int *)data); int8_t dvd_channel; - + /* Be paranoid */ if(this && this->stream && this->dvdnav) { if(!(dvdnav_is_domain_vts(this->dvdnav))) { - sprintf(data, "%s", "menu"); + strcpy(data, "menu"); if (channel <= 0) return INPUT_OPTIONAL_SUCCESS; else @@ -1336,7 +1341,7 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, return INPUT_OPTIONAL_SUCCESS; } else { if(channel == -1) { - sprintf(data, "%s", "none"); + strcpy(data, "none"); return INPUT_OPTIONAL_SUCCESS; } } @@ -1344,14 +1349,14 @@ static int dvd_plugin_get_optional_data (input_plugin_t *this_gen, return INPUT_OPTIONAL_UNSUPPORTED; } break; - + } - + return INPUT_OPTIONAL_UNSUPPORTED; } #ifdef __sun -/* +/* * Check the environment, if we're running under sun's * vold/rmmount control. */ @@ -1369,10 +1374,7 @@ check_solaris_vold_device(dvd_input_class_t *this) (volume_action = getenv("VOLUME_ACTION")) != NULL && strcmp(volume_action, "insert") == 0) { - device = malloc(strlen(volume_device) + strlen(volume_name) + 2); - if (device == NULL) - return; - sprintf(device, "%s/%s", volume_device, volume_name); + asprintf(&device, "%s/%s", volume_device, volume_name); if (stat(device, &stb) != 0 || !S_ISCHR(stb.st_mode)) { free(device); return; @@ -1386,7 +1388,7 @@ check_solaris_vold_device(dvd_input_class_t *this) static int dvd_parse_try_open(dvd_input_plugin_t *this, const char *locator) { const char *intended_dvd_device; - + /* FIXME: we temporarily special-case "dvd:/" for compatibility; * actually "dvd:/" should play a DVD image stored in /, but for * now we have it use the default device */ @@ -1408,7 +1410,7 @@ static int dvd_parse_try_open(dvd_input_plugin_t *this, const char *locator) xine_setenv("DVDCSS_RAW_DEVICE", raw_device.str_value, 1); intended_dvd_device = class->dvd_device; } - + /* attempt to open DVD */ if (this->opened) { if (intended_dvd_device == this->current_dvd_device) { @@ -1418,7 +1420,7 @@ static int dvd_parse_try_open(dvd_input_plugin_t *this, const char *locator) /* Changing DVD device */ dvdnav_close(this->dvdnav); this->dvdnav = NULL; - this->opened = 0; + this->opened = 0; } } if (!this->opened) { @@ -1427,14 +1429,14 @@ static int dvd_parse_try_open(dvd_input_plugin_t *this, const char *locator) this->current_dvd_device = intended_dvd_device; } } - + return this->opened; } static int dvd_parse_mrl(dvd_input_plugin_t *this, char **locator, char **title_part) { *title_part = NULL; - + if (dvd_parse_try_open(this, *locator)) { return MODE_NAVIGATE; } else { @@ -1459,7 +1461,7 @@ static int dvd_parse_mrl(dvd_input_plugin_t *this, char **locator, char **title_ *locator = ""; } else return MODE_FAIL; - + if (dvd_parse_try_open(this, *locator)) if (strlen(*title_part)) return MODE_TITLE; @@ -1473,25 +1475,25 @@ static int dvd_parse_mrl(dvd_input_plugin_t *this, char **locator, char **title_ static int dvd_plugin_open (input_plugin_t *this_gen) { dvd_input_plugin_t *this = (dvd_input_plugin_t*)this_gen; dvd_input_class_t *class = (dvd_input_class_t*)this_gen->input_class; - + char *locator, *locator_orig; char *title_part; xine_event_t event; xine_cfg_entry_t region_entry, lang_entry, cfg_entry; - + trace_print("Called\n"); /* we already checked the "dvd:/" MRL before */ locator_orig = locator = strdup (this->mrl + (sizeof("dvd:") - 1)); /* FIXME: call a generic xine-lib MRL parser here to pre-parse - * the MRL for ?title=<title>&part=<part> stuff and to expand + * the MRL for ?title=<title>&part=<part> stuff and to expand * escaped characters properly */ _x_mrl_unescape (locator); this->mode = dvd_parse_mrl(this, &locator, &title_part); - + if (this->mode == MODE_FAIL) { /* opening failed and we have nothing left to try */ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("input_dvd: Error opening DVD device\n")); @@ -1505,26 +1507,26 @@ static int dvd_plugin_open (input_plugin_t *this_gen) { dvdnav_get_title_string(this->dvdnav, &this->dvd_name); if(this->dvd_name) _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, this->dvd_name); - + /* Set region code */ - if (xine_config_lookup_entry (this->stream->xine, "media.dvd.region", - ®ion_entry)) + if (xine_config_lookup_entry (this->stream->xine, "media.dvd.region", + ®ion_entry)) region_changed_cb (class, ®ion_entry); - + /* Set languages */ if (xine_config_lookup_entry (this->stream->xine, "media.dvd.language", - &lang_entry)) + &lang_entry)) language_changed_cb (class, &lang_entry); - + /* Set cache usage */ if (xine_config_lookup_entry(this->stream->xine, "media.dvd.readahead", &cfg_entry)) read_ahead_cb(class, &cfg_entry); - + /* Set seek mode */ if (xine_config_lookup_entry(this->stream->xine, "media.dvd.seek_behaviour", &cfg_entry)) - seek_mode_cb(class, &cfg_entry); + seek_mode_cb(class, &cfg_entry); /* Set single chapter mode */ if (xine_config_lookup_entry(this->stream->xine, "media.dvd.play_single_chapter", @@ -1535,7 +1537,7 @@ static int dvd_plugin_open (input_plugin_t *this_gen) { char *delimiter; int tt, pr; int titles, parts; - + /* a <title>.<part> was specified -> resume parsing */ /* See if there is a period. */ @@ -1545,7 +1547,7 @@ static int dvd_plugin_open (input_plugin_t *this_gen) { tt = strtol(title_part, NULL, 10); dvdnav_get_number_of_titles(this->dvdnav, &titles); if((tt < 0) || (tt > titles)) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_dvd: Title %i is out of range (1 to %i).\n", tt, titles); dvdnav_close(this->dvdnav); this->dvdnav = NULL; @@ -1559,7 +1561,7 @@ static int dvd_plugin_open (input_plugin_t *this_gen) { pr = strtol(delimiter+1, NULL, 10); dvdnav_get_number_of_parts(this->dvdnav, tt, &parts); if ((pr < 0) || (pr > parts)) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_dvd: Part %i is out of range (1 to %i).\n", pr, parts); dvdnav_close(this->dvdnav); this->dvdnav = NULL; @@ -1620,19 +1622,19 @@ static input_plugin_t *dvd_class_get_instance (input_class_t *class_gen, xine_st static char *handled_mrl = "dvd:/"; trace_print("Called\n"); - + /* Check we can handle this MRL */ if (strncasecmp (data, handled_mrl, strlen(handled_mrl) ) != 0) return NULL; - this = (dvd_input_plugin_t *) xine_xmalloc (sizeof (dvd_input_plugin_t)); + this = calloc(1, sizeof (dvd_input_plugin_t)); if (!this) { return NULL; } this->mem_stack = 0; this->mem_stack_max = 1024; - this->mem = xine_xmalloc(sizeof(unsigned char *) * this->mem_stack_max); + this->mem = calloc(this->mem_stack_max, sizeof(unsigned char *)); if (!this->mem) { free(this); return NULL; @@ -1670,9 +1672,9 @@ static input_plugin_t *dvd_class_get_instance (input_class_t *class_gen, xine_st pthread_mutex_init(&this->buf_mutex, NULL); this->freeing = 0; - + this->event_queue = xine_event_new_queue (this->stream); - + /* config callbacks may react now */ class->ip = this; @@ -1693,7 +1695,7 @@ static const char *dvd_class_get_identifier (input_class_t *this_gen) { /* FIXME: adapt to new api. */ #if 0 -static xine_mrl_t **dvd_class_get_dir (input_class_t *this_gen, +static xine_mrl_t **dvd_class_get_dir (input_class_t *this_gen, const char *filename, int *nFiles) { dvd_input_class_t *this = (dvd_input_class_t*)this_gen; @@ -1710,11 +1712,11 @@ static xine_mrl_t **dvd_class_get_dir (input_class_t *this_gen, } #endif -static char **dvd_class_get_autoplay_list (input_class_t *this_gen, +static char **dvd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) { dvd_input_class_t *this = (dvd_input_class_t *) this_gen; - trace_print("get_autoplay_list entered\n"); + trace_print("get_autoplay_list entered\n"); this->filelist[0] = "dvd:/"; this->filelist[1] = NULL; @@ -1758,10 +1760,10 @@ static void *init_class (xine_t *xine, void *data) { printf("input_dvd.c: config = %p\n", config); #endif - this = (dvd_input_class_t *) xine_xmalloc (sizeof (dvd_input_class_t)); + this = (dvd_input_class_t *) calloc(1, sizeof (dvd_input_class_t)); if (!this) return NULL; - + this->input_class.get_instance = dvd_class_get_instance; this->input_class.get_identifier = dvd_class_get_identifier; this->input_class.get_description = dvd_class_get_description; @@ -1772,7 +1774,7 @@ static void *init_class (xine_t *xine, void *data) { this->input_class.get_autoplay_list = dvd_class_get_autoplay_list; this->input_class.dispose = dvd_class_dispose; this->input_class.eject_media = dvd_class_eject_media; - + this->config = config; this->xine = xine; @@ -1797,7 +1799,7 @@ static void *init_class (xine_t *xine, void *data) { static const char *decrypt_modes[] = { "key", "disc", "title", NULL }; char *css_cache_default, *css_cache; int mode; - + raw_device = config->register_filename(config, "media.dvd.raw_device", RDVD_PATH, XINE_CONFIG_STRING_IS_DEVICE_NAME, _("raw device set up for DVD access"), @@ -1812,16 +1814,15 @@ static void *init_class (xine_t *xine, void *data) { "(man raw) for further information."), 10, NULL, NULL); if (raw_device) xine_setenv("DVDCSS_RAW_DEVICE", raw_device, 0); - + mode = config->register_enum(config, "media.dvd.css_decryption_method", 0, decrypt_modes, _("CSS decryption method"), _("Selects the decryption method libdvdcss will use to descramble " "copy protected DVDs. Try the various methods, if you have problems " "playing scrambled DVDs."), 20, NULL, NULL); xine_setenv("DVDCSS_METHOD", decrypt_modes[mode], 0); - - css_cache_default = (char *)malloc(strlen(xine_get_homedir()) + 10); - sprintf(css_cache_default, "%s/.dvdcss/", xine_get_homedir()); + + asprintf(&css_cache_default, "%s/.dvdcss/", xine_get_homedir()); css_cache = config->register_filename(config, "media.dvd.css_cache_path", css_cache_default, XINE_CONFIG_STRING_IS_DIRECTORY_NAME, _("path to the title key cache"), _("Since cracking the copy protection of scrambled DVDs can " @@ -1834,7 +1835,7 @@ static void *init_class (xine_t *xine, void *data) { if (strlen(css_cache) > 0) xine_setenv("DVDCSS_CACHE", css_cache, 0); free(css_cache_default); - + if(xine->verbosity > XINE_VERBOSITY_NONE) xine_setenv("DVDCSS_VERBOSE", "2", 0); @@ -1843,7 +1844,7 @@ static void *init_class (xine_t *xine, void *data) { dlclose(dvdcss); } - + config->register_num(config, "media.dvd.region", 1, _("region the DVD player claims to be in (1 to 8)"), @@ -1915,7 +1916,7 @@ static void *init_class (xine_t *xine, void *data) { const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "DVD", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_file.c b/src/input/input_file.c index f81103dcd..208a5420e 100644 --- a/src/input/input_file.c +++ b/src/input/input_file.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -63,18 +63,18 @@ typedef struct { xine_t *xine; config_values_t *config; - + char *origin_path; int show_hidden_files; int mrls_allocated_entries; xine_mrl_t **mrls; - + } file_input_class_t; typedef struct { input_plugin_t input_plugin; - + xine_stream_t *stream; int fh; @@ -145,15 +145,18 @@ static int check_mmap_file(file_input_plugin_t *this) { static off_t file_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { file_input_plugin_t *this = (file_input_plugin_t *) this_gen; + if (len < 0) + return -1; + #ifdef HAVE_MMAP if ( check_mmap_file(this) ) { off_t l = len; if ( (this->mmap_curr + len) > (this->mmap_base + this->mmap_len) ) l = (this->mmap_base + this->mmap_len) - this->mmap_curr; - + memcpy(buf, this->mmap_curr, l); this->mmap_curr += l; - + return l; } #endif @@ -166,6 +169,13 @@ static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buf file_input_plugin_t *this = (file_input_plugin_t *) this_gen; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->type = BUF_DEMUX_BLOCK; #ifdef HAVE_MMAP @@ -181,7 +191,7 @@ static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buf /* FIXME: it's completely illegal to free buffer->mem here * - buffer->mem has not been allocated by malloc - * - demuxers expect buffer->mem != NULL + * - demuxers expect buffer->mem != NULL */ /* free(buf->mem); buf->mem = NULL; */ @@ -190,7 +200,7 @@ static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buf #endif { off_t num_bytes, total_bytes = 0; - + buf->content = buf->mem; while (total_bytes < todo) { @@ -208,11 +218,11 @@ static buf_element_t *file_plugin_read_block (input_plugin_t *this_gen, fifo_buf } total_bytes += num_bytes; } - + if( buf != NULL ) buf->size = total_bytes; } - + return buf; } @@ -286,7 +296,7 @@ static uint32_t file_plugin_get_blocksize (input_plugin_t *this_gen) { */ static int is_a_dir(char *filepathname) { struct stat pstat; - + stat(filepathname, &pstat); return (S_ISDIR(pstat.st_mode)); @@ -298,9 +308,9 @@ static const char* file_plugin_get_mrl (input_plugin_t *this_gen) { return this->mrl; } -static int file_plugin_get_optional_data (input_plugin_t *this_gen, +static int file_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { - + return INPUT_OPTIONAL_UNSUPPORTED; } @@ -407,7 +417,7 @@ static int file_plugin_open (input_plugin_t *this_gen ) { return 1; } -static input_plugin_t *file_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, +static input_plugin_t *file_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *data) { /* file_input_class_t *cls = (file_input_class_t *) cls_gen; */ @@ -421,7 +431,7 @@ static input_plugin_t *file_class_get_instance (input_class_t *cls_gen, xine_str return NULL; } - this = (file_input_plugin_t *) xine_xmalloc (sizeof (file_input_plugin_t)); + this = (file_input_plugin_t *) calloc(1, sizeof (file_input_plugin_t)); this->stream = stream; this->mrl = mrl; this->fh = -1; @@ -474,12 +484,12 @@ static input_plugin_t *file_class_get_instance (input_class_t *cls_gen, xine_str */ static void hidden_bool_cb(void *data, xine_cfg_entry_t *cfg) { file_input_class_t *this = (file_input_class_t *) data; - + this->show_hidden_files = cfg->num_value; } static void origin_change_cb(void *data, xine_cfg_entry_t *cfg) { file_input_class_t *this = (file_input_class_t *) data; - + this->origin_path = cfg->str_value; } @@ -530,20 +540,20 @@ static int _strverscmp(const char *s1, const char *s2) { c2 = *p2++; state |= (c1 == '0') + (ISDIGIT(c1) != 0); } - + state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT(c2) != 0))]; - + switch(state) { case CMP: return diff; - + case LEN: while(ISDIGIT(*p1++)) if(!ISDIGIT(*p2++)) return 1; - + return ISDIGIT(*p2) ? -1 : diff; - + default: return state; } @@ -573,11 +583,11 @@ static uint32_t get_file_type(char *filepathname, char *origin, xine_t *xine) { return file_type; } } - + file_type |= mrl_file; - + mode = pstat.st_mode; - + if(S_ISLNK(mode)) file_type |= mrl_file_symlink; else if(S_ISDIR(mode)) @@ -597,10 +607,10 @@ static uint32_t get_file_type(char *filepathname, char *origin, xine_t *xine) { if(mode & S_IXUGO) file_type |= mrl_file_exec; } - + if(filepathname[strlen(filepathname) - 1] == '~') file_type |= mrl_file_backup; - + return file_type; } @@ -628,7 +638,7 @@ static const char *file_class_get_identifier (input_class_t *this_gen) { return "file"; } -static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, +static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, const char *filename, int *nFiles) { /* FIXME: this code needs cleanup badly */ @@ -650,7 +660,7 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, *nFiles = 0; memset(current_dir, 0, sizeof(current_dir)); - /* + /* * No origin location, so got the content of the current directory */ if(!filename) { @@ -658,7 +668,7 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, } else { snprintf(current_dir, XINE_PATH_MAX, "%s", filename); - + /* Remove exceed '/' */ while((current_dir[strlen(current_dir) - 1] == '/') && strlen(current_dir) > 1) current_dir[strlen(current_dir) - 1] = '\0'; @@ -666,14 +676,14 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, /* Store new origin path */ try_again_from_home: - + this->config->update_string(this->config, "media.files.origin_path", current_dir); if(strcasecmp(current_dir, "/")) snprintf(current_dir_slashed, sizeof(current_dir_slashed), "%s/", current_dir); else sprintf(current_dir_slashed, "/"); - + /* * Ooch! */ @@ -688,31 +698,28 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, return NULL; } - - dir_files = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t) * MAXFILES); - hide_files = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t) * MAXFILES); - norm_files = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t) * MAXFILES); - + + dir_files = (xine_mrl_t *) calloc(MAXFILES, sizeof(xine_mrl_t)); + hide_files = (xine_mrl_t *) calloc(MAXFILES, sizeof(xine_mrl_t)); + norm_files = (xine_mrl_t *) calloc(MAXFILES, sizeof(xine_mrl_t)); + while((pdirent = readdir(pdir)) != NULL) { - + memset(fullfilename, 0, sizeof(fullfilename)); snprintf(fullfilename, sizeof(fullfilename), "%s/%s", current_dir, pdirent->d_name); - + if(is_a_dir(fullfilename)) { - + /* if user don't want to see hidden files, ignore them */ - if(this->show_hidden_files == 0 && + if(this->show_hidden_files == 0 && ((strlen(pdirent->d_name) > 1) && (pdirent->d_name[0] == '.' && pdirent->d_name[1] != '.'))) { ; } else { - - dir_files[num_dir_files].mrl = (char *) - xine_xmalloc(strlen(current_dir_slashed) + 1 + strlen(pdirent->d_name) + 1); - + dir_files[num_dir_files].origin = strdup(current_dir); - sprintf(dir_files[num_dir_files].mrl, "%s%s", + asprintf(&(dir_files[num_dir_files].mrl), "%s%s", current_dir_slashed, pdirent->d_name); dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = get_file_type(fullfilename, current_dir, this->xine); @@ -722,20 +729,21 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, if(dir_files[num_dir_files].type & mrl_file_symlink) { char linkbuf[XINE_PATH_MAX + XINE_NAME_MAX + 1]; int linksize; - + memset(linkbuf, 0, sizeof(linkbuf)); linksize = readlink(fullfilename, linkbuf, XINE_PATH_MAX + XINE_NAME_MAX); - - if(linksize < 0) + + if(linksize < 0) xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_file: readlink() failed: %s\n", strerror(errno)); else { - dir_files[num_dir_files].link = (char *) xine_xmalloc(linksize + 1); - strncpy(dir_files[num_dir_files].link, linkbuf, linksize); + dir_files[num_dir_files].link = + strndup(linkbuf, linksize); + dir_files[num_dir_files].type |= get_file_type(dir_files[num_dir_files].link, current_dir, this->xine); } } - + num_dir_files++; } @@ -746,80 +754,72 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, /* if user don't want to see hidden files, ignore them */ if(this->show_hidden_files) { - hide_files[num_hide_files].mrl = (char *) - xine_xmalloc(strlen(current_dir_slashed) + 1 + strlen(pdirent->d_name) + 1); - hide_files[num_hide_files].origin = strdup(current_dir); - sprintf(hide_files[num_hide_files].mrl, "%s%s", + asprintf(&(hide_files[num_hide_files].mrl), "%s%s", current_dir_slashed, pdirent->d_name); hide_files[num_hide_files].link = NULL; hide_files[num_hide_files].type = get_file_type(fullfilename, current_dir, this->xine); hide_files[num_hide_files].size = get_file_size(fullfilename, current_dir); - + /* The file is a link, follow it */ if(hide_files[num_hide_files].type & mrl_file_symlink) { char linkbuf[XINE_PATH_MAX + XINE_NAME_MAX + 1]; int linksize; - + memset(linkbuf, 0, sizeof(linkbuf)); linksize = readlink(fullfilename, linkbuf, XINE_PATH_MAX + XINE_NAME_MAX); - + if(linksize < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_file: readlink() failed: %s\n", strerror(errno)); } else { - hide_files[num_hide_files].link = (char *) - xine_xmalloc(linksize + 1); - strncpy(hide_files[num_hide_files].link, linkbuf, linksize); + hide_files[num_hide_files].link = + strndup(linkbuf, linksize); hide_files[num_hide_files].type |= get_file_type(hide_files[num_hide_files].link, current_dir, this->xine); } } - + num_hide_files++; } } /* So a *normal* one. */ else { - norm_files[num_norm_files].mrl = (char *) - xine_xmalloc(strlen(current_dir_slashed) + 1 + strlen(pdirent->d_name) + 1); - norm_files[num_norm_files].origin = strdup(current_dir); - sprintf(norm_files[num_norm_files].mrl, "%s%s", + asprintf(&(norm_files[num_norm_files].mrl), "%s%s", current_dir_slashed, pdirent->d_name); norm_files[num_norm_files].link = NULL; norm_files[num_norm_files].type = get_file_type(fullfilename, current_dir, this->xine); norm_files[num_norm_files].size = get_file_size(fullfilename, current_dir); - + /* The file is a link, follow it */ if(norm_files[num_norm_files].type & mrl_file_symlink) { char linkbuf[XINE_PATH_MAX + XINE_NAME_MAX + 1]; int linksize; - + memset(linkbuf, 0, sizeof(linkbuf)); linksize = readlink(fullfilename, linkbuf, XINE_PATH_MAX + XINE_NAME_MAX); - + if(linksize < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_file: readlink() failed: %s\n", strerror(errno)); } else { - norm_files[num_norm_files].link = (char *) - xine_xmalloc(linksize + 1); - strncpy(norm_files[num_norm_files].link, linkbuf, linksize); + norm_files[num_norm_files].link = + strndup(linkbuf, linksize); norm_files[num_norm_files].type |= get_file_type(norm_files[num_norm_files].link, current_dir, this->xine); } } - + num_norm_files++; } - + num_files++; } - + closedir(pdir); - + /* * Ok, there are some files here, so sort * them then store them into global mrls array. @@ -834,27 +834,27 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, */ if(num_dir_files) qsort(dir_files, num_dir_files, sizeof(xine_mrl_t), func); - + if(num_hide_files) qsort(hide_files, num_hide_files, sizeof(xine_mrl_t), func); - + if(num_norm_files) qsort(norm_files, num_norm_files, sizeof(xine_mrl_t), func); - + /* * Add directories entries */ for(i = 0; i < num_dir_files; i++) { - + if(num_files >= this->mrls_allocated_entries) { ++this->mrls_allocated_entries; this->mrls = realloc(this->mrls, (this->mrls_allocated_entries+1) * sizeof(xine_mrl_t*)); - this->mrls[num_files] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[num_files] = calloc(1, sizeof(xine_mrl_t)); } else memset(this->mrls[num_files], 0, sizeof(xine_mrl_t)); - - MRL_DUPLICATE(&dir_files[i], this->mrls[num_files]); + + MRL_DUPLICATE(&dir_files[i], this->mrls[num_files]); num_files++; } @@ -863,21 +863,21 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, * Add hidden files entries */ for(i = 0; i < num_hide_files; i++) { - + if(num_files >= this->mrls_allocated_entries) { ++this->mrls_allocated_entries; this->mrls = realloc(this->mrls, (this->mrls_allocated_entries+1) * sizeof(xine_mrl_t*)); - this->mrls[num_files] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[num_files] = calloc(1, sizeof(xine_mrl_t)); } else memset(this->mrls[num_files], 0, sizeof(xine_mrl_t)); - - MRL_DUPLICATE(&hide_files[i], this->mrls[num_files]); + + MRL_DUPLICATE(&hide_files[i], this->mrls[num_files]); num_files++; } - - /* + + /* * Add other files entries */ for(i = 0; i < num_norm_files; i++) { @@ -885,29 +885,29 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, if(num_files >= this->mrls_allocated_entries) { ++this->mrls_allocated_entries; this->mrls = realloc(this->mrls, (this->mrls_allocated_entries+1) * sizeof(xine_mrl_t*)); - this->mrls[num_files] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[num_files] = calloc(1, sizeof(xine_mrl_t)); } else memset(this->mrls[num_files], 0, sizeof(xine_mrl_t)); - MRL_DUPLICATE(&norm_files[i], this->mrls[num_files]); + MRL_DUPLICATE(&norm_files[i], this->mrls[num_files]); num_files++; } - + /* Some cleanups before leaving */ for(i = num_dir_files; i == 0; i--) MRL_ZERO(&dir_files[i]); free(dir_files); - + for(i = num_hide_files; i == 0; i--) MRL_ZERO(&hide_files[i]); free(hide_files); - + for(i = num_norm_files; i == 0; i--) MRL_ZERO(&norm_files[i]); free(norm_files); - + } else { free(hide_files); @@ -915,12 +915,12 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, free(norm_files); return NULL; } - + /* * Inform caller about files found number. */ *nFiles = num_files; - + /* * Freeing exceeded mrls if exists. */ @@ -928,7 +928,7 @@ static xine_mrl_t **file_class_get_dir (input_class_t *this_gen, MRL_ZERO(this->mrls[this->mrls_allocated_entries - 1]); free(this->mrls[this->mrls_allocated_entries--]); } - + /* * This is useful to let UI know where it should stops ;-). */ @@ -965,12 +965,12 @@ static void *init_plugin (xine_t *xine, void *data) { file_input_class_t *this; config_values_t *config; - this = (file_input_class_t *) xine_xmalloc (sizeof (file_input_class_t)); + this = (file_input_class_t *) calloc(1, sizeof (file_input_class_t)); this->xine = xine; this->config = xine->config; config = xine->config; - + this->input_class.get_instance = file_class_get_instance; this->input_class.get_identifier = file_class_get_identifier; this->input_class.get_description = file_class_get_description; @@ -979,12 +979,12 @@ static void *init_plugin (xine_t *xine, void *data) { this->input_class.dispose = file_class_dispose; this->input_class.eject_media = NULL; - this->mrls = (xine_mrl_t **) xine_xmalloc(sizeof(xine_mrl_t*)); + this->mrls = (xine_mrl_t **) calloc(1, sizeof(xine_mrl_t*)); this->mrls_allocated_entries = 0; { char current_dir[XINE_PATH_MAX + 1]; - + if(getcwd(current_dir, sizeof(current_dir)) == NULL) strcpy(current_dir, "."); @@ -995,14 +995,14 @@ static void *init_plugin (xine_t *xine, void *data) { "start at this location."), 0, origin_change_cb, (void *) this); } - - this->show_hidden_files = config->register_bool(config, - "media.files.show_hidden_files", + + this->show_hidden_files = config->register_bool(config, + "media.files.show_hidden_files", 0, _("list hidden files"), _("If enabled, the browser to select the file to " "play will also show hidden files."), 10, hidden_bool_cb, (void *) this); - + return this; } @@ -1011,7 +1011,7 @@ static void *init_plugin (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "FILE", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_gnome_vfs.c b/src/input/input_gnome_vfs.c index 0848b9206..cf97074ee 100644 --- a/src/input/input_gnome_vfs.c +++ b/src/input/input_gnome_vfs.c @@ -1,19 +1,19 @@ /* * Copyright (C) 2000-2003 the xine project * 2002 Bastien Nocera <hadess@hadess.net> - * + * * This file is part of totem, - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -121,6 +121,13 @@ gnomevfs_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t total_bytes; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -223,7 +230,7 @@ static const char } static int -gnomevfs_plugin_get_optional_data (input_plugin_t *this_gen, +gnomevfs_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { D ("input_gnomevfs: get optional data, type %08x\n", data_type); diff --git a/src/input/input_http.c b/src/input/input_http.c index af696ca14..35fff8ce0 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -68,31 +68,35 @@ typedef struct { input_plugin_t input_plugin; xine_stream_t *stream; - + int fh; char *mrl; - nbc_t *nbc; + nbc_t *nbc; off_t curpos; off_t contentlength; - + char buf[BUFSIZE]; char proxybuf[BUFSIZE]; char auth[BUFSIZE]; char proxyauth[BUFSIZE]; - + + char *mime_type; + char *proto; char *user; char *password; char *host; int port; char *uri; - + + const char *user_agent; + char preview[MAX_PREVIEW_SIZE]; off_t preview_size; - + /* Last.FM streaming server */ unsigned char is_lastfm; @@ -108,7 +112,7 @@ typedef struct { /* scratch buffer for forward seeking */ char seek_buf[BUFSIZE]; - + } http_input_plugin_t; typedef struct { @@ -136,7 +140,7 @@ static void proxy_host_change_cb (void *this_gen, xine_cfg_entry_t *cfg) { static void proxy_port_change_cb(void *this_gen, xine_cfg_entry_t *cfg) { http_input_class_t *this = (http_input_class_t *)this_gen; - + this->proxyport = cfg->num_value; } @@ -168,17 +172,17 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { struct hostent *info; size_t i = 0, host_len, noprox_len; - /* - * get full host name + /* + * get full host name */ if ((info = gethostbyname(host)) == NULL) { - xine_log(this->xine, XINE_LOG_MSG, + xine_log(this->xine, XINE_LOG_MSG, _("input_http: gethostbyname(%s) failed: %s\n"), host, hstrerror(h_errno)); return 1; } if (!info->h_name) return 1; - + if ( info->h_addr_list[0] ) { /* \177\0\0\1 is the *octal* representation of 127.0.0.1 */ if ( info->h_addrtype == AF_INET && !memcmp(info->h_addr_list[0], "\177\0\0\1", 4) ) { @@ -235,26 +239,16 @@ static int http_plugin_basicauth (const char *user, const char *password, char* char *tmp; char *sptr; char *dptr; - int totlen; + size_t count; int enclen; - int count; - - totlen = strlen (user) + 1; - if(password != NULL) - totlen += strlen (password); - - enclen = ((totlen + 2) / 3 ) * 4 + 1; - + + count = asprintf(&tmp, "%s:%s", user, (password != NULL) ? password : ""); + + enclen = ((count + 2) / 3 ) * 4 + 1; + if (len < enclen) return -1; - - tmp = malloc (sizeof(char) * (totlen + 1)); - strcpy (tmp, user); - strcat (tmp, ":"); - if (password != NULL) - strcat (tmp, password); - - count = strlen(tmp); + sptr = tmp; dptr = dest; while (count >= 3) { @@ -266,29 +260,29 @@ static int http_plugin_basicauth (const char *user, const char *password, char* sptr += 3; dptr += 4; } - + if (count > 0) { dptr[0] = enctable[(sptr[0] & 0xFC) >> 2]; dptr[1] = enctable[(sptr[0] & 0x3) << 4]; dptr[2] = '='; - + if (count > 1) { dptr[1] = enctable[((sptr[0] & 0x3) << 4) | ((sptr[1] & 0xF0) >> 4)]; dptr[2] = enctable[(sptr[1] & 0x0F) << 2]; } - + dptr[3] = '='; dptr += 4; } - + dptr[0] = '\0'; - + free(tmp); return 0; } static int http_plugin_read_metainf (http_input_plugin_t *this) { - + char metadata_buf[255 * 16]; unsigned char len = 0; char *title_end; @@ -296,19 +290,19 @@ static int http_plugin_read_metainf (http_input_plugin_t *this) { const char *radio; xine_event_t uevent; xine_ui_data_t data; - + /* get the length of the metadata */ if (_x_io_tcp_read (this->stream, this->fh, (char*)&len, 1) != 1) return 0; lprintf ("http_plugin_read_metainf: len=%d\n", len); - + if (len > 0) { if (_x_io_tcp_read (this->stream, this->fh, metadata_buf, len * 16) != (len * 16)) return 0; - + metadata_buf[len * 16] = '\0'; - + lprintf ("http_plugin_read_metainf: %s\n", metadata_buf); /* Extract the title of the current song */ @@ -321,13 +315,13 @@ static int http_plugin_read_metainf (http_input_plugin_t *this) { } if ((title_end = strstr(songtitle, terminator))) { *title_end = '\0'; - + if ((!this->shoutcast_songtitle || (strcmp(songtitle, this->shoutcast_songtitle))) && (strlen(songtitle) > 0)) { - + lprintf ("http_plugin_read_metainf: songtitle: %s\n", songtitle); - + if (this->shoutcast_songtitle) free(this->shoutcast_songtitle); this->shoutcast_songtitle = strdup(songtitle); @@ -364,7 +358,7 @@ static off_t http_plugin_read_int (http_input_plugin_t *this, char *buf, off_t total) { int read_bytes = 0; int nlen; - + lprintf("total=%"PRId64"\n", total); while (total) { nlen = total; @@ -379,7 +373,7 @@ static off_t http_plugin_read_int (http_input_plugin_t *this, if (!http_plugin_read_metainf(this)) goto error; this->shoutcast_pos = 0; - + } else { nlen = _x_io_tcp_read (this->stream, this->fh, &buf[read_bytes], nlen); if (nlen < 0) @@ -406,7 +400,7 @@ static off_t http_plugin_read_int (http_input_plugin_t *this, this->shoutcast_pos += nlen; } - + /* end of file */ if (nlen == 0) return read_bytes; @@ -414,9 +408,9 @@ static off_t http_plugin_read_int (http_input_plugin_t *this, total -= nlen; } return read_bytes; - + error: - if (!_x_action_pending(this->stream)) + if (!_x_action_pending(this->stream)) _x_message (this->stream, XINE_MSG_READ_ERROR, this->host, NULL); xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: read error %d\n"), errno); return read_bytes; @@ -429,6 +423,9 @@ static off_t http_plugin_read (input_plugin_t *this_gen, num_bytes = 0; + if (nlen < 0) + return -1; + if (this->curpos < this->preview_size) { if (nlen > (this->preview_size - this->curpos)) @@ -445,10 +442,10 @@ static off_t http_plugin_read (input_plugin_t *this_gen, n = nlen - num_bytes; - if (n) { + if (n > 0) { int read_bytes; read_bytes = http_plugin_read_int (this, &buf[num_bytes], n); - + if (read_bytes < 0) return read_bytes; @@ -466,7 +463,7 @@ static int resync_nsv(http_input_plugin_t *this) { lprintf("resyncing NSV stream\n"); while ((pos < 3) && (read_bytes < (1024*1024))) { - + if (http_plugin_read_int(this, (char*)&c, 1) != 1) return 1; @@ -498,7 +495,7 @@ static int resync_nsv(http_input_plugin_t *this) { if (pos == 3) { lprintf("NSV stream resynced\n"); } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "http: cannot resync NSV stream!\n"); return 0; } @@ -511,6 +508,13 @@ static buf_element_t *http_plugin_read_block (input_plugin_t *this_gen, fifo_buf off_t total_bytes; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -562,7 +566,7 @@ static off_t http_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -576,15 +580,15 @@ static off_t http_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin if( this->curpos <= this->preview_size ) this->curpos = offset; else - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "http: cannot seek back! (%" PRIdMAX " > %" PRIdMAX ")\n", (intmax_t)this->curpos, (intmax_t)offset); - + } else { offset -= this->curpos; for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -602,17 +606,20 @@ static const char* http_plugin_get_mrl (input_plugin_t *this_gen) { } static int http_plugin_get_optional_data (input_plugin_t *this_gen, - void *data, int data_type) { + void *const data, int data_type) { + void **const ptr = (void **const) data; http_input_plugin_t *this = (http_input_plugin_t *) this_gen; switch (data_type) { case INPUT_OPTIONAL_DATA_PREVIEW: - memcpy (data, this->preview, this->preview_size); return this->preview_size; - break; + case INPUT_OPTIONAL_DATA_MIME_TYPE: + *ptr = this->mime_type; + case INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE: + return *this->mime_type ? INPUT_OPTIONAL_SUCCESS : INPUT_OPTIONAL_UNSUPPORTED; } return INPUT_OPTIONAL_UNSUPPORTED; @@ -625,7 +632,7 @@ static void http_plugin_dispose (input_plugin_t *this_gen ) { close(this->fh); this->fh = -1; } - + if (this->nbc) { nbc_close (this->nbc); this->nbc = NULL; @@ -637,6 +644,7 @@ static void http_plugin_dispose (input_plugin_t *this_gen ) { if (this->user) free(this->user); if (this->password) free(this->password); if (this->uri) free(this->uri); + if (this->mime_type) free(this->mime_type); free (this); } @@ -644,7 +652,7 @@ static void report_progress (xine_stream_t *stream, int p) { xine_event_t event; xine_progress_data_t prg; - + prg.description = _("Connecting HTTP server..."); prg.percent = p; @@ -661,13 +669,15 @@ static int http_plugin_open (input_plugin_t *this_gen ) { int done, len, linenum; int httpcode; int res; - int buflen; + size_t buflen; int use_proxy; int proxyport; int mpegurl_redirect = 0; - + char mime_type[256]; + + mime_type[0] = 0; use_proxy = this_class->proxyhost && strlen(this_class->proxyhost); - + if (use_proxy) { if (this_class->proxyuser && strlen(this_class->proxyuser)) { if (http_plugin_basicauth (this_class->proxyuser, @@ -678,10 +688,11 @@ static int http_plugin_open (input_plugin_t *this_gen ) { } } } - - + + if (!_x_parse_url(this->mrl, &this->proto, &this->host, &this->port, - &this->user, &this->password, &this->uri)) { + &this->user, &this->password, &this->uri, + &this->user_agent)) { _x_message(this->stream, XINE_MSG_GENERAL_WARNING, "malformed url", NULL); return 0; } @@ -689,14 +700,14 @@ static int http_plugin_open (input_plugin_t *this_gen ) { if (this->port == 0) this->port = DEFAULT_HTTP_PORT; - + if (this->user && strlen(this->user)) { if (http_plugin_basicauth (this->user, this->password, this->auth, BUFSIZE)) { _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "basic auth error", NULL); return -1; } } - + if (this_class->proxyport == 0) proxyport = DEFAULT_HTTP_PORT; else @@ -710,10 +721,10 @@ static int http_plugin_open (input_plugin_t *this_gen ) { printf ("input_http: password : >%s<\n", this->password); printf ("input_http: path : >%s<\n", this->uri); - + if (use_proxy) printf (" via proxy >%s:%d<", this_class->proxyhost, proxyport); - + printf ("\n"); } @@ -723,13 +734,13 @@ static int http_plugin_open (input_plugin_t *this_gen ) { this->fh = _x_io_tcp_connect (this->stream, this_class->proxyhost, proxyport); else this->fh = _x_io_tcp_connect (this->stream, this->host, this->port); - + this->curpos = 0; - + if (this->fh == -1) return -2; - { + { uint32_t timeout, progress; xine_cfg_entry_t cfgentry; if (xine_config_lookup_entry (this->stream->xine, "media.network.timeout", &cfgentry)) { @@ -753,43 +764,40 @@ static int http_plugin_open (input_plugin_t *this_gen ) { if (use_proxy) { if (this->port != DEFAULT_HTTP_PORT) { - snprintf (this->buf, BUFSIZE, "GET http://%s:%d%s HTTP/1.0\015\012", - this->host, this->port, this->uri); + buflen = snprintf (this->buf, BUFSIZE, "GET http://%s:%d%s HTTP/1.0\015\012", + this->host, this->port, this->uri); } else { - snprintf (this->buf, BUFSIZE, "GET http://%s%s HTTP/1.0\015\012", - this->host, this->uri); + buflen = snprintf (this->buf, BUFSIZE, "GET http://%s%s HTTP/1.0\015\012", + this->host, this->uri); } - } + } else - snprintf (this->buf, BUFSIZE, "GET %s HTTP/1.0\015\012", this->uri); - - buflen = strlen(this->buf); + buflen = snprintf (this->buf, BUFSIZE, "GET %s HTTP/1.0\015\012", this->uri); + if (this->port != DEFAULT_HTTP_PORT) - snprintf (this->buf + buflen, BUFSIZE - buflen, "Host: %s:%d\015\012", - this->host, this->port); + buflen += snprintf (this->buf + buflen, BUFSIZE - buflen, "Host: %s:%d\015\012", + this->host, this->port); else - snprintf (this->buf + buflen, BUFSIZE - buflen, "Host: %s\015\012", - this->host); - - buflen = strlen(this->buf); + buflen += snprintf (this->buf + buflen, BUFSIZE - buflen, "Host: %s\015\012", + this->host); + if (this_class->proxyuser && strlen(this_class->proxyuser)) { - snprintf (this->buf + buflen, BUFSIZE - buflen, - "Proxy-Authorization: Basic %s\015\012", this->proxyauth); - buflen = strlen(this->buf); + buflen += snprintf (this->buf + buflen, BUFSIZE - buflen, + "Proxy-Authorization: Basic %s\015\012", this->proxyauth); } if (this->user && strlen(this->user)) { - snprintf (this->buf + buflen, BUFSIZE - buflen, - "Authorization: Basic %s\015\012", this->auth); - buflen = strlen(this->buf); + buflen += snprintf (this->buf + buflen, BUFSIZE - buflen, + "Authorization: Basic %s\015\012", this->auth); } - - snprintf(this->buf + buflen, BUFSIZE - buflen, - "User-Agent: xine/%s\015\012" - "Accept: */*\015\012" - "Icy-MetaData: 1\015\012" - "\015\012", - VERSION); - buflen = strlen(this->buf); + + buflen += snprintf(this->buf + buflen, BUFSIZE - buflen, + "User-Agent: %s%sxine/%s\015\012" + "Accept: */*\015\012" + "Icy-MetaData: 1\015\012" + "\015\012", + this->user_agent ? this->user_agent : "", + this->user_agent ? " " : "", + VERSION); if (_x_io_tcp_write (this->stream, this->fh, this->buf, buflen) != buflen) { _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "couldn't send request", NULL); xprintf(this_class->xine, XINE_VERBOSITY_DEBUG, "input_http: couldn't send request\n"); @@ -813,14 +821,14 @@ static int http_plugin_open (input_plugin_t *this_gen ) { this->buf[len] = '\0'; len--; - + if (len >= 0 && this->buf[len] == '\015') { this->buf[len] = '\0'; len--; } linenum++; - + lprintf ("answer: >%s<\n", this->buf); if (linenum == 1) { @@ -836,13 +844,13 @@ static int http_plugin_open (input_plugin_t *this_gen ) { &httpcode, httpstatus) != 2) ) { _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "invalid http answer", NULL); - xine_log (this->stream->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: invalid http answer\n")); return -6; } if (httpcode >= 300 && httpcode < 400) { - xine_log (this->stream->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: 3xx redirection: >%d %s<\n"), httpcode, httpstatus); } else if (httpcode == 404) { @@ -860,7 +868,7 @@ static int http_plugin_open (input_plugin_t *this_gen ) { } else if (httpcode < 200 || httpcode >= 300) { _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "http status not 2xx: ", httpstatus, NULL); - xine_log (this->stream->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: http status not 2xx: >%d %s<\n"), httpcode, httpstatus); return -9; @@ -868,18 +876,18 @@ static int http_plugin_open (input_plugin_t *this_gen ) { } else { if (this->contentlength == 0) { intmax_t contentlength; - + if (sscanf(this->buf, "Content-Length: %" SCNdMAX , &contentlength) == 1) { - xine_log (this->stream->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: content length = %" PRIdMAX " bytes\n"), contentlength); this->contentlength = (off_t)contentlength; } } - + if (!strncasecmp(this->buf, "Location: ", 10)) { char *href = (this->buf + 10); - + lprintf ("trying to open target of redirection: >%s<\n", href); href = _x_canonicalise_url (this->mrl, href); @@ -907,13 +915,13 @@ static int http_plugin_open (input_plugin_t *this_gen ) { (this->buf + sizeof(TAG_ICY_NAME) - 1 + (*(this->buf + sizeof(TAG_ICY_NAME) - 1) == ' '))); } - + if (!strncasecmp(this->buf, TAG_ICY_GENRE, sizeof(TAG_ICY_GENRE) - 1)) { _x_meta_info_set(this->stream, XINE_META_INFO_GENRE, (this->buf + sizeof(TAG_ICY_GENRE) - 1 + (*(this->buf + sizeof(TAG_ICY_GENRE) - 1) == ' '))); } - + /* icy-notice1 is always the same */ if (!strncasecmp(this->buf, TAG_ICY_NOTICE2, sizeof(TAG_ICY_NOTICE2) - 1)) { char *end; @@ -924,17 +932,21 @@ static int http_plugin_open (input_plugin_t *this_gen ) { (this->buf + sizeof(TAG_ICY_NOTICE2) - 1 + (*(this->buf + sizeof(TAG_ICY_NOTICE2) - 1) == ' '))); } - + /* metadata interval (in byte) */ if (sscanf(this->buf, TAG_ICY_METAINT"%d", &this->shoutcast_metaint) == 1) { lprintf("shoutcast_metaint: %d\n", this->shoutcast_metaint); this->shoutcast_mode = 1; this->shoutcast_pos = 0; } - + /* content type */ if (!strncasecmp(this->buf, TAG_CONTENT_TYPE, sizeof(TAG_CONTENT_TYPE) - 1)) { - if (!strncasecmp(this->buf + sizeof(TAG_CONTENT_TYPE) - 1, "video/nsv", 9)) { + const char *type = this->buf + sizeof (TAG_CONTENT_TYPE) - 1; + while (isspace (*type)) + ++type; + sprintf (mime_type, "%.255s", type); + if (!strncasecmp (type, "video/nsv", 9)) { lprintf("shoutcast nsv detected\n"); this->is_nsv = 1; } @@ -944,7 +956,7 @@ static int http_plugin_open (input_plugin_t *this_gen ) { this->is_lastfm = 1; } } - + if (len == -1) done = 1; else @@ -977,7 +989,7 @@ static int http_plugin_open (input_plugin_t *this_gen ) { *newline = '\0'; lprintf("mpegurl pointing to %s\n", buf); - + href = _x_canonicalise_url (this->mrl, buf); free(this->mrl); this->mrl = href; @@ -992,20 +1004,23 @@ static int http_plugin_open (input_plugin_t *this_gen ) { if (this->is_nsv) { if (!resync_nsv(this)) return -11; - + /* the first 3 chars are "NSV" */ this->preview_size = http_plugin_read_int (this, this->preview + 3, MAX_PREVIEW_SIZE - 3); } else { this->preview_size = http_plugin_read_int (this, this->preview, MAX_PREVIEW_SIZE); } if (this->preview_size < 0) { + this->preview_size = 0; xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: read error %d\n"), errno); return -12; } - + lprintf("preview_size=%"PRId64"\n", this->preview_size); this->curpos = 0; - + if (*mime_type) + this->mime_type = strdup (mime_type); + return 1; } @@ -1016,25 +1031,25 @@ static input_plugin_t *http_class_get_instance (input_class_t *cls_gen, xine_str const char *mrl) { /* http_input_class_t *cls = (http_input_class_t *) cls_gen;*/ http_input_plugin_t *this; - - if (strncasecmp (mrl, "http://", 7) && + + if (strncasecmp (mrl, "http://", 7) && strncasecmp (mrl, "unsv://", 7) && - strncasecmp (mrl, "peercast://pls/", 15)) { + strncasecmp (mrl, "peercast://pls/", 15) && + !_x_url_user_agent (mrl) /* user agent hacks */) { return NULL; } - this = (http_input_plugin_t *) xine_xmalloc(sizeof(http_input_plugin_t)); + this = calloc(1, sizeof(http_input_plugin_t)); if (!strncasecmp (mrl, "peercast://pls/", 15)) { - this->mrl = xine_xmalloc (30 + strlen(mrl) - 15); - sprintf (this->mrl, "http://127.0.0.1:7144/stream/%s", mrl+15); - } else { + asprintf (&this->mrl, "http://127.0.0.1:7144/stream/%s", mrl+15); + } else { this->mrl = strdup (mrl); } - + this->stream = stream; this->fh = -1; this->nbc = nbc_init (this->stream); - + this->input_plugin.open = http_plugin_open; this->input_plugin.get_capabilities = http_plugin_get_capabilities; this->input_plugin.read = http_plugin_read; @@ -1061,7 +1076,7 @@ static const char *http_class_get_identifier (input_class_t *this_gen) { static void http_class_dispose (input_class_t *this_gen) { http_input_class_t *this = (http_input_class_t *) this_gen; - + if(this->proxyhost_env) free(this->proxyhost_env); @@ -1073,7 +1088,7 @@ static void *init_class (xine_t *xine, void *data) { config_values_t *config; char *proxy_env; - this = (http_input_class_t *) xine_xmalloc (sizeof (http_input_class_t)); + this = calloc(1, sizeof (http_input_class_t)); this->xine = xine; this->config = xine->config; @@ -1087,28 +1102,24 @@ static void *init_class (xine_t *xine, void *data) { this->input_class.dispose = http_class_dispose; this->input_class.eject_media = NULL; - /* - * honour http_proxy envvar + /* + * honour http_proxy envvar */ - if((proxy_env = getenv("http_proxy")) && (strlen(proxy_env))) { + if((proxy_env = getenv("http_proxy")) && *proxy_env) { int proxy_port = DEFAULT_HTTP_PORT; - char *http_proxy = xine_xmalloc(strlen(proxy_env) + 1); char *p; - + if(!strncmp(proxy_env, "http://", 7)) proxy_env += 7; - - sprintf(http_proxy, "%s", proxy_env); - - if((p = strrchr(&http_proxy[0], ':')) && (strlen(p) > 1)) { + + this->proxyhost_env = strdup(proxy_env); + + if((p = strrchr(this->proxyhost_env, ':')) && (strlen(p) > 1)) { *p++ = '\0'; proxy_port = (int) strtol(p, &p, 10); } - - this->proxyhost_env = strdup(http_proxy); + this->proxyport_env = proxy_port; - - free(http_proxy); } else proxy_env = NULL; /* proxy_env can be "" */ @@ -1116,7 +1127,7 @@ static void *init_class (xine_t *xine, void *data) { /* * proxy settings */ - this->proxyhost = config->register_string(config, + this->proxyhost = config->register_string(config, "media.network.http_proxy_host", proxy_env ? this->proxyhost_env : "", _("HTTP proxy host"), _("The hostname of the HTTP proxy."), 10, proxy_host_change_cb, (void *) this); @@ -1124,13 +1135,13 @@ static void *init_class (xine_t *xine, void *data) { "media.network.http_proxy_port", proxy_env ? this->proxyport_env : DEFAULT_HTTP_PORT, _("HTTP proxy port"), _("The port number of the HTTP proxy."), 10, proxy_port_change_cb, (void *) this); - + /* registered entries could be empty. Don't ignore envvar */ if(!strlen(this->proxyhost) && (proxy_env && strlen(proxy_env))) { config->update_string(config, "media.network.http_proxy_host", this->proxyhost_env); config->update_num(config, "media.network.http_proxy_port", this->proxyport_env); } - + this->proxyuser = config->register_string(config, "media.network.http_proxy_user", "", _("HTTP proxy username"), _("The user name for the HTTP proxy."), 10, @@ -1143,7 +1154,7 @@ static void *init_class (xine_t *xine, void *data) { "media.network.http_no_proxy", "", _("Domains for which to ignore the HTTP proxy"), _("A comma-separated list of domain names for which the proxy is to be ignored.\nIf a domain name is prefixed with '=' then it is treated as a host name only (full match required)."), 10, no_proxy_list_change_cb, (void *) this); - + return this; } @@ -1152,7 +1163,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "http", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_mms.c b/src/input/input_mms.c index 6a1e729e6..05c6722ed 100644 --- a/src/input/input_mms.c +++ b/src/input/input_mms.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2002-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -76,26 +76,26 @@ typedef struct { char *mrl; - nbc_t *nbc; + nbc_t *nbc; char scratch[1025]; int bandwidth; int protocol; /* mmst or mmsh */ - + } mms_input_plugin_t; typedef struct { input_class_t input_class; - + mms_input_plugin_t *ip; int protocol; /* autoprobe, mmst or mmsh */ xine_t *xine; } mms_input_class_t; -static off_t mms_plugin_read (input_plugin_t *this_gen, +static off_t mms_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; off_t n = 0; @@ -122,9 +122,16 @@ static buf_element_t *mms_plugin_read_block (input_plugin_t *this_gen, lprintf ("mms_plugin_read_block: %"PRId64" bytes...\n", todo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; - + total_bytes = mms_plugin_read (this_gen, (char*)buf->content, todo); if (total_bytes != todo) { @@ -138,7 +145,7 @@ static buf_element_t *mms_plugin_read_block (input_plugin_t *this_gen, } static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { - mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; + mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; off_t dest = 0; off_t curpos = 0; @@ -153,7 +160,7 @@ static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin curpos = mmsh_get_current_pos (this->mmsh); break; } - + switch (origin) { case SEEK_SET: dest = offset; @@ -170,7 +177,7 @@ static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin printf ("input_mms: cannot seek back!\n"); return curpos; } - + while (curpos < dest) { int n = 0; int diff; @@ -188,7 +195,7 @@ static off_t mms_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin n = mmsh_read (this->mmsh, this->scratch, diff); break; } - + curpos += n; if (n < diff) @@ -204,7 +211,7 @@ static off_t mms_plugin_seek_time (input_plugin_t *this_gen, int time_offset, in off_t curpos = 0; lprintf ("seek_time %d msec, origin %d\n", time_offset, origin); - + switch (this->protocol) { case PROTOCOL_MMST: if (origin == SEEK_SET) @@ -217,12 +224,12 @@ static off_t mms_plugin_seek_time (input_plugin_t *this_gen, int time_offset, in curpos = mmsh_get_current_pos (this->mmsh); break; } - + return curpos; } static off_t mms_plugin_get_length (input_plugin_t *this_gen) { - mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; + mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; off_t length = 0; if (!this->mms) @@ -254,7 +261,7 @@ static uint32_t mms_plugin_get_blocksize (input_plugin_t *this_gen) { static off_t mms_plugin_get_current_pos (input_plugin_t *this_gen){ mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; off_t curpos = 0; - + switch (this->protocol) { case PROTOCOL_MMST: curpos = mms_get_current_pos(this->mms); @@ -272,10 +279,10 @@ static void mms_plugin_dispose (input_plugin_t *this_gen) { if (this->mms) mms_close (this->mms); - + if (this->mmsh) mmsh_close (this->mmsh); - + this->mms = NULL; this->mmsh = NULL; @@ -283,10 +290,10 @@ static void mms_plugin_dispose (input_plugin_t *this_gen) { nbc_close (this->nbc); this->nbc = NULL; } - + if(this->mrl) free(this->mrl); - + free (this); } @@ -296,7 +303,7 @@ static const char* mms_plugin_get_mrl (input_plugin_t *this_gen) { return this->mrl; } -static int mms_plugin_get_optional_data (input_plugin_t *this_gen, +static int mms_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; @@ -312,7 +319,7 @@ static int mms_plugin_get_optional_data (input_plugin_t *this_gen, break; } break; - + default: return INPUT_OPTIONAL_UNSUPPORTED; break; @@ -350,7 +357,7 @@ static int mms_plugin_open (input_plugin_t *this_gen) { mms_input_plugin_t *this = (mms_input_plugin_t *) this_gen; mms_t *mms = NULL; mmsh_t *mmsh = NULL; - + switch (this->protocol) { case PROTOCOL_UNDEFINED: mms = mms_connect (this->stream, this->mrl, this->bandwidth); @@ -368,18 +375,18 @@ static int mms_plugin_open (input_plugin_t *this_gen) { mmsh = mmsh_connect (this->stream, this->mrl, this->bandwidth); break; } - + if (!mms && !mmsh) { return 0; } - + this->mms = mms; this->mmsh = mmsh; - + return 1; } -static input_plugin_t *mms_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, +static input_plugin_t *mms_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *data) { mms_input_class_t *cls = (mms_input_class_t *) cls_gen; @@ -387,7 +394,7 @@ static input_plugin_t *mms_class_get_instance (input_class_t *cls_gen, xine_stre char *mrl = strdup(data); xine_cfg_entry_t bandwidth_entry; int protocol; - + lprintf ("trying to open '%s'\n", mrl); if (!strncasecmp (mrl, "mms://", 6)) { @@ -401,16 +408,16 @@ static input_plugin_t *mms_class_get_instance (input_class_t *cls_gen, xine_stre return NULL; } - this = (mms_input_plugin_t *) xine_xmalloc (sizeof (mms_input_plugin_t)); + this = calloc(1, sizeof (mms_input_plugin_t)); cls->ip = this; this->stream = stream; this->mms = NULL; this->mmsh = NULL; this->protocol = protocol; - this->mrl = mrl; + this->mrl = mrl; this->nbc = nbc_init (this->stream); - if (xine_config_lookup_entry (stream->xine, "media.network.bandwidth", + if (xine_config_lookup_entry (stream->xine, "media.network.bandwidth", &bandwidth_entry)) { bandwidth_changed_cb(cls, &bandwidth_entry); } @@ -429,7 +436,7 @@ static input_plugin_t *mms_class_get_instance (input_class_t *cls_gen, xine_stre this->input_plugin.get_optional_data = mms_plugin_get_optional_data; this->input_plugin.input_class = cls_gen; - + return &this->input_plugin; } @@ -449,7 +456,7 @@ static void mms_class_dispose (input_class_t *this_gen) { mms_input_class_t *this = (mms_input_class_t *) this_gen; this->xine->config->unregister_callback(this->xine->config, - "media.network.bandwidth"); + "media.network.bandwidth"); this->xine->config->unregister_callback(this->xine->config, "media.network.mms_protocol"); free (this); @@ -459,7 +466,7 @@ static void *init_class (xine_t *xine, void *data) { mms_input_class_t *this; - this = (mms_input_class_t *) xine_xmalloc (sizeof (mms_input_class_t)); + this = calloc(1, sizeof (mms_input_class_t)); this->xine = xine; this->ip = NULL; @@ -481,12 +488,12 @@ static void *init_class (xine_t *xine, void *data) { 0, bandwidth_changed_cb, (void*) this); this->protocol = xine->config->register_enum(xine->config, - "media.network.mms_protocol", - 0, - mms_protocol_strs, + "media.network.mms_protocol", + 0, + mms_protocol_strs, _("MMS protocol"), _("Select the protocol to encapsulate MMS.\nTCP is better but you may need HTTP behind a firewall."), - 20, + 20, protocol_changed_cb, (void*)this); return this; @@ -497,7 +504,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "mms", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_net.c b/src/input/input_net.c index fe78c93f4..55339b2bb 100644 --- a/src/input/input_net.c +++ b/src/input/input_net.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,9 +21,9 @@ * other end and you can watch tv anywhere in the house ..) * * how to set up mp1e for use with this plugin: - * + * * use mp1 to capture the live stream, e.g. - * mp1e -b 1200 -R 4,32 -a 0 -B 160 -v >live.mpg + * mp1e -b 1200 -R 4,32 -a 0 -B 160 -v >live.mpg * * add an extra service "xine" to /etc/services and /etc/inetd.conf, e.g.: * /etc/services: @@ -78,11 +78,11 @@ typedef struct { input_plugin_t input_plugin; xine_stream_t *stream; - + int fh; char *mrl; char *host_port; - + char preview[MAX_PREVIEW_SIZE]; off_t preview_size; @@ -122,21 +122,21 @@ static int host_connect_attempt_ipv4(struct in_addr ia, int port, xine_t *xine) return -1; } - sin.sin_family = AF_INET; + sin.sin_family = AF_INET; sin.sin_addr = ia; sin.sin_port = htons(port); - + #ifndef WIN32 - if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && errno != EINPROGRESS) + if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && errno != EINPROGRESS) #else - if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && WSAGetLastError() != WSAEINPROGRESS) + if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && WSAGetLastError() != WSAEINPROGRESS) #endif { xine_log(xine, XINE_LOG_MSG, _("input_net: connect(): %s\n"), strerror(errno)); close(s); return -1; - } + } return s; } @@ -144,7 +144,7 @@ static int host_connect_attempt_ipv4(struct in_addr ia, int port, xine_t *xine) static int host_connect_attempt(int family, struct sockaddr* sin, int addrlen, xine_t *xine) { int s; - + s = socket(family, SOCK_STREAM, IPPROTO_TCP); if (s==-1) { xine_log(xine, XINE_LOG_MSG, @@ -153,16 +153,16 @@ static int host_connect_attempt(int family, struct sockaddr* sin, int addrlen, x } #ifndef WIN32 - if (connect(s, sin, addrlen)==-1 && errno != EINPROGRESS) + if (connect(s, sin, addrlen)==-1 && errno != EINPROGRESS) #else - if (connect(s, sin, addrlen)==-1 && WSAGetLastError() != WSAEINPROGRESS) + if (connect(s, sin, addrlen)==-1 && WSAGetLastError() != WSAEINPROGRESS) #endif { xine_log(xine, XINE_LOG_MSG, _("input_net: connect(): %s\n"), strerror(errno)); close(s); return -1; - } + } return s; } @@ -173,14 +173,14 @@ static int host_connect_ipv4(const char *host, int port, xine_t *xine) { struct hostent *h; int i; int s; - + h = gethostbyname(host); if (h==NULL) { xine_log(xine, XINE_LOG_MSG, _("input_net: unable to resolve '%s'.\n"), host); return -1; } - + for (i=0; h->h_addr_list[i]; i++) { struct in_addr ia; memcpy (&ia, h->h_addr_list[i],4); @@ -205,36 +205,36 @@ static int host_connect(const char *host, int port, xine_t *xine) { int error; char strport[16]; int s; - + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; - + hints.ai_family = PF_UNSPEC; + snprintf(strport, sizeof(strport), "%d", port); lprintf("Resolving host '%s' at port '%s'\n", host, strport); error = getaddrinfo(host, strport, &hints, &res); - + if (error) { - + xine_log(xine, XINE_LOG_MSG, _("input_net: unable to resolve '%s'.\n"), host); return -1; } - + /* We loop over all addresses and try to connect */ tmpaddr = res; while (tmpaddr) { - - s = host_connect_attempt (tmpaddr->ai_family, + + s = host_connect_attempt (tmpaddr->ai_family, tmpaddr->ai_addr, tmpaddr->ai_addrlen, xine); if (s != -1) return s; tmpaddr = tmpaddr->ai_next; } - + xine_log(xine, XINE_LOG_MSG, _("input_net: unable to connect to '%s'.\n"), host); return -1; @@ -246,13 +246,16 @@ static int host_connect(const char *host, int port, xine_t *xine) { #define LOW_WATER_MARK 50 #define HIGH_WATER_MARK 100 -static off_t net_plugin_read (input_plugin_t *this_gen, +static off_t net_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { net_input_plugin_t *this = (net_input_plugin_t *) this_gen; off_t n, total; lprintf("reading %" PRIdMAX " bytes...\n", (intmax_t)len); + if (len < 0) + return -1; + total=0; if (this->curpos < this->preview_size) { n = this->preview_size - this->curpos; @@ -270,7 +273,7 @@ static off_t net_plugin_read (input_plugin_t *this_gen, n = _x_read_abort (this->stream, this->fh, &buf[total], len-total); xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_net: got %" PRIdMAX " bytes (%" PRIdMAX "/%" PRIdMAX " bytes read)\n", (intmax_t)n, (intmax_t)total, (intmax_t)len); - + if (n < 0) { _x_message(this->stream, XINE_MSG_READ_ERROR, this->host_port, NULL); return 0; @@ -282,15 +285,22 @@ static off_t net_plugin_read (input_plugin_t *this_gen, return total; } -static buf_element_t *net_plugin_read_block (input_plugin_t *this_gen, +static buf_element_t *net_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { /* net_input_plugin_t *this = (net_input_plugin_t *) this_gen; */ buf_element_t *buf = fifo->buffer_pool_alloc (fifo); off_t total_bytes; + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; - + total_bytes = net_plugin_read (this_gen, (char*)buf->content, todo); if (total_bytes != todo) { @@ -331,7 +341,7 @@ static off_t net_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -353,7 +363,7 @@ static off_t net_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin offset -= this->curpos; for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -371,7 +381,7 @@ static const char* net_plugin_get_mrl (input_plugin_t *this_gen) { return this->mrl; } -static int net_plugin_get_optional_data (input_plugin_t *this_gen, +static int net_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { net_input_plugin_t *this = (net_input_plugin_t *) this_gen; @@ -394,10 +404,10 @@ static void net_plugin_dispose (input_plugin_t *this_gen ) { close(this->fh); this->fh = -1; } - + free (this->mrl); free (this->host_port); - + if (this->nbc) { nbc_close (this->nbc); this->nbc = NULL; @@ -454,33 +464,33 @@ static input_plugin_t *net_class_get_instance (input_class_t *cls_gen, xine_stre if (!strncasecmp (mrl, "tcp://", 6)) { filename = (char *) &mrl[6]; - + if((!filename) || (strlen(filename) == 0)) { return NULL; } - + nbc = nbc_init (stream); - + } else if (!strncasecmp (mrl, "slave://", 8)) { - + filename = (char *) &mrl[8]; - + if((!filename) || (strlen(filename) == 0)) { return NULL; } - + /* the only difference for slave:// is that network buffering control * is not used. otherwise, dvd still menus are not displayed (it freezes * with "buffering..." all the time) */ - + nbc = NULL; - + } else { return NULL; } - this = xine_xmalloc(sizeof(net_input_plugin_t)); + this = calloc(1, sizeof(net_input_plugin_t)); this->mrl = strdup(mrl); this->host_port = strdup(filename); this->stream = stream; @@ -509,7 +519,7 @@ static input_plugin_t *net_class_get_instance (input_class_t *cls_gen, xine_stre /* * net plugin class */ - + static const char *net_class_get_description (input_class_t *this_gen) { return _("net input plugin as shipped with xine"); } @@ -528,7 +538,7 @@ static void *init_class (xine_t *xine, void *data) { net_input_class_t *this; - this = (net_input_class_t *) xine_xmalloc(sizeof(net_input_class_t)); + this = calloc(1, sizeof(net_input_class_t)); this->config = xine->config; this->xine = xine; @@ -548,7 +558,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT, 17, "tcp", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_plugin.h b/src/input/input_plugin.h index 1d1e5cf53..c2cfd6455 100644 --- a/src/input/input_plugin.h +++ b/src/input/input_plugin.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -36,7 +36,7 @@ #endif #define INPUT_PLUGIN_IFACE_VERSION 17 - + typedef struct input_class_s input_class_t ; typedef struct input_plugin_s input_plugin_t; @@ -55,7 +55,7 @@ struct input_class_s { const char* (*get_identifier) (input_class_t *this); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ const char* (*get_description) (input_class_t *this); @@ -97,7 +97,7 @@ struct input_plugin_s { * return capabilities of the current playable entity. See * get_current_pos below for a description of a "playable entity" * Capabilities a created by "OR"ing a mask of constants listed - * below which start "INPUT_CAP". + * below which start "INPUT_CAP". * * depending on the values set, some of the functions below * will or will not get called or should (not) be able to @@ -128,7 +128,7 @@ struct input_plugin_s { /* - * seek position, return new position + * seek position, return new position * * if seeking failed, -1 is returned */ @@ -136,7 +136,7 @@ struct input_plugin_s { /* - * seek to time position, return new position + * seek to time position, return new position * time_offset is given in miliseconds * * if seeking failed, -1 is returned @@ -153,7 +153,7 @@ struct input_plugin_s { */ off_t (*get_current_pos) (input_plugin_t *this); - + /* * get current time position in stream in miliseconds. * @@ -165,7 +165,7 @@ struct input_plugin_s { /* * return number of bytes in the next playable entity or -1 if the * input is unlimited, as would be the case in a network stream. - * + * * A "playable entity" tends to be the entities listed in a playback * list or the units on which playback control generally works on. * It might be the number of bytes in a VCD "segment" or "track" (if @@ -186,7 +186,7 @@ struct input_plugin_s { * return block size in bytes of next complete playable entity (if * supported, 0 otherwise). See the description above under * get_length for a description of a "complete playable entity". - * + * * this block size is only used for mpeg streams stored on * a block oriented storage media, e.g. DVDs and VCDs, to speed * up the demuxing process. only set this (and the INPUT_CAP_BLOCK @@ -231,11 +231,11 @@ struct input_plugin_s { #define INPUT_CAP_NOCAP 0x00000000 /* - * INPUT_CAP_SEEKABLE: - * seek () works reliably. + * INPUT_CAP_SEEKABLE: + * seek () works reliably. * even for plugins that do not have this flag set - * it is a good idea to implement the seek() function - * in a "best effort" style anyway, so at least + * it is a good idea to implement the seek() function + * in a "best effort" style anyway, so at least * throw away data for network streams when seeking forward */ @@ -243,9 +243,9 @@ struct input_plugin_s { /* * INPUT_CAP_BLOCK: - * means more or less that a block device sits behind - * this input plugin. get_blocksize must be implemented. - * will be used for fast and efficient demuxing of + * means more or less that a block device sits behind + * this input plugin. get_blocksize must be implemented. + * will be used for fast and efficient demuxing of * mpeg streams (demux_mpeg_block). */ @@ -254,8 +254,8 @@ struct input_plugin_s { /* * INPUT_CAP_AUDIOLANG: * INPUT_CAP_SPULANG: - * input plugin knows something about audio/spu languages, - * e.g. knows that audio stream #0 is english, + * input plugin knows something about audio/spu languages, + * e.g. knows that audio stream #0 is english, * audio stream #1 is german, ... * *((int *)data) will provide the requested channel number * and awaits the language back in (char *)data @@ -263,20 +263,20 @@ struct input_plugin_s { #define INPUT_CAP_AUDIOLANG 0x00000008 #define INPUT_CAP_SPULANG 0x00000010 - -/* + +/* * INPUT_CAP_PREVIEW: - * get_optional_data can handle INPUT_OPTIONAL_DATA_PREVIEW - * so a non-seekable stream plugin can povide the first - * few bytes for demuxers to look at them and decide wheter - * they can handle the stream or not. the preview data must - * be buffered and delivered again through subsequent + * get_optional_data can handle INPUT_OPTIONAL_DATA_PREVIEW + * so a non-seekable stream plugin can povide the first + * few bytes for demuxers to look at them and decide wheter + * they can handle the stream or not. the preview data must + * be buffered and delivered again through subsequent * read() calls. - * caller must provide a buffer allocated with at least + * caller must provide a buffer allocated with at least * MAX_PREVIEW_SIZE bytes. */ -#define INPUT_CAP_PREVIEW 0x00000040 +#define INPUT_CAP_PREVIEW 0x00000040 /* * INPUT_CAP_CHAPTERS: @@ -307,6 +307,13 @@ struct input_plugin_s { #define INPUT_OPTIONAL_DATA_SPULANG 3 #define INPUT_OPTIONAL_DATA_PREVIEW 7 +/* buffer is a const char **; the string is freed by the input plugin. */ +#define INPUT_OPTIONAL_DATA_MIME_TYPE 8 +/* buffer is unused; true if the demuxer should be determined by the MIME type */ +#define INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE 9 +/* buffer is a const char **; the string is static or freed by the input plugin. */ +#define INPUT_OPTIONAL_DATA_DEMUXER 10 + #define MAX_MRL_ENTRIES 255 #define MAX_PREVIEW_SIZE 4096 @@ -333,65 +340,38 @@ struct input_plugin_s { /* * Freeing/zeroing all of entries of given mrl. */ -#define MRL_ZERO(m) { \ - if((m)) { \ - if((m)->origin) \ - free((m)->origin); \ - if((m)->mrl) \ - free((m)->mrl); \ - if((m)->link) \ - free((m)->link); \ - (m)->origin = NULL; \ - (m)->mrl = NULL; \ - (m)->link = NULL; \ - (m)->type = 0; \ - (m)->size = (off_t) 0; \ - } \ -} +#define MRL_ZERO(m) { \ + if((m)) { \ + free((m)->origin); \ + free((m)->mrl); \ + free((m)->link); \ + (m)->origin = NULL; \ + (m)->mrl = NULL; \ + (m)->link = NULL; \ + (m)->type = 0; \ + (m)->size = (off_t) 0; \ + } \ + } /* * Duplicate two mrls entries (s = source, d = destination). */ -#define MRL_DUPLICATE(s, d) { \ - _x_assert((s) != NULL); \ - _x_assert((d) != NULL); \ - \ - if((s)->origin) { \ - if((d)->origin) { \ - (d)->origin = (char *) realloc((d)->origin, strlen((s)->origin) + 1); \ - sprintf((d)->origin, "%s", (s)->origin); \ - } \ - else \ - (d)->origin = strdup((s)->origin); \ - } \ - else \ - (d)->origin = NULL; \ - \ - if((s)->mrl) { \ - if((d)->mrl) { \ - (d)->mrl = (char *) realloc((d)->mrl, strlen((s)->mrl) + 1); \ - sprintf((d)->mrl, "%s", (s)->mrl); \ - } \ - else \ - (d)->mrl = strdup((s)->mrl); \ - } \ - else \ - (d)->mrl = NULL; \ - \ - if((s)->link) { \ - if((d)->link) { \ - (d)->link = (char *) realloc((d)->link, strlen((s)->link) + 1); \ - sprintf((d)->link, "%s", (s)->link); \ - } \ - else \ - (d)->link = strdup((s)->link); \ - } \ - else \ - (d)->link = NULL; \ - \ - (d)->type = (s)->type; \ - (d)->size = (s)->size; \ -} +#define MRL_DUPLICATE(s, d) { \ + _x_assert((s) != NULL); \ + _x_assert((d) != NULL); \ + \ + free((d)->origin); \ + (d)->origin = (s)->origin ? strdup((s)->origin) : NULL; \ + \ + free((d)->mrl); \ + (d)->mrl = (s)->mrl ? strdup((s)->mrl) : NULL; \ + \ + free((d)->link); \ + (d)->link = (s)->link ? strdup((s)->link) : NULL; \ + \ + (d)->type = (s)->type; \ + (d)->size = (s)->size; \ + } /* * Duplicate two arrays of mrls (s = source, d = destination). diff --git a/src/input/input_pnm.c b/src/input/input_pnm.c index 680c5b1e8..6d9809a6a 100644 --- a/src/input/input_pnm.c +++ b/src/input/input_pnm.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2002-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -61,36 +61,35 @@ typedef struct { input_plugin_t input_plugin; xine_stream_t *stream; - + pnm_t *pnm; char *mrl; off_t curpos; - nbc_t *nbc; + nbc_t *nbc; char scratch[BUFSIZE]; } pnm_input_plugin_t; -static off_t pnm_plugin_read (input_plugin_t *this_gen, +static off_t pnm_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { pnm_input_plugin_t *this = (pnm_input_plugin_t *) this_gen; off_t n; lprintf ("pnm_plugin_read: %"PRId64" bytes ...\n", len); - nbc_check_buffers (this->nbc); - n = pnm_read (this->pnm, buf, len); - this->curpos += n; + if (n >= 0) + this->curpos += n; return n; } -static buf_element_t *pnm_plugin_read_block (input_plugin_t *this_gen, +static buf_element_t *pnm_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { /*pnm_input_plugin_t *this = (pnm_input_plugin_t *) this_gen; */ buf_element_t *buf = fifo->buffer_pool_alloc (fifo); @@ -98,9 +97,16 @@ static buf_element_t *pnm_plugin_read_block (input_plugin_t *this_gen, lprintf ("pnm_plugin_read_block: %"PRId64" bytes...\n", todo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; - + total_bytes = pnm_plugin_read (this_gen, (char*)buf->content, todo); if (total_bytes != todo) { @@ -125,10 +131,16 @@ static off_t pnm_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - this->curpos += pnm_plugin_read (this_gen, this->scratch, BUFSIZE); + off_t n = pnm_plugin_read (this_gen, this->scratch, BUFSIZE); + if (n <= 0) + return this->curpos; + this->curpos += n; } - this->curpos += pnm_plugin_read (this_gen, this->scratch, offset); + off_t n = pnm_plugin_read (this_gen, this->scratch, offset); + if (n <= 0) + return this->curpos; + this->curpos += n; } return this->curpos; @@ -137,7 +149,7 @@ static off_t pnm_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin static off_t pnm_plugin_get_length (input_plugin_t *this_gen) { /* - pnm_input_plugin_t *this = (pnm_input_plugin_t *) this_gen; + pnm_input_plugin_t *this = (pnm_input_plugin_t *) this_gen; off_t length; */ @@ -174,10 +186,10 @@ static void pnm_plugin_dispose (input_plugin_t *this_gen) { nbc_close (this->nbc); this->nbc = NULL; } - + if(this->mrl) free(this->mrl); - + free (this); } @@ -187,7 +199,7 @@ static const char* pnm_plugin_get_mrl (input_plugin_t *this_gen) { return this->mrl; } -static int pnm_plugin_get_optional_data (input_plugin_t *this_gen, +static int pnm_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { pnm_input_plugin_t *this = (pnm_input_plugin_t *) this_gen; @@ -215,11 +227,11 @@ static int pnm_plugin_open (input_plugin_t *this_gen) { } this->pnm = pnm; - + return 1; } -static input_plugin_t *pnm_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, +static input_plugin_t *pnm_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *data) { /* pnm_input_class_t *cls = (pnm_input_class_t *) cls_gen; */ @@ -231,13 +243,13 @@ static input_plugin_t *pnm_class_get_instance (input_class_t *cls_gen, xine_stre return NULL; } - this = (pnm_input_plugin_t *) xine_xmalloc (sizeof (pnm_input_plugin_t)); + this = calloc(1, sizeof (pnm_input_plugin_t)); this->stream = stream; this->pnm = NULL; - this->mrl = mrl; + this->mrl = mrl; this->nbc = nbc_init (this->stream); - + this->input_plugin.open = pnm_plugin_open; this->input_plugin.get_capabilities = pnm_plugin_get_capabilities; this->input_plugin.read = pnm_plugin_read; @@ -250,7 +262,7 @@ static input_plugin_t *pnm_class_get_instance (input_class_t *cls_gen, xine_stre this->input_plugin.dispose = pnm_plugin_dispose; this->input_plugin.get_optional_data = pnm_plugin_get_optional_data; this->input_plugin.input_class = cls_gen; - + return &this->input_plugin; } @@ -276,7 +288,7 @@ static void *init_class (xine_t *xine, void *data) { pnm_input_class_t *this; - this = (pnm_input_class_t *) xine_xmalloc (sizeof (pnm_input_class_t)); + this = calloc(1, sizeof (pnm_input_class_t)); this->xine = xine; @@ -296,7 +308,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT, 17, "pnm", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_pvr.c b/src/input/input_pvr.c index f07e98133..5e7f7bca9 100644 --- a/src/input/input_pvr.c +++ b/src/input/input_pvr.c @@ -4,17 +4,17 @@ * This plugin was sponsored by 1Control * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -32,26 +32,26 @@ * - audio.synchronization.av_sync_method=resample * - ivtv driver (01 Jul 2003 cvs is known to work) * - * MRL: + * MRL: * pvr:/<prefix_to_tmp_files>!<prefix_to_saved_files>!<max_page_age> * - * usage: + * usage: * xine pvr:/<prefix_to_tmp_files>\!<prefix_to_saved_files>\!<max_page_age> */ /************************************************************************** - + Programmer's note (or how to write your PVR frontend): - + - in order to use live pause functionality you must capture data to disk. this is done using XINE_EVENT_SET_V4L2 event. it is important to set the inputs/channel/frequency you want to capture data from. - + comments: 1) session_id must be set: it is used to create the temporary filenames. - + 2) if session_id = -1 no data will be recorded to disk (no pause/replay) - + 3) if session_id is the same as previous value it will just set the "sync point". sync point (show_page) may be used by the PVR frontend to tell that a new show has began. of course, the PVR frontend should be aware @@ -60,18 +60,18 @@ - when user wants to start recording (that is: temporary data will be made permanent) it should issue a XINE_EVENT_PVR_SAVE. mode can be one of the following: - + -1 = do nothing, just set the name (see below) 0 = truncate current session and save from now on 1 = save from last sync point 2 = save everything on current session - + saving actually means just marking the current pages as not temporary. when a session is finished, instead of erasing the files they will be renamed using the save file prefix. - the permanent name can be set in two ways: - + 1) passing a name with the XINE_EVENT_PVR_SAVE before closing the current session. (id = -1) 2) when a saved session is closed without setting the name, it will be @@ -81,7 +81,7 @@ pass back a XINE_EVENT_PVR_SAVE with id set. pvr plugin will rename the files again. -***************************************************************************/ +***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -167,7 +167,7 @@ typedef struct { config_values_t *config; char *devname; - + } pvr_input_class_t; @@ -175,18 +175,18 @@ typedef struct { input_plugin_t input_plugin; pvr_input_class_t *class; - + xine_stream_t *stream; - + xine_event_queue_t *event_queue; - + pvrscr_t *scr; int scr_tunning; int speed_before_pause; - + uint32_t session; /* session number used to identify the pvr file */ int new_session; /* force going to realtime for new sessions */ - + int dev_fd; /* fd of the mpeg2 encoder device */ int rec_fd; /* fd of the current recording file (session/page) */ int play_fd; /* fd of the current playback (-1 when realtime) */ @@ -200,22 +200,22 @@ typedef struct { uint32_t show_page; /* first page of current show */ uint32_t save_page; /* first page to save */ uint32_t page_block[MAX_PAGES]; /* first block of each page */ - + char *mrl; char *tmp_prefix; char *save_prefix; char *save_name; xine_list_t *saved_shows; int saved_id; - + time_t start_time; /* time when recording started */ time_t show_time; /* time when current show started */ - + /* buffer to pass data from pvr thread to xine */ uint8_t data[PVR_BLOCK_SIZE]; int valid_data; int want_data; - + pthread_mutex_t lock; pthread_mutex_t dev_lock; pthread_cond_t has_valid_data; @@ -224,14 +224,14 @@ typedef struct { int pvr_running; int pvr_playing; int pvr_play_paused; - + int preview_buffers; - + /* device properties */ int input; int channel; - uint32_t frequency; - + uint32_t frequency; + } pvr_input_plugin_t; typedef struct { @@ -245,7 +245,7 @@ typedef struct { * unix System Clock Reference + fine tunning * * on an ideal world we would be using scr from mpeg2 - * encoder just like dxr3 does. + * encoder just like dxr3 does. * unfortunately it is not supported by ivtv driver, * and perhaps not even possible with wintv cards. * @@ -279,19 +279,19 @@ static void pvrscr_set_pivot (pvrscr_t *this) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; -/* This next part introduces a one off inaccuracy - * to the scr due to rounding tv to pts. +/* This next part introduces a one off inaccuracy + * to the scr due to rounding tv to pts. */ this->cur_time.tv_sec=tv.tv_sec; this->cur_time.tv_usec=tv.tv_usec; - this->cur_pts=pts; + this->cur_pts=pts; return ; } @@ -303,7 +303,7 @@ static int pvrscr_set_speed (scr_plugin_t *scr, int speed) { pvrscr_set_pivot( this ); this->xine_speed = speed; - this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL * + this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL * this->speed_tunning; pthread_mutex_unlock (&this->lock); @@ -316,7 +316,7 @@ static void pvrscr_speed_tunning (pvrscr_t *this, double factor) { pvrscr_set_pivot( this ); this->speed_tunning = factor; - this->speed_factor = (double) this->xine_speed * 90000.0 / XINE_FINE_SPEED_NORMAL * + this->speed_factor = (double) this->xine_speed * 90000.0 / XINE_FINE_SPEED_NORMAL * this->speed_tunning; pthread_mutex_unlock (&this->lock); @@ -345,7 +345,7 @@ static void pvrscr_start (scr_plugin_t *scr, int64_t start_vpts) { this->cur_pts = start_vpts; pthread_mutex_unlock (&this->lock); - + pvrscr_set_speed (&this->scr, XINE_FINE_SPEED_NORMAL); } @@ -354,16 +354,16 @@ static int64_t pvrscr_get_current (scr_plugin_t *scr) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&tv, NULL); - + pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; - + pthread_mutex_unlock (&this->lock); return pts; @@ -376,10 +376,10 @@ static void pvrscr_exit (scr_plugin_t *scr) { free(this); } -static pvrscr_t* pvrscr_init (void) { +static pvrscr_t *XINE_MALLOC pvrscr_init (void) { pvrscr_t *this; - this = (pvrscr_t *) xine_xmalloc(sizeof(pvrscr_t)); + this = calloc(1, sizeof(pvrscr_t)); this->scr.interface_version = 3; this->scr.get_priority = pvrscr_get_priority; @@ -388,9 +388,9 @@ static pvrscr_t* pvrscr_init (void) { this->scr.start = pvrscr_start; this->scr.get_current = pvrscr_get_current; this->scr.exit = pvrscr_exit; - + pthread_mutex_init (&this->lock, NULL); - + pvrscr_speed_tunning(this, 1.0 ); pvrscr_set_speed (&this->scr, XINE_SPEED_PAUSE); #ifdef SCRLOG @@ -405,10 +405,10 @@ static pvrscr_t* pvrscr_init (void) { static uint32_t block_to_page(pvr_input_plugin_t *this, uint32_t block) { uint32_t page; - + for( page = 0; page < this->rec_page; page++ ) { if( block < this->page_block[page+1] ) - break; + break; } return page; } @@ -424,6 +424,9 @@ static uint32_t pvr_plugin_get_capabilities (input_plugin_t *this_gen) { static off_t pvr_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { /*pvr_input_plugin_t *this = (pvr_input_plugin_t *) this_gen;*/ + if (len < 4) + return -1; + /* FIXME: Tricking the demux_mpeg_block plugin */ buf[0] = 0; buf[1] = 0; @@ -433,7 +436,7 @@ static off_t pvr_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { } -/* +/* * this function will adjust playback speed to control buffer utilization. * we must avoid: * - overflow: buffer runs full. no data is read from the mpeg2 card so it will discard @@ -444,15 +447,15 @@ static off_t pvr_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { * OBS: use with audio.synchronization.av_sync_method=resample */ static void pvr_adjust_realtime_speed(pvr_input_plugin_t *this, fifo_buffer_t *fifo, int speed ) { - + int num_used, num_free; int scr_tunning = this->scr_tunning; - + num_used = fifo->size(fifo); num_free = fifo->num_free(fifo); - + if( num_used == 0 && scr_tunning != -2 ) { - + /* buffer is empty. pause it for a while */ this->scr_tunning = -2; /* marked as paused */ pvrscr_speed_tunning(this->scr, 1.0); @@ -461,77 +464,67 @@ static void pvr_adjust_realtime_speed(pvr_input_plugin_t *this, fifo_buffer_t *f #ifdef SCRLOG printf("input_pvr: buffer empty, pausing playback\n" ); #endif - + } else if( scr_tunning == -2 ) { - + /* currently paused, revert to normal if 1/3 full */ if( 2*num_used > num_free ) { this->scr_tunning = 0; - + pvrscr_speed_tunning(this->scr, 1.0 ); _x_set_speed(this->stream, this->speed_before_pause); #ifdef SCRLOG printf("input_pvr: resuming playback\n" ); #endif } - + } else if( speed == XINE_SPEED_NORMAL && this->play_fd == -1 ) { - + /* when playing realtime, adjust the scr to make xine buffers half full */ if( num_used > 2*num_free ) - scr_tunning = +1; /* play faster */ + scr_tunning = +1; /* play faster */ else if( num_free > 2*num_used ) scr_tunning = -1; /* play slower */ else if( (scr_tunning > 0 && num_free > num_used) || (scr_tunning < 0 && num_used > num_free) ) scr_tunning = 0; - + if( scr_tunning != this->scr_tunning ) { this->scr_tunning = scr_tunning; #ifdef SCRLOG printf("input_pvr: scr_tunning = %d (used: %d free: %d)\n", scr_tunning, num_used, num_free ); #endif - + /* make it play .5% faster or slower */ pvrscr_speed_tunning(this->scr, 1.0 + (0.005 * scr_tunning) ); } - + } else if( this->scr_tunning ) { this->scr_tunning = 0; - + pvrscr_speed_tunning(this->scr, 1.0 ); } } #define PVR_FILENAME "%s%08d_%08d.vob" -#define PVR_FILENAME_SIZE 1+8+1+8+4+1 static char *make_temp_name(pvr_input_plugin_t *this, int page) { - char *filename; - - int size = strlen(this->tmp_prefix)+PVR_FILENAME_SIZE; - filename = malloc(size); - - snprintf(filename, size, PVR_FILENAME, this->tmp_prefix, this->session, page); - + + asprintf(&filename, PVR_FILENAME, this->tmp_prefix, this->session, page); + return filename; } - + #define SAVE_BASE_FILENAME "ch%03d %02d-%02d-%04d %02d:%02d:%02d" -#define SAVE_BASE_FILENAME_SIZE 2+3+1+2+1+2+1+4+1+2+1+2+1+2+1 - + static char *make_base_save_name(int channel, time_t tm) { - struct tm rec_time; char *filename; - - int size = SAVE_BASE_FILENAME_SIZE; - filename = malloc(size); - + localtime_r(&tm, &rec_time); - - snprintf(filename, size, SAVE_BASE_FILENAME, + + asprintf(&filename, SAVE_BASE_FILENAME, channel, rec_time.tm_mon+1, rec_time.tm_mday, rec_time.tm_year+1900, rec_time.tm_hour, rec_time.tm_min, rec_time.tm_sec); @@ -539,17 +532,12 @@ static char *make_base_save_name(int channel, time_t tm) { } #define SAVE_FILENAME "%s%s_%04d.vob" -#define SAVE_FILENAME_SIZE 1+4+4+1 static char *make_save_name(pvr_input_plugin_t *this, char *base, int page) { - char *filename; - - int size = strlen(this->save_prefix)+strlen(base)+SAVE_FILENAME_SIZE; - filename = malloc(size); - - snprintf(filename, size, SAVE_FILENAME, this->save_prefix, base, page); - + + asprintf(&filename, SAVE_FILENAME, this->save_prefix, base, page); + return filename; } @@ -574,27 +562,27 @@ static void pvr_report_realtime (pvr_input_plugin_t *this, int mode) { * close current recording page and open a new one */ static int pvr_break_rec_page (pvr_input_plugin_t *this) { - + char *filename; - + if( this->session == (unsigned)-1 ) /* not recording */ return 1; - + if( this->rec_fd != -1 && this->rec_fd != this->play_fd ) { - close(this->rec_fd); + close(this->rec_fd); } - + if( this->rec_fd == -1 ) this->rec_page = 0; else this->rec_page++; - + this->page_block[this->rec_page] = this->rec_blk; - + filename = make_temp_name(this, this->rec_page); - + lprintf("opening pvr file for writing (%s)\n", filename); - + this->rec_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC, 0666 ); if( this->rec_fd == -1 ) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, @@ -603,39 +591,39 @@ static int pvr_break_rec_page (pvr_input_plugin_t *this) { return 0; } free(filename); - + /* erase first_page if old and not to be saved */ - if( this->max_page_age != (unsigned)-1 && + if( this->max_page_age != (unsigned)-1 && this->rec_page - this->max_page_age == this->first_page && (this->save_page == (unsigned)-1 || this->first_page < this->save_page) ) { - + filename = make_temp_name(this, this->first_page); lprintf("erasing old pvr file (%s)\n", filename); - + this->first_page++; if(this->play_fd != -1 && this->play_page < this->first_page) { this->play_blk = this->page_block[this->first_page]; close(this->play_fd); this->play_fd = -1; } - + remove(filename); free(filename); - } + } return 1; } /* - * check the status of recording file, open new one as needed and write the current data. + * check the status of recording file, open new one as needed and write the current data. */ static int pvr_rec_file(pvr_input_plugin_t *this) { - + off_t pos; if( this->session == (unsigned)-1 ) /* not recording */ return 1; - + /* check if it's time to change page/file */ if( this->rec_fd == -1 || (this->rec_blk - this->page_block[this->rec_page]) >= BLOCKS_PER_PAGE ) { if( !pvr_break_rec_page(this) ) @@ -643,61 +631,61 @@ static int pvr_rec_file(pvr_input_plugin_t *this) { } pos = (off_t)(this->rec_blk - this->page_block[this->rec_page]) * PVR_BLOCK_SIZE; if( lseek (this->rec_fd, pos, SEEK_SET) != pos ) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: error setting position for writing %" PRIdMAX "\n", (intmax_t)pos); return 0; } if( this->rec_fd != -1 ) { if( write(this->rec_fd, this->data, PVR_BLOCK_SIZE) < PVR_BLOCK_SIZE ) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: short write to pvr file (out of disk space?)\n"); return 0; } this->rec_blk++; } - + return 1; } -/* +/* * check for playback mode, switching realtime <-> non-realtime. * gets data from file in non-realtime mode. */ static int pvr_play_file(pvr_input_plugin_t *this, fifo_buffer_t *fifo, uint8_t *buffer, int speed) { - + off_t pos; - + /* check for realtime. don't switch back unless enough buffers are * free to not block the pvr thread */ if( this->new_session || (this->play_blk+1 >= this->rec_blk && speed >= XINE_SPEED_NORMAL && (this->play_fd == -1 || fifo->size(fifo) < fifo->num_free(fifo))) ) { - + this->play_blk = (this->rec_blk) ? (this->rec_blk-1) : 0; - + if( speed > XINE_SPEED_NORMAL ) _x_set_speed(this->stream, XINE_SPEED_NORMAL); - + if( this->play_fd != -1 ) { if(this->play_fd != this->rec_fd ) - close(this->play_fd); + close(this->play_fd); this->play_fd = -1; - + lprintf("switching back to realtime\n"); pvr_report_realtime(this,1); - + } else if (this->new_session) { lprintf("starting new session in realtime\n"); pvr_report_realtime(this,1); } - + this->want_data = 1; this->new_session = 0; - + } else { - if( this->rec_fd == -1 ) + if( this->rec_fd == -1 ) return 1; if(speed != XINE_SPEED_PAUSE) { @@ -711,30 +699,30 @@ static int pvr_play_file(pvr_input_plugin_t *this, fifo_buffer_t *fifo, uint8_t } } - if( this->play_fd == -1 || + if( this->play_fd == -1 || ((this->play_blk - this->page_block[this->play_page]) >= BLOCKS_PER_PAGE) || (this->rec_page > this->play_page && this->play_blk >= this->page_block[this->play_page+1]) ) { - + if(this->play_fd == -1) { lprintf("switching to non-realtime\n"); pvr_report_realtime(this,0); } - + if( this->play_fd != -1 && this->play_fd != this->rec_fd ) { - close(this->play_fd); + close(this->play_fd); } - + if( this->play_fd == -1 ) this->play_page = block_to_page(this, this->play_blk); else this->play_page++; - + if( this->play_page < this->first_page ) { this->play_page = this->first_page; this->play_blk = this->page_block[this->play_page]; } - + /* should be impossible */ if( this->play_page > this->rec_page || this->play_blk > this->rec_blk ) { @@ -747,11 +735,11 @@ static int pvr_play_file(pvr_input_plugin_t *this, fifo_buffer_t *fifo, uint8_t this->play_fd = this->rec_fd; } else { char *filename; - + filename = make_temp_name(this, this->play_page); lprintf("opening pvr file for reading (%s)\n", filename); - + this->play_fd = open(filename, O_RDONLY ); if( this->play_fd == -1 ) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, @@ -764,7 +752,7 @@ static int pvr_play_file(pvr_input_plugin_t *this, fifo_buffer_t *fifo, uint8_t this->want_data = 0; pthread_cond_signal (&this->wake_pvr); } - + if(speed != XINE_SPEED_PAUSE) { pos = (off_t)(this->play_blk - this->page_block[this->play_page]) * PVR_BLOCK_SIZE; @@ -815,29 +803,29 @@ static void *pvr_loop (void *this_gen) { int lost_sync; while( this->pvr_running ) { - + pthread_mutex_lock(&this->lock); this->valid_data = 0; pthread_mutex_unlock(&this->lock); - + total_bytes = 0; do { - + lost_sync = 0; - + pthread_mutex_lock(&this->dev_lock); while (total_bytes < PVR_BLOCK_SIZE) { num_bytes = read (this->dev_fd, this->data + total_bytes, PVR_BLOCK_SIZE-total_bytes); if (num_bytes <= 0) { - if (num_bytes < 0) + if (num_bytes < 0) xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("input_pvr: read error (%s)\n"), strerror(errno)); - this->pvr_running = 0; + this->pvr_running = 0; break; } total_bytes += num_bytes; } - + if( this->data[0] || this->data[1] || this->data[2] != 1 || this->data[3] != 0xba ) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "resyncing mpeg stream\n"); @@ -848,28 +836,28 @@ static void *pvr_loop (void *this_gen) { this->data[0] = 0; this->data[1] = 0; this->data[2] = 1; this->data[3] = 0xba; total_bytes = 4; } - } + } pthread_mutex_unlock(&this->dev_lock); - - } while( lost_sync ); - + + } while( lost_sync ); + pthread_mutex_lock(&this->lock); - + if( !pvr_rec_file(this) ) { - this->pvr_running = 0; + this->pvr_running = 0; } - + this->valid_data = 1; pthread_cond_signal (&this->has_valid_data); - while(this->valid_data && this->play_fd == -1 && + while(this->valid_data && this->play_fd == -1 && this->want_data && this->pvr_playing) { pthread_cond_wait (&this->wake_pvr, &this->lock); } - + pthread_mutex_unlock(&this->lock); } - + pthread_exit(NULL); } @@ -880,7 +868,7 @@ static void *pvr_loop (void *this_gen) { * name (save_name) or a default one using channel and time. */ static void pvr_finish_recording (pvr_input_plugin_t *this) { - + char *src_filename; char *save_base; char *dst_filename; @@ -889,31 +877,31 @@ static void pvr_finish_recording (pvr_input_plugin_t *this) { lprintf("finish_recording\n"); if( this->rec_fd != -1 ) { - close(this->rec_fd); - + close(this->rec_fd); + if( this->play_fd != -1 && this->play_fd != this->rec_fd ) close(this->play_fd); - + this->rec_fd = this->play_fd = -1; - + if( this->save_page == this->show_page ) save_base = make_base_save_name(this->channel, this->show_time); else save_base = make_base_save_name(this->channel, this->start_time); - + for( i = this->first_page; i <= this->rec_page; i++ ) { - + src_filename = make_temp_name(this, i); - + if( this->save_page == (unsigned)-1 || i < this->save_page ) { lprintf("erasing old pvr file (%s)\n", src_filename); remove(src_filename); } else { - + if( !this->save_name || !strlen(this->save_name) ) dst_filename = make_save_name(this, save_base, i-this->save_page+1); - else + else dst_filename = make_save_name(this, this->save_name, i-this->save_page+1); lprintf("moving (%s) to (%s)\n", src_filename, dst_filename); @@ -923,17 +911,17 @@ static void pvr_finish_recording (pvr_input_plugin_t *this) { } free(src_filename); } - + if( this->save_page != (unsigned)-1 && (!this->save_name || !strlen(this->save_name)) ) { saved_show_t *show = malloc(sizeof(saved_show_t)); xine_event_t event; xine_pvr_save_data_t data; - + show->base_name = save_base; show->id = ++this->saved_id; show->pages = this->rec_page - this->save_page + 1; xine_list_push_back (this->saved_shows, show); - + lprintf("sending event with base name [%s]\n", show->base_name); /* tell frontend the name of the saved show */ @@ -942,18 +930,18 @@ static void pvr_finish_recording (pvr_input_plugin_t *this) { event.data = &data; event.data_length = sizeof(data); gettimeofday(&event.tv, NULL); - + data.mode = 0; data.id = show->id; strncpy(data.name, show->base_name, sizeof(data.name)); data.name[sizeof(data.name) - 1] = '\0'; - + xine_event_send(this->stream, &event); } else { free(save_base); } } - + this->first_page = 0; this->show_page = 0; this->save_page = -1; @@ -1016,23 +1004,25 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { /* change input */ if (v4l2_data->input != -1 && v4l2_data->input != this->input) { - lprintf("change input to:%d\n", v4l2_data->input); this->input = v4l2_data->input; /* as of ivtv 0.10.6: must close and reopen to set input */ close(this->dev_fd); this->dev_fd = open (this->class->devname, O_RDWR); - if (this->dev_fd == -1) { + if (this->dev_fd < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: error opening device %s\n", this->class->devname ); } else { - if( ioctl(this->dev_fd, VIDIOC_S_INPUT, &this->input) ) - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + if( ioctl(this->dev_fd, VIDIOC_S_INPUT, &this->input) == 0 ) { + lprintf("Tuner Input set to:%d\n", v4l2_data->input); + } else { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: error setting v4l2 input\n"); + } } } - /* change channel */ + /* change channel */ if (v4l2_data->channel != -1 && v4l2_data->channel != this->channel) { lprintf("change channel to:%d\n", v4l2_data->channel); this->channel = v4l2_data->channel; @@ -1040,24 +1030,40 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { /* change frequency */ if (v4l2_data->frequency != -1 && v4l2_data->frequency != this->frequency) { - lprintf("changing frequency to:%.2f\n", (float)v4l2_data->frequency * 62.5); + double freq = (double)v4l2_data->frequency / 1000.0; struct v4l2_frequency vf; + struct v4l2_tuner vt; + double fac = 16; + + memset(&vf, 0, sizeof(vf)); + memset(&vt, 0, sizeof(vt)); + this->frequency = v4l2_data->frequency; - vf.frequency = this->frequency; + + if (ioctl(this->dev_fd, VIDIOC_G_TUNER, &vt) == 0) { + fac = (vt.capability & V4L2_TUNER_CAP_LOW) ? 16000 : 16; + } + vf.tuner = 0; - if( ioctl(this->dev_fd, VIDIOC_S_FREQUENCY, &vf) ) + vf.type = vt.type; + vf.frequency = (__u32)(freq * fac); + + if (ioctl(this->dev_fd, VIDIOC_S_FREQUENCY, &vf) == 0) { + lprintf("Tuner Frequency set to %d (%f.3 MHz)\n", vf.frequency, vf.frequency / fac); + } else { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: error setting v4l2 frequency\n"); + } } pthread_mutex_unlock(&this->dev_lock); - + /* FIXME: also flush the device */ /* _x_demux_flush_engine(this->stream); */ break; - - + + case XINE_EVENT_PVR_SAVE: if( this->session != -1 ) { switch( save_data->mode ) { @@ -1090,11 +1096,11 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { if( this->save_name ) free( this->save_name ); this->save_name = NULL; - + if( save_data->id < 0 ) { /* no id: set name for current recording */ this->save_name = strdup(save_data->name); - + } else { /* search for the ID of saved shows and rename it * to the given name. */ @@ -1102,17 +1108,17 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { char *dst_filename; saved_show_t *show; xine_list_iterator_t ite; - + pthread_mutex_lock(&this->lock); - + ite = xine_list_front (this->saved_shows); while (ite) { show = xine_list_get_value(this->saved_shows, ite); if( show->id == save_data->id ) { int i; - + for( i = 0; i < show->pages; i++ ) { - + src_filename = make_save_name(this, show->base_name, i+1); dst_filename = make_save_name(this, save_data->name, i+1); @@ -1144,7 +1150,7 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { case XINE_EVENT_SET_MPEG_DATA: { struct ivtv_ioctl_codec codec; - + pthread_mutex_lock(&this->dev_lock); /* how lame. we must close and reopen to change bitrate. */ @@ -1155,9 +1161,9 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { _("input_pvr: error opening device %s\n"), this->class->devname ); return; } - + if (ioctl(this->dev_fd, IVTV_IOC_G_CODEC, &codec) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("input_pvr: IVTV_IOC_G_CODEC failed, maybe API changed?\n")); } else { codec.bitrate = mpeg_data->bitrate_mean; @@ -1172,7 +1178,7 @@ static void pvr_event_handler (pvr_input_plugin_t *this) { pthread_mutex_unlock(&this->dev_lock); } break; - + #if 0 default: printf ("input_pvr: got an event, type 0x%08x\n", event->type); @@ -1198,7 +1204,15 @@ static buf_element_t *pvr_plugin_read_block (input_plugin_t *this_gen, fifo_buff if( !this->pvr_running ) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_pvr: thread died, aborting\n"); - return NULL; + return NULL; + } + + buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer(buf); + return NULL; } if( this->scr_tunning == -2 ) @@ -1206,7 +1220,7 @@ static buf_element_t *pvr_plugin_read_block (input_plugin_t *this_gen, fifo_buff if( this->pvr_play_paused ) speed = XINE_SPEED_PAUSE; - + if( this->pvr_playing && _x_stream_info_get(this->stream, XINE_STREAM_INFO_IGNORE_VIDEO) ) { /* video decoding has being disabled. avoid tweaking the clock */ this->pvr_playing = 0; @@ -1218,56 +1232,55 @@ static buf_element_t *pvr_plugin_read_block (input_plugin_t *this_gen, fifo_buff this->pvr_playing = 1; this->play_blk = this->rec_blk; } - + if( this->pvr_playing ) pvr_adjust_realtime_speed(this, fifo, speed); pvr_event_handler(this); - - buf = fifo->buffer_pool_alloc (fifo); + buf->content = buf->mem; - + pthread_mutex_lock(&this->lock); - + if( this->pvr_playing ) if( !pvr_play_file(this, fifo, buf->content, speed) ) { buf->free_buffer(buf); pthread_mutex_unlock(&this->lock); return NULL; } - + if( todo == PVR_BLOCK_SIZE && speed != XINE_SPEED_PAUSE && this->pvr_playing ) { buf->type = BUF_DEMUX_BLOCK; buf->size = PVR_BLOCK_SIZE; - + if(this->play_fd == -1) { - + /* realtime mode: wait for valid data from pvr thread */ this->want_data = 1; while(!this->valid_data && this->pvr_running) pthread_cond_wait (&this->has_valid_data, &this->lock); - + this->play_blk = this->rec_blk; xine_fast_memcpy(buf->content, this->data, PVR_BLOCK_SIZE); - + this->valid_data = 0; pthread_cond_signal (&this->wake_pvr); } pthread_mutex_unlock(&this->lock); - + } else { pthread_mutex_unlock(&this->lock); - + buf->type = BUF_CONTROL_NOP; - buf->size = 0; - + buf->size = 0; + if(this->preview_buffers) this->preview_buffers--; else xine_usec_sleep (20000); } - + return buf; } @@ -1276,7 +1289,7 @@ static off_t pvr_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin pvr_input_plugin_t *this = (pvr_input_plugin_t *) this_gen; pthread_mutex_lock(&this->lock); - + switch( origin ) { case SEEK_SET: this->play_blk = (offset / PVR_BLOCK_SIZE) + this->page_block[this->first_page]; @@ -1288,18 +1301,18 @@ static off_t pvr_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin this->play_blk = this->rec_blk + (offset / PVR_BLOCK_SIZE); break; } - + /* invalidate the fd if needed */ if( this->play_fd != -1 && block_to_page(this,this->play_blk) != this->play_page ) { if( this->play_fd != this->rec_fd ) - close(this->play_fd); + close(this->play_fd); this->play_fd = -1; if( this->play_blk >= this->rec_blk ) pvr_report_realtime(this,1); } pthread_mutex_unlock(&this->lock); - + return (off_t) (this->play_blk - this->page_block[this->first_page]) * PVR_BLOCK_SIZE; } @@ -1326,9 +1339,9 @@ static const char* pvr_plugin_get_mrl (input_plugin_t *this_gen) { return this->mrl; } -static int pvr_plugin_get_optional_data (input_plugin_t *this_gen, +static int pvr_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { - + return INPUT_OPTIONAL_UNSUPPORTED; } @@ -1346,11 +1359,11 @@ static void pvr_plugin_dispose (input_plugin_t *this_gen ) { this->want_data = 0; pthread_cond_signal (&this->wake_pvr); pthread_mutex_unlock(&this->lock); - pthread_join (this->pvr_thread, &p); + pthread_join (this->pvr_thread, &p); lprintf("pvr thread joined\n"); } - + if (this->scr) { this->stream->xine->clock->unregister_scr(this->stream->xine->clock, &this->scr->scr); this->scr->scr.exit(&this->scr->scr); @@ -1363,15 +1376,15 @@ static void pvr_plugin_dispose (input_plugin_t *this_gen ) { close(this->dev_fd); pvr_finish_recording(this); - + free (this->mrl); - + if (this->tmp_prefix) free (this->tmp_prefix); - + if (this->save_prefix) free (this->save_prefix); - + ite = xine_list_front (this->saved_shows); while (ite) { show = xine_list_get_value(this->saved_shows, ite); @@ -1388,7 +1401,7 @@ static int pvr_plugin_open (input_plugin_t *this_gen ) { int64_t time; int err; struct ivtv_ioctl_codec codec; - + this->session = 0; this->rec_fd = -1; this->play_fd = -1; @@ -1404,7 +1417,7 @@ static int pvr_plugin_open (input_plugin_t *this_gen ) { this->dev_fd = open (this->class->devname, O_RDWR); if (this->dev_fd == -1) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("input_pvr: error opening device %s\n"), this->class->devname ); return 0; } @@ -1423,46 +1436,46 @@ static int pvr_plugin_open (input_plugin_t *this_gen ) { _("input_pvr: IVTV_IOC_S_CODEC failed, maybe API changed?\n")); } } - - /* register our own scr provider */ + + /* register our own scr provider */ time = this->stream->xine->clock->get_current_time(this->stream->xine->clock); this->scr = pvrscr_init(); this->scr->scr.start(&this->scr->scr, time); this->stream->xine->clock->register_scr(this->stream->xine->clock, &this->scr->scr); this->scr_tunning = 0; - + this->event_queue = xine_event_new_queue (this->stream); - + /* enable resample method */ this->stream->xine->config->update_num(this->stream->xine->config,"audio.synchronization.av_sync_method",1); - + this->pvr_running = 1; - + if ((err = pthread_create (&this->pvr_thread, NULL, pvr_loop, this)) != 0) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_NONE, "input_pvr: can't create new thread (%s)\n", strerror(err)); _x_abort(); } - + return 1; } -static input_plugin_t *pvr_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, +static input_plugin_t *pvr_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *data) { pvr_input_class_t *cls = (pvr_input_class_t *) cls_gen; pvr_input_plugin_t *this; char *mrl; char *aux; - - if (strncasecmp (data, "pvr:/", 5)) + + if (strncasecmp (data, "pvr:/", 5)) return NULL; - + mrl = strdup(data); aux = &mrl[5]; - this = (pvr_input_plugin_t *) xine_xmalloc (sizeof (pvr_input_plugin_t)); + this = calloc(1, sizeof (pvr_input_plugin_t)); this->class = cls; this->stream = stream; this->dev_fd = -1; @@ -1472,14 +1485,14 @@ static input_plugin_t *pvr_class_get_instance (input_class_t *cls_gen, xine_stre /* decode configuration options from mrl */ if( strlen(aux) ) { this->tmp_prefix = strdup(aux); - + aux = strchr(this->tmp_prefix,'!'); if( aux ) { aux[0] = '\0'; this->save_prefix = strdup(aux+1); aux = strchr(this->save_prefix, '!'); - if( aux ) { + if( aux ) { aux[0] = '\0'; if( atoi(aux+1) ) this->max_page_age = atoi(aux+1); @@ -1491,11 +1504,11 @@ static input_plugin_t *pvr_class_get_instance (input_class_t *cls_gen, xine_stre this->tmp_prefix=strdup("./"); this->save_prefix=strdup("./"); } - + lprintf("tmp_prefix=%s\n", this->tmp_prefix); lprintf("save_prefix=%s\n", this->save_prefix); lprintf("max_page_age=%d\n", this->max_page_age); - + this->input_plugin.open = pvr_plugin_open; this->input_plugin.get_capabilities = pvr_plugin_get_capabilities; this->input_plugin.read = pvr_plugin_read; @@ -1513,12 +1526,12 @@ static input_plugin_t *pvr_class_get_instance (input_class_t *cls_gen, xine_stre this->event_queue = NULL; this->save_name = NULL; this->saved_shows = xine_list_new(); - + pthread_mutex_init (&this->lock, NULL); pthread_mutex_init (&this->dev_lock, NULL); pthread_cond_init (&this->has_valid_data,NULL); pthread_cond_init (&this->wake_pvr,NULL); - + return &this->input_plugin; } @@ -1546,7 +1559,7 @@ static void *init_plugin (xine_t *xine, void *data) { pvr_input_class_t *this; - this = (pvr_input_class_t *) xine_xmalloc (sizeof (pvr_input_class_t)); + this = calloc(1, sizeof (pvr_input_class_t)); this->xine = xine; this->config = xine->config; @@ -1575,7 +1588,7 @@ static void *init_plugin (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "pvr", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_rtp.c b/src/input/input_rtp.c index 25498f289..e91e43f55 100644 --- a/src/input/input_rtp.c +++ b/src/input/input_rtp.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -114,7 +114,7 @@ typedef struct { input_plugin_t input_plugin; xine_stream_t *stream; - + char *mrl; config_values_t *config; @@ -122,16 +122,16 @@ typedef struct { int port; char *interface; /* For multicast, eth0, eth1 etc */ int is_rtp; - + int fh; - + unsigned char *buffer; /* circular buffer */ unsigned char *buffer_get_ptr; /* get pointer used by reader */ unsigned char *buffer_put_ptr; /* put pointer used by writer */ long buffer_count; /* number of bytes in the buffer */ unsigned char packet_buffer[65536]; - + int last_input_error; int input_eof; @@ -184,7 +184,7 @@ static int host_connect_attempt(struct in_addr ia, int port, return -1; } - saddr.in.sin_family = AF_INET; + saddr.in.sin_family = AF_INET; saddr.in.sin_addr = ia; saddr.in.sin_port = htons(port); @@ -193,8 +193,8 @@ static int host_connect_attempt(struct in_addr ia, int port, LOG_MSG(xine, _("IP address specified is multicast\n")); multicast = 1; /* boolean true */ } - - + + /* Try to increase receive buffer to 1MB to avoid dropping packets */ optval = BUFFER_SIZE; if ((setsockopt(s, SOL_SOCKET, SO_RCVBUF, @@ -217,7 +217,7 @@ static int host_connect_attempt(struct in_addr ia, int port, LOG_MSG(xine, _("bind(): %s.\n"), strerror(errno)); return -1; } - + /* multicast ? */ if (multicast) { @@ -250,14 +250,14 @@ static int host_connect_attempt(struct in_addr ia, int port, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); } - + if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) { LOG_MSG(xine, _("setsockopt(IP_ADD_MEMBERSHIP) failed (multicast kernel?): %s.\n"), strerror(errno)); return -1; } } - + return s; } @@ -271,13 +271,13 @@ static int host_connect(const char *host, int port, struct hostent *h; int i; int s; - + h=gethostbyname(host); if(h==NULL) { LOG_MSG(xine, _("unable to resolve '%s'.\n"), host); return -1; } - + for(i=0; h->h_addr_list[i]; i++) { struct in_addr ia; memcpy(&ia, h->h_addr_list[i],4); @@ -299,7 +299,7 @@ static void * input_plugin_read_loop(void *arg) { fd_set read_fds; while (1) { - + /* System calls are not a thread cancellation point in Linux * pthreads. However, the RT signal sent to cancel the thread * will cause recv() to return with EINTR, and we can manually @@ -339,11 +339,11 @@ static void * input_plugin_read_loop(void *arg) { } else { data = this->packet_buffer; - + if (this->is_rtp) { int pad, ext; int csrc; - + /* Do minimal RTP parsing to extract payload. See * http://www.faqs.org/rfcs/rfc1889.html for header format. * @@ -351,7 +351,7 @@ static void * input_plugin_read_loop(void *arg) { */ if (length < 12) continue; - + pad = data[0] & 0x20; ext = data[0] & 0x10; csrc = data[0] & 0x0f; @@ -361,7 +361,7 @@ static void * input_plugin_read_loop(void *arg) { if (ext) { long hlen; - + if (length < 4) continue; hlen = (data[2] << 8) | data[3]; @@ -382,12 +382,12 @@ static void * input_plugin_read_loop(void *arg) { /* insert data into cyclic buffer */ if (length > 0) { - - /* + + /* * if the buffer is full, wait for the reader - * to signal - */ - + * to signal + */ + pthread_mutex_lock(&this->buffer_ring_mut); /* wait for enough space to write the whole of the recv'ed data */ while( (BUFFER_SIZE - this->buffer_count) < length ) @@ -399,23 +399,23 @@ static void * input_plugin_read_loop(void *arg) { timeout.tv_nsec = tv.tv_usec * 1000; timeout.tv_sec = tv.tv_sec + 2; - + if( pthread_cond_timedwait(&this->writer_cond, &this->buffer_ring_mut, &timeout) != 0 ) { fprintf( stdout, "input_rtp: buffer ring not read within 2 seconds!\n" ); } } - + /* Now there's enough space to write some bytes into the buffer * determine how many bytes can be written. If the buffer wraps * around, write in two pieces: from the head pointer to the - * end of the buffer and from the base to the remaining number + * end of the buffer and from the base to the remaining number * of bytes. */ { long buffer_space_remaining = BUFFER_SIZE - (this->buffer_put_ptr - this->buffer); - + if( buffer_space_remaining >= length ) { /* data fits inside the buffer */ @@ -445,14 +445,17 @@ static void * input_plugin_read_loop(void *arg) { /* END OF PRIVATES */ /* ***************************************************************** */ -static off_t rtp_plugin_read (input_plugin_t *this_gen, +static off_t rtp_plugin_read (input_plugin_t *this_gen, char *buf, off_t length) { rtp_input_plugin_t *this = (rtp_input_plugin_t *) this_gen; struct timeval tv; struct timespec timeout; - off_t copied = 0; - + off_t copied = 0; + + if (length < 0) + return -1; + while(length > 0) { off_t n; @@ -469,7 +472,7 @@ static off_t rtp_plugin_read (input_plugin_t *this_gen, gettimeofday(&tv, NULL); timeout.tv_nsec = tv.tv_usec * 1000; timeout.tv_sec = tv.tv_sec + 5; - + if(pthread_cond_timedwait(&this->reader_cond, &this->buffer_ring_mut, &timeout) != 0) { /* we timed out, no data available */ @@ -480,9 +483,9 @@ static off_t rtp_plugin_read (input_plugin_t *this_gen, /* Now determine how many bytes can be read. If the buffer * will wrap the buffer is read in two pieces, first read - * to the end of the buffer, wrap the tail pointer and + * to the end of the buffer, wrap the tail pointer and * update the buffer count. Finally read the second piece - * from the base to the remaining count + * from the base to the remaining count */ if(length > this->buffer_count) { n = this->buffer_count; @@ -490,26 +493,26 @@ static off_t rtp_plugin_read (input_plugin_t *this_gen, else { n = length; } - + if(((this->buffer_get_ptr - this->buffer) + n) > BUFFER_SIZE) { n = BUFFER_SIZE - (this->buffer_get_ptr - this->buffer); } - + /* the actual read */ memcpy(buf, this->buffer_get_ptr, n); buf += n; copied += n; length -= n; - + /* update the tail pointer, watch for wrap arounds */ this->buffer_get_ptr += n; if(this->buffer_get_ptr - this->buffer >= BUFFER_SIZE) this->buffer_get_ptr = this->buffer; - + this->buffer_count -= n; - - /* signal the writer that there's space in the buffer again */ + + /* signal the writer that there's space in the buffer again */ pthread_cond_signal(&this->writer_cond); pthread_mutex_unlock(&this->buffer_ring_mut); } @@ -524,6 +527,12 @@ static buf_element_t *rtp_plugin_read_block (input_plugin_t *this_gen, buf_element_t *buf = fifo->buffer_pool_alloc (fifo); int total_bytes; + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -545,7 +554,7 @@ static buf_element_t *rtp_plugin_read_block (input_plugin_t *this_gen, */ static off_t rtp_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { - + return -1; } @@ -562,7 +571,7 @@ static off_t rtp_plugin_get_length (input_plugin_t *this_gen) { */ static off_t rtp_plugin_get_current_pos (input_plugin_t *this_gen){ rtp_input_plugin_t *this = (rtp_input_plugin_t *) this_gen; - + return this->curpos; } @@ -570,7 +579,7 @@ static off_t rtp_plugin_get_current_pos (input_plugin_t *this_gen){ * */ static uint32_t rtp_plugin_get_capabilities (input_plugin_t *this_gen) { - + return INPUT_CAP_PREVIEW; } @@ -578,7 +587,7 @@ static uint32_t rtp_plugin_get_capabilities (input_plugin_t *this_gen) { * */ static uint32_t rtp_plugin_get_blocksize (input_plugin_t *this_gen) { - + return 0; } @@ -587,14 +596,14 @@ static uint32_t rtp_plugin_get_blocksize (input_plugin_t *this_gen) { */ static const char* rtp_plugin_get_mrl (input_plugin_t *this_gen) { rtp_input_plugin_t *this = (rtp_input_plugin_t *) this_gen; - + return this->mrl; } /* * */ -static int rtp_plugin_get_optional_data (input_plugin_t *this_gen, +static int rtp_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { rtp_input_plugin_t *this = (rtp_input_plugin_t *) this_gen; @@ -609,11 +618,14 @@ static int rtp_plugin_get_optional_data (input_plugin_t *this_gen, if (data_type == INPUT_OPTIONAL_DATA_PREVIEW) { if (!this->preview_read_done) { this->preview_size = rtp_plugin_read(this_gen, this->preview, MAX_PREVIEW_SIZE); + if (this->preview_size < 0) + this->preview_size = 0; lprintf("Preview data length = %d\n", this->preview_size); this->preview_read_done = 1; } - memcpy(data, this->preview, this->preview_size); + if (this->preview_size) + memcpy(data, this->preview, this->preview_size); return this->preview_size; } else { @@ -623,16 +635,16 @@ static int rtp_plugin_get_optional_data (input_plugin_t *this_gen, static void rtp_plugin_dispose (input_plugin_t *this_gen ) { rtp_input_plugin_t *this = (rtp_input_plugin_t *) this_gen; - + if (this->nbc) nbc_close(this->nbc); - + if (this->rtp_running) { LOG_MSG(this->stream->xine, _("RTP: stopping reading thread...\n")); pthread_cancel(this->reader_thread); pthread_join(this->reader_thread, NULL); LOG_MSG(this->stream->xine, _("RTP: reading thread terminated\n")); } - + if (this->fh != -1) close(this->fh); free(this->buffer); @@ -649,7 +661,7 @@ static int rtp_plugin_open (input_plugin_t *this_gen ) { this->filename, this->port, this->interface); - + this->fh = host_connect(this->filename, this->port, this->interface, this->stream->xine); @@ -660,12 +672,12 @@ static int rtp_plugin_open (input_plugin_t *this_gen ) { this->curpos = 0; this->rtp_running = 1; - if ((err = pthread_create(&this->reader_thread, NULL, + if ((err = pthread_create(&this->reader_thread, NULL, input_plugin_read_loop, (void *)this)) != 0) { LOG_MSG(this->stream->xine, _("input_rtp: can't create new thread (%s)\n"), strerror(err)); _x_abort(); } - + return 1; } @@ -679,7 +691,7 @@ static input_plugin_t *rtp_class_get_instance (input_class_t *cls_gen, char *mrl; int is_rtp = 0; int port = 7658; - + mrl = strdup(data); if (!strncasecmp (mrl, "rtp://", 6)) { @@ -690,12 +702,12 @@ static input_plugin_t *rtp_class_get_instance (input_class_t *cls_gen, filename = &mrl[6]; is_rtp = 0; } - + if (filename == NULL || strlen(filename) == 0) { free(mrl); return NULL; } - + /* Locate the port number */ pptr=strchr(filename, ':'); iptr = NULL; @@ -716,8 +728,8 @@ static input_plugin_t *rtp_class_get_instance (input_class_t *cls_gen, } } } - - this = (rtp_input_plugin_t *) xine_xmalloc(sizeof(rtp_input_plugin_t)); + + this = calloc(1, sizeof(rtp_input_plugin_t)); this->stream = stream; this->mrl = mrl; this->filename = filename; @@ -753,8 +765,8 @@ static input_plugin_t *rtp_class_get_instance (input_class_t *cls_gen, this->input_plugin.get_optional_data = rtp_plugin_get_optional_data; this->input_plugin.dispose = rtp_plugin_dispose; this->input_plugin.input_class = cls_gen; - - this->nbc = NULL; + + this->nbc = NULL; this->nbc = nbc_init(this->stream); return &this->input_plugin; @@ -764,7 +776,7 @@ static input_plugin_t *rtp_class_get_instance (input_class_t *cls_gen, /* * net plugin class */ - + static const char *rtp_class_get_description (input_class_t *this_gen) { return _("RTP and UDP input plugin as shipped with xine"); } @@ -783,8 +795,8 @@ static void *init_class (xine_t *xine, void *data) { rtp_input_class_t *this; - - this = (rtp_input_class_t *) xine_xmalloc(sizeof(rtp_input_class_t)); + + this = calloc(1, sizeof(rtp_input_class_t)); this->config = xine->config; this->xine = xine; @@ -804,7 +816,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT, 17, "rtp", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_rtsp.c b/src/input/input_rtsp.c index 2895edf5d..fbfad0364 100644 --- a/src/input/input_rtsp.c +++ b/src/input/input_rtsp.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2002-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -69,29 +69,28 @@ typedef struct { off_t curpos; - nbc_t *nbc; + nbc_t *nbc; char scratch[BUFSIZE]; } rtsp_input_plugin_t; -static off_t rtsp_plugin_read (input_plugin_t *this_gen, +static off_t rtsp_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; off_t n; lprintf ("rtsp_plugin_read: %"PRId64" bytes ...\n", len); - nbc_check_buffers (this->nbc); - n = rtsp_session_read (this->rtsp, buf, len); - this->curpos += n; + if (n > 0) + this->curpos += n; return n; } -static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen, +static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { /*rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; */ buf_element_t *buf = fifo->buffer_pool_alloc (fifo); @@ -99,9 +98,16 @@ static buf_element_t *rtsp_plugin_read_block (input_plugin_t *this_gen, lprintf ("rtsp_plugin_read_block: %"PRId64" bytes...\n", todo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; - + total_bytes = rtsp_plugin_read (this_gen, (char*)buf->content, todo); if (total_bytes != todo) { @@ -125,10 +131,16 @@ static off_t rtsp_plugin_seek (input_plugin_t *this_gen, off_t offset, int origi if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - this->curpos += rtsp_plugin_read (this_gen, this->scratch, BUFSIZE); + off_t n = rtsp_plugin_read (this_gen, this->scratch, BUFSIZE); + if (n <= 0) + return this->curpos; + this->curpos += n; } - this->curpos += rtsp_plugin_read (this_gen, this->scratch, offset); + off_t n = rtsp_plugin_read (this_gen, this->scratch, offset); + if (n <= 0) + return this->curpos; + this->curpos += n; } return this->curpos; @@ -139,17 +151,17 @@ static off_t rtsp_plugin_seek_time (input_plugin_t *this_gen, int time_offset, i rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; lprintf ("seek_time %d msec, origin %d\n", time_offset, origin); - + if (origin == SEEK_SET) rtsp_session_set_start_time (this->rtsp, time_offset); - + return this->curpos; } static off_t rtsp_plugin_get_length (input_plugin_t *this_gen) { /* - rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; + rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; off_t length; */ @@ -186,13 +198,13 @@ static void rtsp_plugin_dispose (input_plugin_t *this_gen) { nbc_close (this->nbc); this->nbc = NULL; } - + if(this->mrl) free(this->mrl); - + if(this->public_mrl) free(this->public_mrl); - + free (this); } @@ -202,7 +214,7 @@ static const char* rtsp_plugin_get_mrl (input_plugin_t *this_gen) { return this->public_mrl; } -static int rtsp_plugin_get_optional_data (input_plugin_t *this_gen, +static int rtsp_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { rtsp_input_plugin_t *this = (rtsp_input_plugin_t *) this_gen; @@ -233,11 +245,11 @@ static int rtsp_plugin_open (input_plugin_t *this_gen) { } this->rtsp = rtsp; - + return 1; } -static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, +static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *mrl) { /* rtsp_input_class_t *cls = (rtsp_input_class_t *) cls_gen; */ @@ -246,7 +258,7 @@ static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_str if (strncasecmp (mrl, "rtsp://", 6)) return NULL; - this = (rtsp_input_plugin_t *) xine_xmalloc (sizeof (rtsp_input_plugin_t)); + this = calloc(1, sizeof (rtsp_input_plugin_t)); this->stream = stream; this->rtsp = NULL; @@ -254,9 +266,8 @@ static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_str /* since we handle only real streams yet, we can savely add * an .rm extention to force handling by demux_real. */ - this->public_mrl = xine_xmalloc (sizeof (char)*(strlen(this->mrl)+10)); - sprintf(this->public_mrl, "%s.rm", this->mrl); - + asprintf(&this->public_mrl, "%s.rm", this->mrl); + this->nbc = nbc_init (stream); this->input_plugin.open = rtsp_plugin_open; @@ -272,7 +283,7 @@ static input_plugin_t *rtsp_class_get_instance (input_class_t *cls_gen, xine_str this->input_plugin.dispose = rtsp_plugin_dispose; this->input_plugin.get_optional_data = rtsp_plugin_get_optional_data; this->input_plugin.input_class = cls_gen; - + return &this->input_plugin; } @@ -298,7 +309,7 @@ static void *init_class (xine_t *xine, void *data) { rtsp_input_class_t *this; - this = (rtsp_input_class_t *) xine_xmalloc (sizeof (rtsp_input_class_t)); + this = calloc(1, sizeof (rtsp_input_class_t)); this->xine = xine; @@ -318,7 +329,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT, 17, "rtsp", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/input_smb.c b/src/input/input_smb.c index 7da9c1454..5d97d7518 100644 --- a/src/input/input_smb.c +++ b/src/input/input_smb.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2004 the xine project - * + * Copyright (C) 2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -41,7 +41,7 @@ typedef struct { input_class_t input_class; xine_t *xine; - + int mrls_allocated_entries; xine_mrl_t **mrls; } smb_input_class_t; @@ -51,7 +51,7 @@ typedef struct { xine_stream_t *stream; /* File */ - char *mrl; + const char *mrl; int fd; } smb_input_t; @@ -69,6 +69,8 @@ smb_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) smb_input_t *this = (smb_input_t *) this_gen; off_t n, num_bytes; + if (len < 0) + return -1; num_bytes = 0; while (num_bytes < len) @@ -89,6 +91,13 @@ smb_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t total_bytes; buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -129,7 +138,7 @@ smb_plugin_get_length (input_plugin_t *this_gen) int e; struct stat st; - + if (this->fd>=0) e = smbc_fstat(this->fd,&st); else e = smbc_stat(this->mrl,&st); @@ -138,7 +147,7 @@ smb_plugin_get_length (input_plugin_t *this_gen) return st.st_size; } -static char* +static const char* smb_plugin_get_mrl (input_plugin_t *this_gen) { smb_input_t *this = (smb_input_t *) this_gen; @@ -150,7 +159,7 @@ static uint32_t smb_plugin_get_blocksize (input_plugin_t *this_gen) { return 0; } -static char +static const char *smb_class_get_description (input_class_t *this_gen) { return _("CIFS/SMB input plugin based on libsmbclient"); @@ -209,20 +218,20 @@ static int _strverscmp(const char *s1, const char *s2) { c2 = *p2++; state |= (c1 == '0') + (ISDIGIT(c1) != 0); } - + state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT(c2) != 0))]; - + switch(state) { case CMP: return diff; - + case LEN: while(ISDIGIT(*p1++)) if(!ISDIGIT(*p2++)) return 1; - + return ISDIGIT(*p2) ? -1 : diff; - + default: return state; } @@ -236,9 +245,9 @@ static int _sortfiles_default(const xine_mrl_t *s1, const xine_mrl_t *s2) { } -static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, +static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, const char *filename, int *nFiles) { - + smb_input_class_t *this = (smb_input_class_t *) this_gen; int (*func) () = _sortfiles_default; int dir; @@ -254,38 +263,33 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, snprintf(current_path, XINE_PATH_MAX, "smb:/"); snprintf(current_path_smb, XINE_PATH_MAX, "smb://"); } - + if ((dir = smbc_opendir(current_path_smb)) >= 0){ - xine_mrl_t *dir_files = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t) * MAXFILES); - xine_mrl_t *norm_files = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t) * MAXFILES); - int num_dir_files=0; + xine_mrl_t *dir_files = (xine_mrl_t *) calloc(MAXFILES, sizeof(xine_mrl_t)); + xine_mrl_t *norm_files = (xine_mrl_t *) calloc(MAXFILES, sizeof(xine_mrl_t)); + int num_dir_files=0; int num_norm_files=0; while ((pdirent = smbc_readdir(dir)) != NULL){ if (pdirent->smbc_type == SMBC_WORKGROUP){ dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].origin = strdup(current_path); - dir_files[num_dir_files].mrl = (char *) xine_xmalloc( - strlen(current_path) + 1 + strlen(pdirent->name) + 1); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", current_path, pdirent->name); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", current_path, pdirent->name); dir_files[num_dir_files].size = pdirent->dirlen; num_dir_files ++; - }else if (pdirent->smbc_type == SMBC_SERVER){ + }else if (pdirent->smbc_type == SMBC_SERVER){ if (num_dir_files == 0) { dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].origin = strdup("smb:/"); - dir_files[num_dir_files].mrl = (char *) xine_xmalloc(strlen("smb:/") + 4); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", "smb:/", ".."); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", "smb:/", ".."); dir_files[num_dir_files].size = pdirent->dirlen; num_dir_files ++; } dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].origin = strdup("smb:/"); - dir_files[num_dir_files].mrl = - (char *) xine_xmalloc(strlen("smb:/") + 1 + strlen(pdirent->name) + 1); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", "smb:/", pdirent->name); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", "smb:/", pdirent->name); dir_files[num_dir_files].size = pdirent->dirlen; num_dir_files ++; } else if (pdirent->smbc_type == SMBC_FILE_SHARE){ @@ -293,9 +297,7 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].origin = strdup(current_path); - dir_files[num_dir_files].mrl = (char *) xine_xmalloc( - strlen(current_path) + 3); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", current_path, ".."); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", current_path, ".."); dir_files[num_dir_files].type |= mrl_file_directory; dir_files[num_dir_files].size = pdirent->dirlen; num_dir_files ++; @@ -304,28 +306,22 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].origin = strdup(current_path); - dir_files[num_dir_files].mrl = (char *) xine_xmalloc( - strlen(current_path) + 1 + strlen(pdirent->name) + 1); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", current_path, pdirent->name); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", current_path, pdirent->name); dir_files[num_dir_files].size = pdirent->dirlen; num_dir_files ++; - } + } } else if (pdirent->smbc_type == SMBC_DIR){ dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].origin = strdup(current_path); - dir_files[num_dir_files].mrl = - (char *) xine_xmalloc(strlen(current_path) + 1 + strlen(pdirent->name) + 1); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", current_path, pdirent->name); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", current_path, pdirent->name); dir_files[num_dir_files].size = pdirent->dirlen; num_dir_files ++; }else if (pdirent->smbc_type == SMBC_FILE){ norm_files[num_norm_files].link = NULL; norm_files[num_norm_files].type = mrl_file | mrl_file_normal; norm_files[num_norm_files].origin = strdup(current_path); - norm_files[num_norm_files].mrl = - (char *) xine_xmalloc(strlen(current_path) + 1 + strlen(pdirent->name) + 1); - sprintf(norm_files[num_norm_files].mrl, "%s/%s", current_path, pdirent->name); + asprintf(&(norm_files[num_norm_files].mrl), "%s/%s", current_path, pdirent->name); norm_files[num_norm_files].size = pdirent->dirlen; num_norm_files ++; } @@ -335,8 +331,7 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, if (num_dir_files == 0) { dir_files[num_dir_files].link = NULL; dir_files[num_dir_files].origin = strdup(current_path); - dir_files[num_dir_files].mrl = (char *) xine_xmalloc(strlen(current_path) + 4); - sprintf(dir_files[num_dir_files].mrl, "%s/%s", current_path, ".."); + asprintf(&(dir_files[num_dir_files].mrl), "%s/%s", current_path, ".."); dir_files[num_dir_files].type = mrl_file | mrl_file_directory; dir_files[num_dir_files].size = 0; num_dir_files ++; @@ -347,49 +342,49 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, */ if(num_dir_files) qsort(dir_files, num_dir_files, sizeof(xine_mrl_t), func); - + if(num_norm_files) qsort(norm_files, num_norm_files, sizeof(xine_mrl_t), func); - + /* * Add directories entries */ for(i = 0; i < num_dir_files; i++) { if (num_files >= this->mrls_allocated_entries) { ++this->mrls_allocated_entries; - this->mrls = realloc(this->mrls, + this->mrls = realloc(this->mrls, (this->mrls_allocated_entries+1) * sizeof(xine_mrl_t*)); - this->mrls[num_files] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[num_files] = calloc(1, sizeof(xine_mrl_t)); }else memset(this->mrls[num_files], 0, sizeof(xine_mrl_t)); - - MRL_DUPLICATE(&dir_files[i], this->mrls[num_files]); + + MRL_DUPLICATE(&dir_files[i], this->mrls[num_files]); num_files++; } - - /* + + /* * Add other files entries */ for(i = 0; i < num_norm_files; i++) { if(num_files >= this->mrls_allocated_entries) { ++this->mrls_allocated_entries; - this->mrls = realloc(this->mrls, + this->mrls = realloc(this->mrls, (this->mrls_allocated_entries+1) * sizeof(xine_mrl_t*)); - this->mrls[num_files] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[num_files] = calloc(1, sizeof(xine_mrl_t)); }else memset(this->mrls[num_files], 0, sizeof(xine_mrl_t)); - MRL_DUPLICATE(&norm_files[i], this->mrls[num_files]); + MRL_DUPLICATE(&norm_files[i], this->mrls[num_files]); num_files++; } - + /* Some cleanups before leaving */ for(i = num_dir_files; i == 0; i--) MRL_ZERO(&dir_files[i]); free(dir_files); - + for(i = num_norm_files; i == 0; i--) MRL_ZERO(&norm_files[i]); free(norm_files); @@ -399,13 +394,13 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, current_path, errno, strerror(errno)); *nFiles = 0; return NULL; - } - + } + /* * Inform caller about files found number. */ *nFiles = num_files; - + /* * Freeing exceeded mrls if exists. */ @@ -413,7 +408,7 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, MRL_ZERO(this->mrls[this->mrls_allocated_entries - 1]); free(this->mrls[this->mrls_allocated_entries--]); } - + /* * This is useful to let UI know where it should stops ;-). */ @@ -423,7 +418,7 @@ static xine_mrl_t **smb_class_get_dir (input_class_t *this_gen, } static int -smb_plugin_get_optional_data (input_plugin_t *this_gen, +smb_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { return INPUT_OPTIONAL_UNSUPPORTED; @@ -437,7 +432,7 @@ smb_plugin_dispose (input_plugin_t *this_gen ) if (this->fd>=0) smbc_close(this->fd); if (this->mrl) - free (this->mrl); + free ((char *)this->mrl); free (this); } @@ -448,8 +443,8 @@ smb_plugin_open (input_plugin_t *this_gen ) smb_input_class_t *class = (smb_input_class_t *) this_gen->input_class; this->fd = smbc_open(this->mrl,O_RDONLY,0); - xprintf(class->xine, XINE_VERBOSITY_DEBUG, - "input_smb: open failed for %s: %s\n", + xprintf(class->xine, XINE_VERBOSITY_DEBUG, + "input_smb: open failed for %s: %s\n", this->mrl, strerror(errno)); if (this->fd<0) return 0; @@ -469,13 +464,13 @@ smb_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, const char *mrl) { smb_input_t *this; - + if (mrl == NULL) return NULL; if (strncmp (mrl, "smb://",6)) return NULL; - this = (smb_input_t *)xine_xmalloc(sizeof(smb_input_t)); + this = calloc(1, sizeof(smb_input_t)); this->stream = stream; this->mrl = strdup (mrl); this->fd = -1; @@ -513,8 +508,8 @@ static void if (smbc_init(smb_auth,(xine->verbosity >= XINE_VERBOSITY_DEBUG))) goto _exit_error; - - this = (smb_input_class_t *) xine_xmalloc(sizeof(smb_input_class_t)); + + this = calloc(1, sizeof(smb_input_class_t)); this->xine = xine; this->input_class.get_instance = smb_class_get_instance; @@ -531,7 +526,7 @@ static void setlocale(LC_MESSAGES, lcl); free(lcl); #endif - + return (input_class_t *) this; } diff --git a/src/input/input_stdin_fifo.c b/src/input/input_stdin_fifo.c index 465e9c00b..74f2a1014 100644 --- a/src/input/input_stdin_fifo.c +++ b/src/input/input_stdin_fifo.c @@ -2,17 +2,17 @@ * Copyright (C) 2000-2003 the xine project * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -78,13 +78,15 @@ static off_t stdin_plugin_get_current_pos (input_plugin_t *this_gen); -static off_t stdin_plugin_read (input_plugin_t *this_gen, +static off_t stdin_plugin_read (input_plugin_t *this_gen, char *buf, off_t len) { stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; off_t n, total; lprintf ("reading %"PRId64" bytes...\n", len); + if (len < 0) + return -1; total=0; if (this->curpos < this->preview_size) { @@ -102,7 +104,7 @@ static off_t stdin_plugin_read (input_plugin_t *this_gen, n = _x_io_file_read (this->stream, this->fh, &buf[total], len - total); lprintf ("got %"PRId64" bytes (%"PRId64"/%"PRId64" bytes read)\n", n,total,len); - + if (n < 0) { _x_message(this->stream, XINE_MSG_READ_ERROR, NULL); return 0; @@ -114,13 +116,20 @@ static off_t stdin_plugin_read (input_plugin_t *this_gen, return total; } -static buf_element_t *stdin_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, +static buf_element_t *stdin_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { off_t total_bytes; /* stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; */ buf_element_t *buf = fifo->buffer_pool_alloc (fifo); + if (todo > buf->max_size) + todo = buf->max_size; + if (todo < 0) { + buf->free_buffer (buf); + return NULL; + } + buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -146,7 +155,7 @@ static off_t stdin_plugin_seek (input_plugin_t *this_gen, off_t offset, int orig if ((origin == SEEK_CUR) && (offset >= 0)) { for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -157,18 +166,18 @@ static off_t stdin_plugin_seek (input_plugin_t *this_gen, off_t offset, int orig if (offset < this->curpos) { - if( this->curpos <= this->preview_size ) + if( this->curpos <= this->preview_size ) this->curpos = offset; else - xprintf (this->xine, XINE_VERBOSITY_LOG, - _("stdin: cannot seek back! (%" PRIdMAX " > %" PRIdMAX ")\n"), + xprintf (this->xine, XINE_VERBOSITY_LOG, + _("stdin: cannot seek back! (%" PRIdMAX " > %" PRIdMAX ")\n"), (intmax_t)this->curpos, (intmax_t)offset); } else { offset -= this->curpos; for (;((int)offset) - BUFSIZE > 0; offset -= BUFSIZE) { - if( !this_gen->read (this_gen, this->seek_buf, BUFSIZE) ) + if( this_gen->read (this_gen, this->seek_buf, BUFSIZE) <= 0 ) return this->curpos; } @@ -185,7 +194,7 @@ static off_t stdin_plugin_get_length(input_plugin_t *this_gen) { } static uint32_t stdin_plugin_get_capabilities(input_plugin_t *this_gen) { - + return INPUT_CAP_PREVIEW; } @@ -209,17 +218,17 @@ static const char* stdin_plugin_get_mrl (input_plugin_t *this_gen) { static void stdin_plugin_dispose (input_plugin_t *this_gen ) { stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; - if (this->nbc) + if (this->nbc) nbc_close (this->nbc); if ((this->fh != STDIN_FILENO) && (this->fh != -1)) close(this->fh); - + free (this->mrl); free (this); } -static int stdin_plugin_get_optional_data (input_plugin_t *this_gen, +static int stdin_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { stdin_input_plugin_t *this = (stdin_input_plugin_t *) this_gen; @@ -270,13 +279,15 @@ static int stdin_plugin_open (input_plugin_t *this_gen ) { this->preview_size = stdin_plugin_read (&this->input_plugin, this->preview, MAX_PREVIEW_SIZE); + if (this->preview_size < 0) + this->preview_size = 0; this->curpos = 0; return 1; } -static input_plugin_t *stdin_class_get_instance (input_class_t *class_gen, +static input_plugin_t *stdin_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, const char *data) { stdin_input_class_t *class = (stdin_input_class_t *) class_gen; @@ -311,7 +322,7 @@ static input_plugin_t *stdin_class_get_instance (input_class_t *class_gen, * => create plugin instance */ - this = (stdin_input_plugin_t *) xine_xmalloc(sizeof(stdin_input_plugin_t)); + this = calloc(1, sizeof(stdin_input_plugin_t)); this->stream = stream; this->curpos = 0; @@ -362,7 +373,7 @@ static void *init_class (xine_t *xine, void *data) { stdin_input_class_t *this; - this = (stdin_input_class_t *) xine_xmalloc (sizeof (stdin_input_class_t)); + this = calloc(1, sizeof (stdin_input_class_t)); this->xine = xine; diff --git a/src/input/input_v4l.c b/src/input/input_v4l.c index b43a2684a..e3af41f85 100644 --- a/src/input/input_v4l.c +++ b/src/input/input_v4l.c @@ -1,19 +1,19 @@ /* - * Copyright (C) 2003-2004 the xine project + * Copyright (C) 2003-2008 the xine project * Copyright (C) 2003 J.Asselman <j.asselman@itsec-ps.nl> - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -65,7 +65,7 @@ #define LOG_MODULE "input_v4l" #define LOG_VERBOSE /* -#define LOG +#define LOG */ #include "xine_internal.h" @@ -91,13 +91,15 @@ static const resolution_t resolutions[] = { }; #define NUM_RESOLUTIONS (sizeof(resolutions)/sizeof(resolutions[0])) -#define RADIO_DEV "/dev/v4l/radio0" -#define VIDEO_DEV "/dev/v4l/video0" - -#if !defined(NDELAY) && defined(O_NDELAY) -#define FNDELAY O_NDELAY +#define RADIO_DEV "/dev/radio0" +#define VIDEO_DEV "/dev/video0" +#ifdef HAVE_ALSA +#define AUDIO_DEV "plughw:0,0" #endif +static char *tv_standard_names[] = { "AUTO", "PAL", "NTSC", "SECAM", "OLD", NULL }; +static int tv_standard_values[] = { VIDEO_MODE_AUTO, VIDEO_MODE_PAL, VIDEO_MODE_NTSC, VIDEO_MODE_SECAM, -1 }; + typedef struct pvrscr_s pvrscr_t; typedef struct { @@ -107,7 +109,7 @@ typedef struct { typedef struct { input_plugin_t input_plugin; - + xine_stream_t *stream; char *mrl; @@ -117,7 +119,11 @@ typedef struct { int old_zoomx; int old_zoomy; int audio_only; - + + buf_element_t *frames_base; + void *audio_content_base; + void *video_content_base; + /* Audio */ buf_element_t *aud_frames; pthread_mutex_t aud_frames_lock; @@ -126,32 +132,32 @@ typedef struct { #ifdef HAVE_ALSA /* Handle for the PCM device */ snd_pcm_t *pcm_handle; - + /* Record stream (via line 1) */ snd_pcm_stream_t pcm_stream; - + /* Information and configuration for the PCM stream */ snd_pcm_hw_params_t *pcm_hwparams; /* Name of the PCM device, plughw:0,0?=>soundcard,device*/ - char *pcm_name; - + char *pcm_name; + /* Use alsa to capture the sound (for a/v sync) */ char audio_capture; - + int exact_rate; /* Actual sample rate sndpcm_hw_params_set_rate_near */ int dir; /* exact rate == rate --> dir = 0 exact rate < rate --> dir = -1 exact rate > rate --> dir = 1 */ - + unsigned char *pcm_data; - + int64_t pts_aud_start; #endif int audio_header_sent; - + int rate; /* Sample rate */ int periods; /* Number of periods */ int periodsize; /* Periodsize in bytes */ @@ -180,9 +186,9 @@ typedef struct { struct video_audio audio; struct video_audio audio_saved; struct video_mbuf gb_buffers; - + int video_header_sent; - + int frame_format; const resolution_t *resolution; int frame_size; @@ -219,13 +225,13 @@ typedef struct { struct pvrscr_s { scr_plugin_t scr; - + struct timeval cur_time; int64_t cur_pts; int xine_speed; double speed_factor; double speed_tuning; - + pthread_mutex_t lock; }; @@ -240,47 +246,47 @@ static void pvrscr_set_pivot(pvrscr_t *this) struct timeval tv; int64_t pts; double pts_calc; - + xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; - + /* This next part introduces a one off inaccuracy * to the scr due to rounding tv to pts. */ this->cur_time.tv_sec = tv.tv_sec; this->cur_time.tv_usec = tv.tv_usec; this->cur_pts = pts; - + return; } static int pvrscr_set_fine_speed (scr_plugin_t *scr, int speed) { pvrscr_t *this = (pvrscr_t*) scr; - + pthread_mutex_lock (&this->lock); - + pvrscr_set_pivot( this ); this->xine_speed = speed; this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL * this->speed_tuning; - + pthread_mutex_unlock (&this->lock); - + return speed; } static void pvrscr_speed_tuning (pvrscr_t *this, double factor) { pthread_mutex_lock (&this->lock); - + pvrscr_set_pivot( this ); this->speed_tuning = factor; this->speed_factor = (double) this->xine_speed * 90000.0 / XINE_FINE_SPEED_NORMAL * this->speed_tuning; - + pthread_mutex_unlock (&this->lock); } @@ -288,28 +294,28 @@ static void pvrscr_adjust (scr_plugin_t *scr, int64_t vpts) { pvrscr_t *this = (pvrscr_t*) scr; struct timeval tv; - + pthread_mutex_lock (&this->lock); - + xine_monotonic_clock(&tv, NULL); this->cur_time.tv_sec = tv.tv_sec; this->cur_time.tv_usec = tv.tv_usec; this->cur_pts = vpts; - + pthread_mutex_unlock (&this->lock); } static void pvrscr_start (scr_plugin_t *scr, int64_t start_vpts) { pvrscr_t *this = (pvrscr_t*) scr; - + pthread_mutex_lock (&this->lock); - + xine_monotonic_clock(&this->cur_time, NULL); this->cur_pts = start_vpts; pthread_mutex_unlock (&this->lock); - + pvrscr_set_fine_speed (&this->scr, XINE_FINE_SPEED_NORMAL); } @@ -319,17 +325,17 @@ static int64_t pvrscr_get_current (scr_plugin_t *scr) struct timeval tv; int64_t pts; double pts_calc; - + pthread_mutex_lock (&this->lock); - + xine_monotonic_clock(&tv, NULL); - + pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; - + pthread_mutex_unlock (&this->lock); - + /*printf("returning pts %lld\n", pts);*/ return pts; } @@ -337,17 +343,17 @@ static int64_t pvrscr_get_current (scr_plugin_t *scr) static void pvrscr_exit (scr_plugin_t *scr) { pvrscr_t *this = (pvrscr_t*) scr; - + pthread_mutex_destroy (&this->lock); free(this); } -static pvrscr_t* pvrscr_init (void) +static pvrscr_t *XINE_MALLOC pvrscr_init (void) { pvrscr_t *this; - - this = (pvrscr_t *) xine_xmalloc(sizeof(pvrscr_t)); - + + this = calloc(1, sizeof(pvrscr_t)); + this->scr.interface_version = 3; this->scr.get_priority = pvrscr_get_priority; this->scr.set_fine_speed = pvrscr_set_fine_speed; @@ -355,7 +361,7 @@ static pvrscr_t* pvrscr_init (void) this->scr.start = pvrscr_start; this->scr.get_current = pvrscr_get_current; this->scr.exit = pvrscr_exit; - + pthread_mutex_init (&this->lock, NULL); pvrscr_speed_tuning(this, 1.0 ); @@ -363,7 +369,7 @@ static pvrscr_t* pvrscr_init (void) #ifdef SCRLOG printf("input_v4l: scr init complete\n"); #endif - + return this; } @@ -374,7 +380,7 @@ static void report_progress (xine_stream_t *stream, int p) { xine_event_t event; xine_progress_data_t prg; - + if (p == SCR_PAUSED) { prg.description = _("Buffer underrun..."); p = 0; @@ -384,13 +390,13 @@ static void report_progress (xine_stream_t *stream, int p) p = 100; } else prg.description = _("Adjusting..."); - + prg.percent = (p>100)?100:p; - + event.type = XINE_EVENT_PROGRESS; event.data = &prg; event.data_length = sizeof (xine_progress_data_t); - + xine_event_send (stream, &event); } @@ -406,25 +412,25 @@ static void v4l_event_handler(v4l_input_plugin_t *this); inline static buf_element_t *alloc_aud_frame (v4l_input_plugin_t *this) { buf_element_t *frame; - + lprintf("alloc_aud_frame. trying to get lock...\n"); pthread_mutex_lock (&this->aud_frames_lock) ; - + lprintf("got the lock\n"); - + while (!this->aud_frames) { lprintf("no audio frame available...\n"); pthread_cond_wait (&this->aud_frame_freed, &this->aud_frames_lock); } - + frame = this->aud_frames; this->aud_frames = this->aud_frames->next; - + pthread_mutex_unlock (&this->aud_frames_lock); - + lprintf("alloc_aud_frame done\n"); - + return frame; } @@ -438,10 +444,10 @@ static void store_aud_frame (buf_element_t *frame) lprintf("store_aud_frame\n"); pthread_mutex_lock (&this->aud_frames_lock) ; - + frame->next = this->aud_frames; this->aud_frames = frame; - + pthread_cond_signal (&this->aud_frame_freed); pthread_mutex_unlock (&this->aud_frames_lock); } @@ -458,19 +464,19 @@ inline static buf_element_t *alloc_vid_frame (v4l_input_plugin_t *this) pthread_mutex_lock (&this->vid_frames_lock) ; lprintf("got the lock\n"); - + while (!this->vid_frames) { lprintf("no video frame available...\n"); pthread_cond_wait (&this->vid_frame_freed, &this->vid_frames_lock); } - + frame = this->vid_frames; this->vid_frames = this->vid_frames->next; - + pthread_mutex_unlock (&this->vid_frames_lock); - + lprintf("alloc_vid_frame done\n"); - + return frame; } @@ -481,50 +487,50 @@ static void store_vid_frame (buf_element_t *frame) { v4l_input_plugin_t *this = (v4l_input_plugin_t *) frame->source; - + lprintf("store_vid_frame\n"); - + pthread_mutex_lock (&this->vid_frames_lock) ; frame->next = this->vid_frames; this->vid_frames = frame; - + pthread_cond_signal (&this->vid_frame_freed); pthread_mutex_unlock (&this->vid_frames_lock); } -static int extract_mrl(v4l_input_plugin_t *this, char *mrl) +static int extract_mrl(v4l_input_plugin_t *this, char *mrl) { char *tuner_name = NULL; int frequency = 0; char *locator = NULL; char *begin = NULL; - + if (mrl == NULL) { lprintf("Someone passed an empty mrl\n"); return 0; } - + for (locator = mrl; *locator != '\0' && *locator != '/' ; locator++); - + /* Get tuner name */ if (*locator == '/') { begin = ++locator; - + for (; *locator != '\0' && *locator != '/' ; locator++); - + tuner_name = (char *) strndup(begin, locator - begin); - - /* Get frequency, if available */ + + /* Get frequency, if available */ sscanf(locator, "/%d", &frequency); - + /* cannot use xprintf to log in this routine */ lprintf("input_v4l: Tuner name: %s frequency %d\n", tuner_name, frequency ); } - + this->frequency = frequency; this->tuner_name = tuner_name; - + return 1; } @@ -532,30 +538,36 @@ static int set_frequency(v4l_input_plugin_t *this, unsigned long frequency) { int ret = 0; int fd; - + if (this->video_fd > 0) fd = this->video_fd; else fd = this->radio_fd; - + if (frequency != 0) { + /* FIXME: Don't assume tuner 0 ? */ + this->tuner = 0; + ret = ioctl(fd, VIDIOCSTUNER, &this->tuner); + lprintf("(%d) Response on set tuner to %d\n", ret, this->tuner); + this->video_tuner.tuner = this->tuner; + if (this->video_tuner.flags & VIDEO_TUNER_LOW) { this->calc_frequency = frequency * 16; } else { this->calc_frequency = (frequency * 16) / 1000; } - + ret = ioctl(fd, VIDIOCSFREQ, &this->calc_frequency); lprintf("IOCTL set frequency (%ld) returned: %d\n", frequency, ret); } else { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: No frequency given. Expected syntax: v4l:/tuner/frequency\n" "input_v4l: Using currently tuned settings\n"); } - + this->frequency = frequency; - + if (ret < 0) return ret; else @@ -565,11 +577,11 @@ static int set_frequency(v4l_input_plugin_t *this, unsigned long frequency) static int set_input_source(v4l_input_plugin_t *this, char *input_source) { int ret = 0; - + if ((ret = search_by_channel(this, input_source)) != 1) { ret = search_by_tuner(this, input_source); } - + return ret; } @@ -578,23 +590,23 @@ static int search_by_tuner(v4l_input_plugin_t *this, char *input_source) int ret = 0; int fd = 0; int cur_tuner = 0; - + if (this->video_fd > 0) fd = this->video_fd; else fd = this->radio_fd; - + this->video_tuner.tuner = cur_tuner; ioctl(fd, VIDIOCGCAP, &this->video_cap); - + lprintf("This device has %d channel(s)\n", this->video_cap.channels); - + for (ret = ioctl(fd, VIDIOCGTUNER, &this->video_tuner); ret == 0 && this->video_cap.channels > cur_tuner && strstr(this->video_tuner.name, input_source) == NULL; cur_tuner++) { - + this->video_tuner.tuner = cur_tuner; - + lprintf("(%d) V4L device currently set to: \n", ret); lprintf("Tuner: %d\n", this->video_tuner.tuner); lprintf("Name: %s\n", this->video_tuner.name); @@ -604,7 +616,7 @@ static int search_by_tuner(v4l_input_plugin_t *this, char *input_source) lprintf("Range: %ld - %ld\n", this->video_tuner.rangelow * 1000 / 16, this->video_tuner.rangehigh * 1000 / 16); } } - + lprintf("(%d) V4L device final: \n", ret); lprintf("Tuner: %d\n", this->video_tuner.tuner); lprintf("Name: %s\n", this->video_tuner.name); @@ -613,10 +625,10 @@ static int search_by_tuner(v4l_input_plugin_t *this, char *input_source) } else { lprintf("Range: %ld - %ld\n", this->video_tuner.rangelow * 1000 / 16, this->video_tuner.rangehigh * 1000 / 16); } - + if (strstr(this->video_tuner.name, input_source) == NULL) return -1; - + return 1; } @@ -624,22 +636,23 @@ static int search_by_channel(v4l_input_plugin_t *this, char *input_source) { int ret = 0; int fd = 0; + cfg_entry_t *tv_standard_entry; lprintf("input_source: %s\n", input_source); - + this->input = 0; - + if (this->video_fd > 0) fd = this->video_fd; else fd = this->radio_fd; - + /* Tune into channel */ if (strlen(input_source) > 0) { for( this->video_channel.channel = 0; ioctl(fd, VIDIOCGCHAN, &this->video_channel) == 0; this->video_channel.channel++ ) { - + lprintf("V4L device currently set to:\n"); lprintf("Channel: %d\n", this->video_channel.channel); lprintf("Name: %s\n", this->video_channel.name); @@ -653,34 +666,33 @@ static int search_by_channel(v4l_input_plugin_t *this, char *input_source) break; } } - + if (strstr(this->video_channel.name, input_source) == NULL) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("Tuner name not found\n")); return -1; } - + + tv_standard_entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, + "media.video4linux.tv_standard"); this->tuner_name = input_source; - ret = ioctl(fd, VIDIOCSCHAN, &this->input); - + if (tv_standard_entry->num_value != 0) { + this->video_channel.norm = tv_standard_values[ tv_standard_entry->num_value ]; + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "input_v4l: TV Standard configured as STD %s (%d)\n", + tv_standard_names[ tv_standard_entry->num_value ], this->video_channel.norm ); + ret = ioctl(fd, VIDIOCSCHAN, &this->video_channel); + } else + ret = ioctl(fd, VIDIOCSCHAN, &this->input); + lprintf("(%d) Set channel to %d\n", ret, this->input); - - /* FIXME: Don't assume tuner 0 ? */ - - this->tuner = 0; - - ret = ioctl(fd, VIDIOCSTUNER, &this->tuner); - - lprintf("(%d) Response on set tuner to %d\n", ret, this->tuner); - - this->video_tuner.tuner = this->tuner; } else { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Not setting video source. No source given\n"); } ret = ioctl(fd, VIDIOCGTUNER, &this->video_tuner); lprintf("(%d) Flags %d\n", ret, this->video_tuner.flags); - + lprintf("VIDEO_TUNER_PAL %s set\n", this->video_tuner.flags & VIDEO_TUNER_PAL ? "" : "not"); lprintf("VIDEO_TUNER_NTSC %s set\n", this->video_tuner.flags & VIDEO_TUNER_NTSC ? "" : "not"); lprintf("VIDEO_TUNER_SECAM %s set\n", this->video_tuner.flags & VIDEO_TUNER_SECAM ? "" : "not"); @@ -689,7 +701,7 @@ static int search_by_channel(v4l_input_plugin_t *this, char *input_source) lprintf("VIDEO_TUNER_STEREO_ON %s set\n", this->video_tuner.flags & VIDEO_TUNER_STEREO_ON ? "" : "not"); lprintf("VIDEO_TUNER_RDS_ON %s set\n", this->video_tuner.flags & VIDEO_TUNER_RDS_ON ? "" : "not"); lprintf("VIDEO_TUNER_MBS_ON %s set\n", this->video_tuner.flags & VIDEO_TUNER_MBS_ON ? "" : "not"); - + switch (this->video_tuner.mode) { case VIDEO_MODE_PAL: lprintf("The tuner is in PAL mode\n"); @@ -705,26 +717,53 @@ static int search_by_channel(v4l_input_plugin_t *this, char *input_source) break; } - return 1; + return 1; } -static void allocate_audio_frames(v4l_input_plugin_t *this) +static void allocate_frames(v4l_input_plugin_t *this, unsigned dovideo) { + const size_t framescount = dovideo ? 2*NUM_FRAMES : NUM_FRAMES; + + /* Allocate a single memory area for both audio and video frames */ + buf_element_t *frames = this->frames_base = + calloc(framescount, sizeof(buf_element_t)); + extra_info_t *infos = + calloc(framescount, sizeof(extra_info_t)); + int i; - + + uint8_t *audio_content = this->audio_content_base = + calloc(NUM_FRAMES, this->periodsize); + + /* Set up audio frames */ for (i = 0; i < NUM_FRAMES; i++) { - buf_element_t *frame; - /* Audio frame */ - frame = xine_xmalloc(sizeof(buf_element_t)); - - frame->content = xine_xmalloc(this->periodsize); - frame->type = BUF_AUDIO_LPCM_LE; - frame->source = this; - frame->free_buffer = store_aud_frame; - frame->extra_info = xine_xmalloc(sizeof(extra_info_t)); - - store_aud_frame(frame); + frames[i].content = audio_content; + frames[i].type = BUF_AUDIO_LPCM_LE; + frames[i].source = this; + frames[i].free_buffer = store_aud_frame; + frames[i].extra_info = &infos[i]; + + audio_content += this->periodsize; + store_aud_frame(&frames[i]); + } + + if ( dovideo ) { + uint8_t *video_content = this->video_content_base = + calloc(NUM_FRAMES, this->frame_size); + + /* Set up video frames */ + for (i = NUM_FRAMES; i < 2*NUM_FRAMES; i++) { + /* Video frame */ + frames[i].content = video_content; + frames[i].type = this->frame_format; + frames[i].source = this; + frames[i].free_buffer = store_vid_frame; + frames[i].extra_info = &infos[i]; + + video_content += this->frame_size; + store_vid_frame(&frames[i]); + } } } @@ -733,12 +772,12 @@ static void unmute_audio(v4l_input_plugin_t *this) int fd; lprintf("unmute_audio\n"); - + if (this->video_fd > 0) fd = this->video_fd; else fd = this->radio_fd; - + ioctl(fd, VIDIOCGAUDIO, &this->audio); memcpy(&this->audio_saved, &this->audio, sizeof(this->audio)); @@ -747,43 +786,43 @@ static void unmute_audio(v4l_input_plugin_t *this) ioctl(fd, VIDIOCSAUDIO, &this->audio); } - + static int open_radio_capture_device(v4l_input_plugin_t *this) { int tuner_found = 0; cfg_entry_t *entry; - + lprintf("open_radio_capture_device\n"); - + entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, "media.video4linux.radio_device"); - + if((this->radio_fd = open(entry->str_value, O_RDWR)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "input_v4l: error opening v4l device (%s): %s\n", + "input_v4l: error opening v4l device (%s): %s\n", entry->str_value, strerror(errno)); return 0; } - + lprintf("Device opened, radio %d\n", this->radio_fd); - + if (set_input_source(this, this->tuner_name) > 0) tuner_found = 1; - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); - + /* Pre-allocate some frames for audio so it doesn't have to be done during * capture */ - allocate_audio_frames(this); - + allocate_frames(this, 0); + this->audio_only = 1; - + /* Unmute audio off video capture device */ unmute_audio(this); - - set_frequency(this, this->frequency); - + + set_frequency(this, this->frequency); + if (tuner_found) return 1; else @@ -801,25 +840,25 @@ static int open_video_capture_device(v4l_input_plugin_t *this) { int found = 0; int tuner_found = 0; - int i, ret; + int ret; unsigned int j; cfg_entry_t *entry; - + lprintf("open_video_capture_device\n"); - - entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, + + entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, "media.video4linux.video_device"); /* Try to open the video device */ if((this->video_fd = open(entry->str_value, O_RDWR)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "input_v4l: error opening v4l device (%s): %s\n", + "input_v4l: error opening v4l device (%s): %s\n", entry->str_value, strerror(errno)); return 0; } - + lprintf("Device opened, tv %d\n", this->video_fd); - + /* figure out the resolution */ for (j = 0; j < NUM_RESOLUTIONS; j++) { @@ -831,7 +870,7 @@ static int open_video_capture_device(v4l_input_plugin_t *this) break; } } - + if (found == 0 || resolutions[j].width < this->video_cap.minwidth || resolutions[j].height < this->video_cap.minheight) { @@ -839,19 +878,15 @@ static int open_video_capture_device(v4l_input_plugin_t *this) lprintf("Grab device does not support any preset resolutions"); return 0; } - + this->resolution = &resolutions[j]; - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); - - /* Pre-allocate some frames for audio and video so it doesn't have to be - * done during capture */ - allocate_audio_frames(this); - + /* Unmute audio off video capture device */ unmute_audio(this); - + if (strlen(this->tuner_name) > 0) { /* Tune into source and given frequency */ if (set_input_source(this, this->tuner_name) <= 0) @@ -859,20 +894,20 @@ static int open_video_capture_device(v4l_input_plugin_t *this) else tuner_found = 1; } - - set_frequency(this, this->frequency); - + + set_frequency(this, this->frequency); + /* Test for mmap video access */ ret = ioctl(this->video_fd,VIDIOCGMBUF, &this->gb_buffers); - + if (ret < 0) { /* Device driver does not support mmap */ /* try to use read based access */ struct video_picture pict; int val; - + ioctl(this->video_fd, VIDIOCGPICT, &pict); - + /* try to choose a suitable video format */ pict.palette = VIDEO_PALETTE_YUV420P; ret = ioctl(this->video_fd, VIDIOCSPICT, &pict); @@ -890,13 +925,13 @@ static int open_video_capture_device(v4l_input_plugin_t *this) } else lprintf("Grab: format YUV 4:2:0\n"); - + this->frame_format = pict.palette; val = 1; ioctl(this->video_fd, VIDIOCCAPTURE, &val); - + this->use_mmap = 0; - + } else { /* Good, device driver support mmap. Mmap the memory */ lprintf("using mmap, size %d\n", this->gb_buffers.size); @@ -910,23 +945,23 @@ static int open_video_capture_device(v4l_input_plugin_t *this) return 0; } this->gb_frame = 0; - + /* start to grab the first frame */ this->gb_buf.frame = (this->gb_frame + 1) % this->gb_buffers.frames; this->gb_buf.height = resolutions[j].height; this->gb_buf.width = resolutions[j].width; this->gb_buf.format = VIDEO_PALETTE_YUV420P; - + ret = ioctl(this->video_fd, VIDIOCMCAPTURE, &this->gb_buf); if (ret < 0 && errno != EAGAIN) { /* try YUV422 */ this->gb_buf.format = VIDEO_PALETTE_YUV422; - + ret = ioctl(this->video_fd, VIDIOCMCAPTURE, &this->gb_buf); } else lprintf("(%d) YUV420 should work\n", ret); - + if (ret < 0) { if (errno != EAGAIN) { lprintf("grab device does not support suitable format\n"); @@ -939,7 +974,7 @@ static int open_video_capture_device(v4l_input_plugin_t *this) this->frame_format = this->gb_buf.format; this->use_mmap = 1; } - + switch(this->frame_format) { case VIDEO_PALETTE_YUV420P: this->frame_format = BUF_VIDEO_I420; @@ -950,29 +985,19 @@ static int open_video_capture_device(v4l_input_plugin_t *this) this->frame_size = resolutions[j].width * resolutions[j].height * 2; break; } - - for (i = 0; i < NUM_FRAMES; i++) { - buf_element_t *frame; - - frame = xine_xmalloc (sizeof (buf_element_t)); - - frame->content = xine_xmalloc (this->frame_size); - frame->type = this->frame_format; - frame->source = this; - frame->free_buffer = store_vid_frame; - frame->extra_info = xine_xmalloc(sizeof(extra_info_t)); - - store_vid_frame(frame); - } - - /* Strip the vbi / sync signal from the image by zooming in */ + + /* Strip the vbi / sync signal from the image by zooming in */ this->old_zoomx = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_X); this->old_zoomy = xine_get_param(this->stream, XINE_PARAM_VO_ZOOM_Y); - + xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, 103); xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_Y, 103); - - /* If we made it here, everything went ok */ + + /* Pre-allocate some frames for audio and video so it doesn't have to be + * done during capture */ + allocate_frames(this, 1); + + /* If we made it here, everything went ok */ this->audio_only = 0; if (tuner_found) return 1; @@ -996,98 +1021,98 @@ static int open_audio_capture_device(v4l_input_plugin_t *this) /* Allocate the snd_pcm_hw_params_t structure on the stack. */ snd_pcm_hw_params_alloca(&this->pcm_hwparams); - + /* If we are not capturing video, open the sound device in blocking mode, * otherwise xine gets too many NULL bufs and doesn't seem to handle them * correctly. If we are capturing video, open the sound device in non- * blocking mode, otherwise we will loose video frames while waiting */ if(!this->audio_only) mode = SND_PCM_NONBLOCK; - + /* Open the PCM device. */ if(snd_pcm_open(&this->pcm_handle, this->pcm_name, this->pcm_stream, mode) < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error opening PCM device: %s\n", this->pcm_name); this->audio_capture = 0; } - + /* Get parameters */ if (this->audio_capture && (snd_pcm_hw_params_any(this->pcm_handle, this->pcm_hwparams) < 0)) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Broken configuration for PCM device: No configurations available\n"); this->audio_capture = 0; } - + /* Set access type */ if (this->audio_capture && (snd_pcm_hw_params_set_access(this->pcm_handle, this->pcm_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error setting SND_PCM_ACCESS_RW_INTERLEAVED\n"); this->audio_capture = 0; } - + /* Set sample format */ if (this->audio_capture && - (snd_pcm_hw_params_set_format(this->pcm_handle, + (snd_pcm_hw_params_set_format(this->pcm_handle, this->pcm_hwparams, SND_PCM_FORMAT_S16_LE) < 0)) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error setting SND_PCM_FORMAT_S16_LE\n"); this->audio_capture = 0; } - + /* Set sample rate */ this->exact_rate = this->rate; if (this->audio_capture && - (snd_pcm_hw_params_set_rate_near(this->pcm_handle, this->pcm_hwparams, + (snd_pcm_hw_params_set_rate_near(this->pcm_handle, this->pcm_hwparams, &this->exact_rate, &this->dir) < 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error setting samplerate\n"); this->audio_capture = 0; } if (this->audio_capture && this->dir != 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Samplerate %d Hz is not supported by your hardware\n", this->rate); - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Using %d instead\n", this->exact_rate); } - + /* Set number of channels */ if (this->audio_capture && (snd_pcm_hw_params_set_channels(this->pcm_handle, this->pcm_hwparams, 2) < 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error setting PCM channels\n"); this->audio_capture = 0; } - + if (this->audio_capture && (snd_pcm_hw_params_set_periods(this->pcm_handle, this->pcm_hwparams, this->periods, 0) < 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error setting PCM periods\n"); this->audio_capture = 0; } - + /* Set buffersize */ if (this->audio_capture && - (snd_pcm_hw_params_set_buffer_size_near(this->pcm_handle, + (snd_pcm_hw_params_set_buffer_size_near(this->pcm_handle, this->pcm_hwparams, &buf_size) < 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error setting PCM buffer size to %d\n", (int)buf_size ); this->audio_capture = 0; } - + /* Apply HW parameter settings */ if (this->audio_capture && (snd_pcm_hw_params(this->pcm_handle, this->pcm_hwparams) < 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error Setting PCM HW params\n"); this->audio_capture = 0; } - + if (this->audio_capture) { lprintf("Allocating memory for PCM capture :%d\n", this->periodsize); this->pcm_data = (unsigned char*) malloc(this->periodsize); } else - this->pcm_data = NULL; - + this->pcm_data = NULL; + lprintf("Audio device succesfully configured\n"); #endif return 0; @@ -1103,30 +1128,30 @@ static int v4l_adjust_realtime_speed(v4l_input_plugin_t *this, fifo_buffer_t *fi { int num_used, num_free; int scr_tuning = this->scr_tuning; - + if (fifo == NULL) return 0; - + num_used = fifo->size(fifo); num_free = NUM_FRAMES - num_used; - + if (!this->audio_only && num_used == 0 && scr_tuning != SCR_PAUSED) { /* Buffer is empty, and we did not pause playback */ report_progress(this->stream, SCR_PAUSED); - - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_v4l: Buffer empty, pausing playback (used: %d, num_free: %d)\n", num_used, num_free); - + _x_set_speed(this->stream, XINE_SPEED_PAUSE); this->stream->xine->clock->set_option (this->stream->xine->clock, CLOCK_SCR_ADJUSTABLE, 0); - + this->scr_tuning = SCR_PAUSED; /* pvrscr_speed_tuning(this->scr, 0.0); */ - + } else if (num_free <= 1 && scr_tuning != SCR_SKIP) { this->scr_tuning = SCR_SKIP; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_v4l: Buffer full, skipping (used: %d, free: %d)\n", num_used, num_free); return 0; } else if (scr_tuning == SCR_PAUSED) { @@ -1134,11 +1159,11 @@ static int v4l_adjust_realtime_speed(v4l_input_plugin_t *this, fifo_buffer_t *fi /* Playback was paused, but we have normal buffer usage again */ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_v4l: Resuming from paused (used: %d, free: %d)\n", num_used, num_free); - + this->scr_tuning = 0; - + pvrscr_speed_tuning(this->scr, 1.0); - + _x_set_speed(this->stream, XINE_SPEED_NORMAL); this->stream->xine->clock->set_option (this->stream->xine->clock, CLOCK_SCR_ADJUSTABLE, 1); } @@ -1163,12 +1188,12 @@ static int v4l_adjust_realtime_speed(v4l_input_plugin_t *this, fifo_buffer_t *fi (scr_tuning < 0 && num_used > num_free)) /* Buffer usage is ok again. Set playback speed to normal */ scr_tuning = 0; - - /* Check if speed adjustment should be changed */ + + /* Check if speed adjustment should be changed */ if (scr_tuning != this->scr_tuning) { this->scr_tuning = scr_tuning; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "input_v4l: scr tuning = %d (used: %d, free: %d)\n", + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "input_v4l: scr tuning = %d (used: %d, free: %d)\n", scr_tuning, num_used, num_free); pvrscr_speed_tuning(this->scr, 1.0 + (0.01 * scr_tuning)); } @@ -1178,13 +1203,13 @@ static int v4l_adjust_realtime_speed(v4l_input_plugin_t *this, fifo_buffer_t *fi * speed */ this->scr_tuning = 0; - + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "input_v4l: scr tuning resetting (used: %d, free: %d\n", num_used, num_free); - + pvrscr_speed_tuning(this->scr, 1.0); } - + return 1; } @@ -1221,15 +1246,15 @@ static buf_element_t *v4l_plugin_read_block (input_plugin_t *this_gen, fifo_buff uint8_t *ptr; static char video = 0; int speed = _x_get_speed(this->stream); - - v4l_event_handler(this); - + + v4l_event_handler(this); + #ifdef HAVE_ALSA if (!this->audio_header_sent) { lprintf("sending audio header\n"); - + buf = alloc_aud_frame (this); - + buf->size = 0; buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; @@ -1237,60 +1262,60 @@ static buf_element_t *v4l_plugin_read_block (input_plugin_t *this_gen, fifo_buff buf->decoder_info[1] = this->exact_rate; buf->decoder_info[2] = this->bits; buf->decoder_info[3] = 2; - + this->audio_header_sent = 1; - + return buf; } -#endif - +#endif + if (!this->audio_only && !this->video_header_sent) { xine_bmiheader bih; - + lprintf("sending video header"); - + bih.biSize = sizeof(xine_bmiheader); bih.biWidth = this->resolution->width; bih.biHeight = this->resolution->height; - + buf = alloc_vid_frame (this); - + buf->size = sizeof(xine_bmiheader); buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; memcpy(buf->content, &bih, sizeof(xine_bmiheader)); - + this->video_header_sent = 1; - - return buf; + + return buf; } - + if (!this->audio_only) { if (!v4l_adjust_realtime_speed(this, fifo, speed)) { return NULL; } } - - if (!this->audio_only) + + if (!this->audio_only) video = !video; else video = 0; - + lprintf("%lld bytes...\n", todo); - - if (this->start_time == 0) + + if (this->start_time == 0) /* Create a start pts value */ this->start_time = get_time(); /* this->stream->xine->clock->get_current_time(this->stream->xine->clock); */ - + if (video) { /* Capture video */ buf = alloc_vid_frame (this); buf->decoder_flags = BUF_FLAG_FRAME_START|BUF_FLAG_FRAME_END; - + this->gb_buf.frame = this->gb_frame; - + lprintf("VIDIOCMCAPTURE\n"); - + while (ioctl(this->video_fd, VIDIOCMCAPTURE, &this->gb_buf) < 0) { lprintf("Upper while loop\n"); if (errno == EAGAIN) { @@ -1302,92 +1327,92 @@ static buf_element_t *v4l_plugin_read_block (input_plugin_t *this_gen, fifo_buff return NULL; } } - + this->gb_frame = (this->gb_frame + 1) % this->gb_buffers.frames; - + while (ioctl(this->video_fd, VIDIOCSYNC, &this->gb_frame) < 0 && (errno == EAGAIN || errno == EINTR)) { lprintf("Waiting for videosync\n"); } - + /* printf ("grabbing frame #%d\n", frame_num); */ - + ptr = this->video_buf + this->gb_buffers.offsets[this->gb_frame]; buf->pts = get_time(); /* this->stream->xine->clock->get_current_time(this->stream->xine->clock); */ - xine_fast_memcpy (buf->content, ptr, this->frame_size); + xine_fast_memcpy (buf->content, ptr, this->frame_size); } #ifdef HAVE_ALSA else if (this->audio_capture) { /* Record audio */ int pcmreturn; - - if ((pcmreturn = snd_pcm_readi(this->pcm_handle, this->pcm_data, (this->periodsize)>> 2)) < 0) { + + if ((pcmreturn = snd_pcm_readi(this->pcm_handle, this->pcm_data, (this->periodsize)>> 2)) < 0) { switch (pcmreturn) { case -EAGAIN: /* No data available at the moment */ break; case -EBADFD: /* PCM device in wrong state */ - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: PCM is not in the right state\n"); break; case -EPIPE: /* Buffer overrun */ - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: PCM buffer Overrun (lost some samples)\n"); /* On buffer overrun we need to re prepare the capturing pcm device */ snd_pcm_prepare(this->pcm_handle); break; case -ESTRPIPE: /* Suspend event */ - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: PCM suspend event occured\n"); break; default: /* Unknown */ - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Unknown PCM error code: %d\n", pcmreturn); snd_pcm_prepare(this->pcm_handle); } } else { /* Succesfully read audio data */ - + if (this->pts_aud_start) { buf = alloc_aud_frame (this); buf->decoder_flags = 0; } - + /* We want the pts on the start of the sample. As the soundcard starts * sampling a new sample as soon as the read function returned with a - * success we will save the current pts and assign the current pts to + * success we will save the current pts and assign the current pts to * that sample when we read it */ - + /* Assign start pts to sample */ if (buf) buf->pts = this->pts_aud_start; - + /* Save start pts */ this->pts_aud_start = get_time(); /* this->stream->xine->clock->get_current_time(this->stream->xine->clock); */ - + if (!buf) /* Skip first sample as we don't have a good pts for this one */ return NULL; - + lprintf("Audio: Data read: %d [%d, %d]. Pos: %d\n", pcmreturn, (int) (*this->pcm_data), (int) (*(this->pcm_data + this->periodsize - 3)), (int) this->curpos); - - + + /* Tell decoder the number of bytes we have read */ - buf->size = pcmreturn<<2; - + buf->size = pcmreturn<<2; + this->curpos++; - + xine_fast_memcpy(buf->content, this->pcm_data, buf->size); } } #endif - + lprintf("read block done\n"); - + return buf; } @@ -1397,7 +1422,7 @@ static buf_element_t *v4l_plugin_read_block (input_plugin_t *this_gen, fifo_buff */ static off_t v4l_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; - + lprintf("seek %lld bytes, origin %d\n", offset, origin); return this->curpos; } @@ -1408,10 +1433,10 @@ static off_t v4l_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin */ static off_t v4l_plugin_get_length (input_plugin_t *this_gen) { /* - v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; + v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; off_t length; */ - + return -1; } @@ -1421,8 +1446,8 @@ static off_t v4l_plugin_get_length (input_plugin_t *this_gen) { */ static uint32_t v4l_plugin_get_capabilities (input_plugin_t *this_gen) { - v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; - + v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; + if (this->audio_only) return 0x10; else @@ -1444,26 +1469,26 @@ static uint32_t v4l_plugin_get_blocksize (input_plugin_t *this_gen) */ static off_t v4l_plugin_get_current_pos (input_plugin_t *this_gen){ v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; - + /* printf ("current pos is %lld\n", this->curpos); */ - + return this->curpos; } /** * Event handler. - * + * * Processes events from a frontend. This way frequencies can be changed * without closing the v4l plugin. */ static void v4l_event_handler (v4l_input_plugin_t *this) { xine_event_t *event; - + while ((event = xine_event_get (this->event_queue))) { xine_set_v4l2_data_t *v4l2_data = event->data; - + switch (event->type) { case XINE_EVENT_SET_V4L2: if( v4l2_data->input != this->input || @@ -1473,25 +1498,25 @@ static void v4l_event_handler (v4l_input_plugin_t *this) { this->input = v4l2_data->input; this->channel = v4l2_data->channel; this->frequency = v4l2_data->frequency; - + lprintf("Switching to input:%d chan:%d freq:%.2f\n", v4l2_data->input, v4l2_data->channel, (float)v4l2_data->frequency); set_frequency(this, this->frequency); - _x_demux_flush_engine(this->stream); + _x_demux_flush_engine(this->stream); } break; /* default: - + lprintf("Got an event, type 0x%08x\n", event->type); */ } - + xine_event_free (event); } -} +} /** * Dispose plugin. @@ -1501,123 +1526,90 @@ static void v4l_event_handler (v4l_input_plugin_t *this) { */ static void v4l_plugin_dispose (input_plugin_t *this_gen) { v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; - + if(this->mrl) free(this->mrl); - + if (this->scr) { this->stream->xine->clock->unregister_scr(this->stream->xine->clock, &this->scr->scr); this->scr->scr.exit(&this->scr->scr); } - + /* Close and free video device */ if (this->tuner_name) free(this->tuner_name); - + /* Close video device only if device was openend */ if (this->video_fd > 0) { - + /* Restore v4l audio volume */ - lprintf("Restoring v4l audio volume %d\n", + lprintf("Restoring v4l audio volume %d\n", ioctl(this->video_fd, VIDIOCSAUDIO, &this->audio_saved)); ioctl(this->video_fd, VIDIOCSAUDIO, &this->audio_saved); - + /* Unmap memory */ - if (this->video_buf != NULL && + if (this->video_buf != NULL && munmap(this->video_buf, this->gb_buffers.size) != 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Could not unmap video memory: %s\n", strerror(errno)); } else lprintf("Succesfully unmapped video memory (size %d)\n", this->gb_buffers.size); - + lprintf("Closing video filehandler %d\n", this->video_fd); - + /* Now close the video device */ if (close(this->video_fd) != 0) - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: Error while closing video file handler: %s\n", strerror(errno)); else lprintf("Video device succesfully closed\n"); - - /* Restore zoom setting */ + + /* Restore zoom setting */ xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_X, this->old_zoomx); xine_set_param(this->stream, XINE_PARAM_VO_ZOOM_Y, this->old_zoomy); } - + if (this->radio_fd > 0) { close(this->radio_fd); } - + #ifdef HAVE_ALSA /* Close audio device */ if (this->pcm_handle) { snd_pcm_drop(this->pcm_handle); snd_pcm_close(this->pcm_handle); } - + if (this->pcm_data) { free(this->pcm_data); } - + if (this->pcm_name) { free(this->pcm_name); } #endif - + if (this->event_queue) xine_event_dispose_queue (this->event_queue); - - lprintf("Freeing allocated audio frames"); - if (this->aud_frames) { - buf_element_t *cur_frame = this->aud_frames; - - while (cur_frame != NULL) { - buf_element_t *next_frame = cur_frame->next; -#ifdef LOG - printf("."); -#endif - if (cur_frame->content) - free(cur_frame->content); - - if (cur_frame->extra_info) - free(cur_frame->extra_info); - - free(cur_frame); - cur_frame = next_frame; - } - } -#ifdef LOG - printf("\n"); -#endif + /* All the frames, both video and audio, are allocated in a single + memory area pointed by the frames_base pointer. The content of + the frames is divided in two areas, one pointed by + audio_content_base and the other by video_content_base. The + extra_info structures are all allocated in the first frame + data. */ + free(this->audio_content_base); + free(this->video_content_base); + if (this->frames_base) + free(this->frames_base->extra_info); + free(this->frames_base); - - lprintf("Freeing allocated video frames"); - if (this->vid_frames) { - buf_element_t *cur_frame = this->vid_frames; - - while (cur_frame != NULL) { - buf_element_t *next_frame = cur_frame->next; -#ifdef LOG - printf("."); -#endif - - if (cur_frame->content) - free(cur_frame->content); - - if (cur_frame->extra_info) - free(cur_frame->extra_info); - - free(cur_frame); - cur_frame = next_frame; - } - } #ifdef LOG printf("\n"); #endif - + free (this); - + lprintf("plugin Bye bye! \n"); } @@ -1628,11 +1620,11 @@ static void v4l_plugin_dispose (input_plugin_t *this_gen) { */ static const char* v4l_plugin_get_mrl (input_plugin_t *this_gen) { v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; - + return this->mrl; } -static int v4l_plugin_get_optional_data (input_plugin_t *this_gen, +static int v4l_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { /* v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; */ @@ -1642,19 +1634,19 @@ static int v4l_plugin_get_optional_data (input_plugin_t *this_gen, static int v4l_plugin_radio_open (input_plugin_t *this_gen) { v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; - + if(open_radio_capture_device(this) != 1) return 0; - + open_audio_capture_device(this); - + #ifdef HAVE_ALSA this->start_time = 0; this->pts_aud_start = 0; this->curpos = 0; this->event_queue = xine_event_new_queue (this->stream); -#endif - +#endif + return 1; } @@ -1663,30 +1655,30 @@ static int v4l_plugin_video_open (input_plugin_t *this_gen) { v4l_input_plugin_t *this = (v4l_input_plugin_t *) this_gen; int64_t time; - + if(!open_video_capture_device(this)) return 0; - + open_audio_capture_device(this); - + #ifdef HAVE_ALSA this->pts_aud_start = 0; #endif this->start_time = 0; this->curpos = 0; - + /* Register our own scr provider */ time = this->stream->xine->clock->get_current_time(this->stream->xine->clock); this->scr = pvrscr_init(); this->scr->scr.start(&this->scr->scr, time); this->stream->xine->clock->register_scr(this->stream->xine->clock, &this->scr->scr); this->scr_tuning = 0; - + /* enable resample method */ this->stream->xine->config->update_num(this->stream->xine->config, "audio.synchronization.av_sync_method", 1); - + this->event_queue = xine_event_new_queue (this->stream); - + return 1; } @@ -1701,46 +1693,50 @@ static input_plugin_t *v4l_class_get_instance (input_class_t *cls_gen, { /* v4l_input_class_t *cls = (v4l_input_class_t *) cls_gen; */ v4l_input_plugin_t *this; +#ifdef HAVE_ALSA + cfg_entry_t *entry; +#endif char *mrl = strdup(data); - + /* Example mrl: v4l:/Television/62500 */ if(!mrl || strncasecmp(mrl, "v4l:/", 5)) { free(mrl); return NULL; } - - this = (v4l_input_plugin_t *) xine_xmalloc (sizeof (v4l_input_plugin_t)); - + + this = calloc(1, sizeof (v4l_input_plugin_t)); + extract_mrl(this, mrl); - - this->stream = stream; - this->mrl = mrl; + + this->stream = stream; + this->mrl = mrl; this->video_buf = NULL; this->video_fd = -1; this->radio_fd = -1; this->event_queue = NULL; this->scr = NULL; #ifdef HAVE_ALSA - this->pcm_name = NULL; this->pcm_data = NULL; this->pcm_hwparams = NULL; - + /* Audio */ this->pcm_stream = SND_PCM_STREAM_CAPTURE; - this->pcm_name = strdup("plughw:0,0"); + entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, + "media.video4linux.audio_device"); + this->pcm_name = strdup (entry->str_value); this->audio_capture = 1; #endif this->rate = 44100; this->periods = 2; this->periodsize = 2 * 8192; this->bits = 16; - + pthread_mutex_init (&this->aud_frames_lock, NULL); pthread_cond_init (&this->aud_frame_freed, NULL); - + pthread_mutex_init (&this->vid_frames_lock, NULL); pthread_cond_init (&this->vid_frame_freed, NULL); - + this->input_plugin.get_capabilities = v4l_plugin_get_capabilities; this->input_plugin.read = v4l_plugin_read; this->input_plugin.read_block = v4l_plugin_read_block; @@ -1752,7 +1748,7 @@ static input_plugin_t *v4l_class_get_instance (input_class_t *cls_gen, this->input_plugin.dispose = v4l_plugin_dispose; this->input_plugin.get_optional_data = v4l_plugin_get_optional_data; this->input_plugin.input_class = cls_gen; - + return &this->input_plugin; } @@ -1762,57 +1758,57 @@ static input_plugin_t *v4l_class_get_video_instance (input_class_t *cls_gen, v4l_input_plugin_t *this = NULL; int is_ok = 1; cfg_entry_t *entry; - + this = (v4l_input_plugin_t *) v4l_class_get_instance (cls_gen, stream, data); - + if (this) this->input_plugin.open = v4l_plugin_video_open; else return NULL; - - entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, + + entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, "media.video4linux.video_device"); - + /* Try to open the video device */ if((this->video_fd = open(entry->str_value, O_RDWR)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "input_v4l: error opening v4l device (%s): %s\n", + "input_v4l: error opening v4l device (%s): %s\n", entry->str_value, strerror(errno)); is_ok = 0; } else lprintf("Device opened, tv %d\n", this->video_fd); - + /* Get capabilities */ if (is_ok && ioctl(this->video_fd, VIDIOCGCAP, &this->video_cap) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: v4l card doesn't support some features needed by xine\n"); is_ok = 0;; } - + if (is_ok && !(this->video_cap.type & VID_TYPE_CAPTURE)) { /* Capture is not supported by the device. This is a must though! */ xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: v4l card doesn't support frame grabbing\n"); is_ok = 0; } - + if (is_ok && set_input_source(this, this->tuner_name) <= 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: unable to locate the tuner name (%s) on your v4l card\n", this->tuner_name); is_ok = 0; } - + if (this->video_fd > 0) { close(this->video_fd); this->video_fd = -1; } - + if (!is_ok) { v4l_plugin_dispose((input_plugin_t *) this); return NULL; } - + return &this->input_plugin; } @@ -1823,45 +1819,45 @@ static input_plugin_t *v4l_class_get_radio_instance (input_class_t *cls_gen, v4l_input_plugin_t *this = NULL; int is_ok = 1; cfg_entry_t *entry; - + if (strstr(data, "Radio") == NULL) return NULL; - + this = (v4l_input_plugin_t *) v4l_class_get_instance (cls_gen, stream, data); - + if (this) this->input_plugin.open = v4l_plugin_radio_open; else return NULL; - - entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, + + entry = this->stream->xine->config->lookup_entry(this->stream->xine->config, "media.video4linux.radio_device"); - + if((this->radio_fd = open(entry->str_value, O_RDWR)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "input_v4l: error opening v4l device (%s): %s\n", + "input_v4l: error opening v4l device (%s): %s\n", entry->str_value, strerror(errno)); is_ok = 0; } else lprintf("Device opened, radio %d\n", this->radio_fd); - + if (is_ok && set_input_source(this, this->tuner_name) <= 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "input_v4l: unable to locate the tuner name (%s) on your v4l card\n", this->tuner_name); is_ok = 0; } - + if (this->radio_fd > 0) { close(this->radio_fd); this->radio_fd = -1; } - + if (!is_ok) { v4l_plugin_dispose((input_plugin_t *) this); return NULL; } - + return &this->input_plugin; } @@ -1870,11 +1866,11 @@ static input_plugin_t *v4l_class_get_radio_instance (input_class_t *cls_gen, * v4l input plugin class stuff */ -static char *v4l_class_get_video_description (input_class_t *this_gen) { +static const char *v4l_class_get_video_description (input_class_t *this_gen) { return _("v4l tv input plugin"); } -static char *v4l_class_get_radio_description (input_class_t *this_gen) { +static const char *v4l_class_get_radio_description (input_class_t *this_gen) { return _("v4l radio input plugin"); } @@ -1884,7 +1880,7 @@ static const char *v4l_class_get_identifier (input_class_t *this_gen) { static void v4l_class_dispose (input_class_t *this_gen) { v4l_input_class_t *this = (v4l_input_class_t *) this_gen; - + free (this); } @@ -1892,11 +1888,11 @@ static void *init_video_class (xine_t *xine, void *data) { v4l_input_class_t *this; config_values_t *config = xine->config; - - this = (v4l_input_class_t *) xine_xmalloc (sizeof (v4l_input_class_t)); - + + this = calloc(1, sizeof (v4l_input_class_t)); + this->xine = xine; - + this->input_class.get_instance = v4l_class_get_video_instance; this->input_class.get_identifier = v4l_class_get_identifier; this->input_class.get_description = v4l_class_get_video_description; @@ -1904,13 +1900,25 @@ static void *init_video_class (xine_t *xine, void *data) this->input_class.get_autoplay_list = NULL; this->input_class.dispose = v4l_class_dispose; this->input_class.eject_media = NULL; - + config->register_filename (config, "media.video4linux.video_device", VIDEO_DEV, XINE_CONFIG_STRING_IS_DEVICE_NAME, _("v4l video device"), _("The path to your Video4Linux video device."), 10, NULL, NULL); - +#ifdef HAVE_ALSA + config->register_filename (config, "media.video4linux.audio_device", + AUDIO_DEV, 0, + _("v4l ALSA audio input device"), + _("The name of the audio device which corresponds " + "to your Video4Linux video device."), + 10, NULL, NULL); +#endif + config->register_enum (config, "media.video4linux.tv_standard", 4 /* old */, + tv_standard_names, _("v4l TV standard"), + _("Selects the TV standard of the input signals. " + "Either: AUTO, PAL, NTSC or SECAM. "), 20, NULL, NULL); + return this; } @@ -1918,11 +1926,11 @@ static void *init_radio_class (xine_t *xine, void *data) { v4l_input_class_t *this; config_values_t *config = xine->config; - - this = (v4l_input_class_t *) xine_xmalloc (sizeof (v4l_input_class_t)); - + + this = calloc(1, sizeof (v4l_input_class_t)); + this->xine = xine; - + this->input_class.get_instance = v4l_class_get_radio_instance; this->input_class.get_identifier = v4l_class_get_identifier; this->input_class.get_description = v4l_class_get_radio_description; @@ -1930,13 +1938,13 @@ static void *init_radio_class (xine_t *xine, void *data) this->input_class.get_autoplay_list = NULL; this->input_class.dispose = v4l_class_dispose; this->input_class.eject_media = NULL; - + config->register_filename (config, "media.video4linux.radio_device", RADIO_DEV, XINE_CONFIG_STRING_IS_DEVICE_NAME, _("v4l radio device"), _("The path to your Video4Linux radio device."), 10, NULL, NULL); - + return this; } @@ -1945,12 +1953,12 @@ static void *init_radio_class (xine_t *xine, void *data) */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "v4l_radio", XINE_VERSION_CODE, NULL, init_radio_class }, { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "v4l_tv", XINE_VERSION_CODE, NULL, init_video_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; /* - * vim:sw=3:sts=3: + * vim:sw=3:sts=3: */ diff --git a/src/input/input_vcd.c b/src/input/input_vcd.c index 007fa5946..43980bd52 100644 --- a/src/input/input_vcd.c +++ b/src/input/input_vcd.c @@ -1,18 +1,18 @@ -/* - * Copyright (C) 2000-2006 the xine project - * +/* + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -84,7 +84,7 @@ typedef struct { const char *device; - char *filelist[100]; + char **filelist; int mrls_allocated_entries; xine_mrl_t **mrls; @@ -92,7 +92,7 @@ typedef struct { #if defined (__linux__) || defined(__sun) struct cdrom_tochdr tochdr; struct cdrom_tocentry tocent[100]; -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) struct ioc_toc_header tochdr; struct cd_toc_entry *tocent; off_t cur_sec; @@ -105,11 +105,11 @@ typedef struct { typedef struct { input_plugin_t input_plugin; - + vcd_input_class_t *cls; - + xine_stream_t *stream; - + char *mrl; config_values_t *config; @@ -117,7 +117,7 @@ typedef struct { int cur_track; -#if defined (__linux__) || defined(__sun) || defined (__FreeBSD_kernel__) +#if defined (__linux__) || defined(__sun) || defined (__FreeBSD_kernel__) || defined (__OpenBSD__) uint8_t cur_min, cur_sec, cur_frame; #endif @@ -136,7 +136,7 @@ typedef struct { */ static void device_change_cb (void *data, xine_cfg_entry_t *cfg) { vcd_input_class_t *this = (vcd_input_class_t *) data; - + this->device = cfg->str_value; } @@ -146,7 +146,7 @@ static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { /* read TOC header */ if ( ioctl(fd, CDROMREADTOCHDR, &this->tochdr) == -1 ) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_vcd : error in ioctl CDROMREADTOCHDR\n"); return -1; } @@ -156,7 +156,7 @@ static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { this->tocent[i-1].cdte_track = i; this->tocent[i-1].cdte_format = CDROM_MSF; if ( ioctl(fd, CDROMREADTOCENTRY, &this->tocent[i-1]) == -1 ) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error in ioctl CDROMREADTOCENTRY for track %d\n", i); return -1; } @@ -166,9 +166,9 @@ static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { this->tocent[this->tochdr.cdth_trk1].cdte_track = CDROM_LEADOUT; this->tocent[this->tochdr.cdth_trk1].cdte_format = CDROM_MSF; - if (ioctl(fd, CDROMREADTOCENTRY, + if (ioctl(fd, CDROMREADTOCENTRY, &this->tocent[this->tochdr.cdth_trk1]) == -1 ) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error in ioctl CDROMREADTOCENTRY for lead-out\n"); return -1; } @@ -177,7 +177,7 @@ static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { return 0; } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { struct ioc_read_toc_entry te; @@ -185,23 +185,23 @@ static int input_vcd_read_toc (vcd_input_class_t *this, int fd) { /* read TOC header */ if ( ioctl(fd, CDIOREADTOCHEADER, &this->tochdr) == -1 ) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_vcd : error in ioctl CDROMREADTOCHDR\n"); return -1; } - ntracks = this->tochdr.ending_track + ntracks = this->tochdr.ending_track - this->tochdr.starting_track + 2; this->tocent = (struct cd_toc_entry *) xine_xmalloc(sizeof(*this->tocent) * ntracks); - + te.address_format = CD_LBA_FORMAT; te.starting_track = 0; te.data_len = ntracks * sizeof(struct cd_toc_entry); te.data = this->tocent; - + if ( ioctl(fd, CDIOREADTOCENTRYS, &te) == -1 ){ - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error in ioctl CDROMREADTOCENTRY\n"); return -1; } @@ -232,11 +232,11 @@ static int sun_vcd_read(vcd_input_plugin_t *this, long lba, cdsector_t *data) */ if (this->controller_type == 0) { if ( ioctl(this->fd, DKIOCINFO, &cinfo) == 0 - && ((strcmp(cinfo.dki_cname, "ide") == 0) + && ((strcmp(cinfo.dki_cname, "ide") == 0) || (strncmp(cinfo.dki_cname, "pci", 3) == 0)) ) this->controller_type = SUN_CTRL_ATAPI; else - this->controller_type = SUN_CTRL_SCSI; + this->controller_type = SUN_CTRL_SCSI; } switch (this->controller_type) { case SUN_CTRL_SCSI: @@ -247,7 +247,7 @@ static int sun_vcd_read(vcd_input_plugin_t *this, long lba, cdsector_t *data) cdxa.cdxa_length = 1; cdxa.cdxa_data = data->subheader; cdxa.cdxa_format = CDROM_XA_SECTOR_DATA; - + if(ioctl(this->fd,CDROMCDXA,&cdxa)==-1) { xprintf(this->cls->xine, XINE_VERBOSITY_DEBUG, "CDROMCDXA: %s\n", strerror(errno)); return -1; @@ -304,12 +304,12 @@ static int sun_vcd_read(vcd_input_plugin_t *this, long lba, cdsector_t *data) cdb.cdb_opaque[7] = (blocks >> 8) & 0xff; cdb.cdb_opaque[8] = blocks & 0xff; cdb.cdb_opaque[9] = (sync << 7) | - (header_code << 5) | - (user_data << 4) | - (edc_ecc << 3) | - (error_field << 1); + (header_code << 5) | + (user_data << 4) | + (edc_ecc << 3) | + (error_field << 1); cdb.cdb_opaque[10] = sub_channel; - + sc.uscsi_cdb = (caddr_t)&cdb; sc.uscsi_cdblen = 12; sc.uscsi_bufaddr = (caddr_t)data->subheader; @@ -321,7 +321,7 @@ static int sun_vcd_read(vcd_input_plugin_t *this, long lba, cdsector_t *data) return -1; } if (sc.uscsi_status) { - xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, "scsi command failed with status %d\n", sc.uscsi_status); return -1; } @@ -336,9 +336,9 @@ static int sun_vcd_read(vcd_input_plugin_t *this, long lba, cdsector_t *data) /* ***************************************************************** */ #if defined (__linux__) -static off_t vcd_plugin_read (input_plugin_t *this_gen, +static off_t vcd_plugin_read (input_plugin_t *this_gen, char *buf, off_t nlen) { - + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; static struct cdrom_msf msf ; static cdsector_t data; @@ -348,14 +348,14 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, return 0; do - { + { end_msf = (struct cdrom_msf0 *) &this->cls->tocent[this->cur_track+1].cdte_addr.msf; /* printf ("cur: %02d:%02d:%02d end: %02d:%02d:%02d\n", - this->cur_min, this->cur_sec, this->cur_frame, - end_msf->minute, end_msf->second, end_msf->frame); + this->cur_min, this->cur_sec, this->cur_frame, + end_msf->minute, end_msf->second, end_msf->frame); */ if ( (this->cur_min>=end_msf->minute) && (this->cur_sec>=end_msf->second) @@ -369,7 +369,7 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, memcpy (&data, &msf, sizeof (msf)); if (ioctl (this->fd, CDROMREADRAW, &data) == -1) { - xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error in CDROMREADRAW\n"); return 0; } @@ -384,17 +384,17 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, this->cur_min++; } } - + /* Header ID check for padding sector. VCD uses this to keep constant bitrate so the CD doesn't stop/start */ } while((data.subheader[2]&~0x01)==0x60); - + memcpy (buf, data.data, VCDSECTORSIZE); /* FIXME */ return VCDSECTORSIZE; } -#elif defined (__FreeBSD_kernel__) -static off_t vcd_plugin_read (input_plugin_t *this_gen, +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) +static off_t vcd_plugin_read (input_plugin_t *this_gen, char *buf, off_t nlen) { vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; static cdsector_t data; @@ -418,9 +418,9 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, return VCDSECTORSIZE; } #elif defined (__sun) -static off_t vcd_plugin_read (input_plugin_t *this_gen, +static off_t vcd_plugin_read (input_plugin_t *this_gen, char *buf, off_t nlen) { - + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; static cdsector_t data; struct cdrom_msf0 *end_msf; @@ -430,14 +430,14 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, return 0; do - { - end_msf = (struct cdrom_msf0 *) + { + end_msf = (struct cdrom_msf0 *) &this->cls->tocent[this->cur_track+1].cdte_addr.msf; /* printf ("cur: %02d:%02d:%02d end: %02d:%02d:%02d\n", - this->cur_min, this->cur_sec, this->cur_frame, - end_msf->minute, end_msf->second, end_msf->frame); + this->cur_min, this->cur_sec, this->cur_frame, + end_msf->minute, end_msf->second, end_msf->frame); */ if ( (this->cur_min>=end_msf->minute) && (this->cur_sec>=end_msf->second) @@ -460,21 +460,21 @@ static off_t vcd_plugin_read (input_plugin_t *this_gen, this->cur_min++; } } - + /* Header ID check for padding sector. VCD uses this to keep constant bitrate so the CD doesn't stop/start */ } while((data.subheader[2]&~0x01)==0x60); - + memcpy (buf, data.data, VCDSECTORSIZE); /* FIXME */ return VCDSECTORSIZE; } #endif #if defined (__linux__) -static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, +static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t nlen) { - + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; buf_element_t *buf; static struct cdrom_msf msf ; @@ -485,13 +485,13 @@ static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, return NULL; do - { + { end_msf = &this->cls->tocent[this->cur_track+1].cdte_addr.msf; /* printf ("cur: %02d:%02d:%02d end: %02d:%02d:%02d\n", - this->cur_min, this->cur_sec, this->cur_frame, - end_msf->minute, end_msf->second, end_msf->frame); + this->cur_min, this->cur_sec, this->cur_frame, + end_msf->minute, end_msf->second, end_msf->frame); */ if ( (this->cur_min>=end_msf->minute) && (this->cur_sec>=end_msf->second) @@ -519,22 +519,22 @@ static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, this->cur_min++; } } - + /* Header ID check for padding sector. VCD uses this to keep constant bitrate so the CD doesn't stop/start */ } while((data.subheader[2]&~0x01)==0x60); - + buf = fifo->buffer_pool_alloc (fifo); buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; memcpy (buf->mem, data.data, VCDSECTORSIZE); /* FIXME */ return buf; } -#elif defined (__FreeBSD_kernel__) -static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) +static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t nlen) { - + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; buf_element_t *buf; static cdsector_t data; @@ -562,9 +562,9 @@ static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, return buf; } #elif defined(__sun) -static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, +static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t nlen) { - + vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; buf_element_t *buf; static cdsector_t data; @@ -575,14 +575,14 @@ static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, return NULL; do - { - end_msf = (struct cdrom_msf0 *) + { + end_msf = (struct cdrom_msf0 *) &this->cls->tocent[this->cur_track+1].cdte_addr.msf; /* printf ("cur: %02d:%02d:%02d end: %02d:%02d:%02d\n", - this->cur_min, this->cur_sec, this->cur_frame, - end_msf->minute, end_msf->second, end_msf->frame); + this->cur_min, this->cur_sec, this->cur_frame, + end_msf->minute, end_msf->second, end_msf->frame); */ if ( (this->cur_min>=end_msf->minute) && (this->cur_sec>=end_msf->second) @@ -606,12 +606,12 @@ static buf_element_t *vcd_plugin_read_block (input_plugin_t *this_gen, this->cur_min++; } } - + /* Header ID check for padding sector. VCD uses this to keep constant bitrate so the CD doesn't stop/start */ } while((data.subheader[2]&~0x01)==0x60); - + buf = fifo->buffer_pool_alloc (fifo); buf->content = buf->mem; buf->type = BUF_DEMUX_BLOCK; @@ -625,17 +625,17 @@ static off_t vcd_time_to_offset (int min, int sec, int frame) { return min * 60 * 75 + sec * 75 + frame; } -static void vcd_offset_to_time (off_t offset, uint8_t *min, uint8_t *sec, +static void vcd_offset_to_time (off_t offset, uint8_t *min, uint8_t *sec, uint8_t *frame) { *min = offset / (60*75); offset %= (60*75); - *sec = offset / 75; - *frame = offset % 75; + *sec = offset / 75; + *frame = offset % 75; } -static off_t vcd_plugin_seek (input_plugin_t *this_gen, +static off_t vcd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; @@ -647,11 +647,11 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, switch (origin) { case SEEK_SET: - sector_pos = (offset / VCDSECTORSIZE) + sector_pos = (offset / VCDSECTORSIZE) + vcd_time_to_offset (start_msf->minute, start_msf->second, start_msf->frame); - + vcd_offset_to_time (sector_pos, &this->cur_min, &this->cur_sec, &this->cur_frame); @@ -663,8 +663,8 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, break; case SEEK_CUR: - if (offset) - xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, + if (offset) + xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, "input_vcd: SEEK_CUR not implemented for offset != 0\n"); /* @@ -683,15 +683,15 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, break; default: - xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error seek to origin %d not implemented!\n", origin); return 0; } return offset ; /* FIXME */ } -#elif defined (__FreeBSD_kernel__) -static off_t vcd_plugin_seek (input_plugin_t *this_gen, +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) +static off_t vcd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { @@ -700,11 +700,11 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, uint32_t dist ; off_t sector_pos; - start = + start = ntohl(this->cls->tocent [this->cur_track+1 - this->cls->tochdr.starting_track].addr.lba); - /* printf("seek: start sector:%lu, origin: %d, offset:%qu\n", + /* printf("seek: start sector:%lu, origin: %d, offset:%qu\n", start, origin, offset); */ @@ -715,7 +715,7 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, break; case SEEK_CUR: - if (offset) + if (offset) xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, "input_vcd: SEEK_CUR not implemented for offset != 0\n"); sector_pos = this->cur_sec; @@ -724,7 +724,7 @@ static off_t vcd_plugin_seek (input_plugin_t *this_gen, break; default: - xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->cls->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error seek to origin %d not implemented!\n", origin); return 0; } @@ -738,46 +738,46 @@ static off_t vcd_plugin_get_length (input_plugin_t *this_gen) { vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; struct cdrom_msf0 *end_msf, *start_msf; off_t len ; - + if(this->cls->total_tracks) { - + start_msf = (struct cdrom_msf0 *) &this->cls->tocent[this->cur_track].cdte_addr.msf; end_msf = (struct cdrom_msf0 *) &this->cls->tocent[this->cur_track+1].cdte_addr.msf; - + len = 75 - start_msf->frame; - + if (start_msf->second<60) len += (59 - start_msf->second) * 75; - + if (end_msf->minute > start_msf->minute) { len += (end_msf->minute - start_msf->minute-1) * 60 * 75; - + len += end_msf->second * 60; - + len += end_msf->frame ; } - + return len * VCDSECTORSIZE; } return (off_t) 0; } -#elif defined (__FreeBSD_kernel__) +#elif defined (__FreeBSD_kernel__) || defined (__OpenBSD__) static off_t vcd_plugin_get_length (input_plugin_t *this_gen) { vcd_input_plugin_t *this = (vcd_input_plugin_t *) this_gen; off_t len ; - len = + len = ntohl(this->cls->tocent - [this->cur_track+2 + [this->cur_track+2 - this->cls->tochdr.starting_track].addr.lba) - ntohl(this->cls->tocent - [this->cur_track+1 + [this->cur_track+1 - this->cls->tochdr.starting_track].addr.lba); - + return len * 2352; /*VCDSECTORSIZE;*/ } @@ -790,7 +790,7 @@ static off_t vcd_plugin_get_current_pos (input_plugin_t *this_gen){ } static uint32_t vcd_plugin_get_capabilities (input_plugin_t *this_gen) { - + return INPUT_CAP_SEEKABLE | INPUT_CAP_BLOCK ; } @@ -816,7 +816,7 @@ static const char* vcd_plugin_get_mrl (input_plugin_t *this_gen) { return this->mrl; } -static int vcd_plugin_get_optional_data (input_plugin_t *this_gen, +static int vcd_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { return INPUT_OPTIONAL_UNSUPPORTED; @@ -843,13 +843,13 @@ static int vcd_plugin_open (input_plugin_t *this_gen) { while (*filename == '/') filename++; if (sscanf (filename, "%d", &this->cur_track) != 1) { - xprintf (cls->xine, XINE_VERBOSITY_LOG, + xprintf (cls->xine, XINE_VERBOSITY_LOG, _("input_vcd: malformed MRL. Use vcdo:/<track #>\n")); return 0; } if (this->cur_track>=this->cls->total_tracks) { - xprintf (cls->xine, XINE_VERBOSITY_LOG, + xprintf (cls->xine, XINE_VERBOSITY_LOG, _("input_vcd: invalid track %d (valid range: 0 .. %d)\n"), this->cur_track, this->cls->total_tracks-1); return 0; @@ -859,6 +859,10 @@ static int vcd_plugin_open (input_plugin_t *this_gen) { this->cur_min = this->cls->tocent[this->cur_track].cdte_addr.msf.minute; this->cur_sec = this->cls->tocent[this->cur_track].cdte_addr.msf.second; this->cur_frame = this->cls->tocent[this->cur_track].cdte_addr.msf.frame; +#elif defined (__OpenBSD__) + this->cur_min = this->cls->tocent[this->cur_track + 1 - this->cls->tochdr.starting_track].addr.msf.minute; + this->cur_sec = this->cls->tocent[this->cur_track + 1 - this->cls->tochdr.starting_track].addr.msf.second; + this->cur_frame = this->cls->tocent[this->cur_track + 1 - this->cls->tochdr.starting_track].addr.msf.frame; #elif defined (__FreeBSD_kernel__) { int bsize = 2352; @@ -866,21 +870,21 @@ static int vcd_plugin_open (input_plugin_t *this_gen) { xprintf (cls->xine, XINE_VERBOSITY_DEBUG, "input_vcd: error in CDRIOCSETBLOCKSIZE %d\n", errno); return 0; } - - this->cur_sec = + + this->cur_sec = ntohl(this->cls->tocent [this->cur_track+1 - this->cls->tochdr.starting_track].addr.lba); - + } #endif - + return 1; } -static input_plugin_t *vcd_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, +static input_plugin_t *vcd_class_get_instance (input_class_t *cls_gen, xine_stream_t *stream, const char *data) { - vcd_input_class_t *cls = (vcd_input_class_t *) cls_gen; + vcd_input_class_t *cls = (vcd_input_class_t *) cls_gen; vcd_input_plugin_t *this; char *mrl = strdup(data); @@ -888,8 +892,8 @@ static input_plugin_t *vcd_class_get_instance (input_class_t *cls_gen, xine_stre free (mrl); return 0; } - - this = (vcd_input_plugin_t *) xine_xmalloc(sizeof(vcd_input_plugin_t)); + + this = calloc(1, sizeof(vcd_input_plugin_t)); this->stream = stream; this->mrl = mrl; @@ -924,17 +928,26 @@ static const char *vcd_class_get_identifier (input_class_t *this_gen) { return "vcdo"; } +static void vcd_filelist_dispose(vcd_input_class_t *this) { + if ( this->filelist == NULL ) return; + + char **entry = this->filelist; + + while(*(entry)) { + free(*(entry++)); + } + + free(this->filelist); +} + static void vcd_class_dispose (input_class_t *this_gen) { vcd_input_class_t *this = (vcd_input_class_t *) this_gen; - int i; config_values_t *config = this->xine->config; config->unregister_callback(config, "media.vcd.device"); - for (i = 0; i < 100; i++) - free (this->filelist[i]); - + vcd_filelist_dispose(this); free (this->mrls); free (this); } @@ -946,7 +959,7 @@ static int vcd_class_eject_media (input_class_t *this_gen) { return media_eject_media (this->xine, this->device); } -static xine_mrl_t **vcd_class_get_dir (input_class_t *this_gen, const char *filename, +static xine_mrl_t **vcd_class_get_dir (input_class_t *this_gen, const char *filename, int *num_files) { vcd_input_class_t *this = (vcd_input_class_t *) this_gen; @@ -957,7 +970,7 @@ static xine_mrl_t **vcd_class_get_dir (input_class_t *this_gen, const char *file if (filename) return NULL; - + fd = open (this->device, O_RDONLY|O_EXCL); if (fd == -1) { @@ -982,33 +995,19 @@ static xine_mrl_t **vcd_class_get_dir (input_class_t *this_gen, const char *file /* printf ("%d tracks\n", this->total_tracks); */ for (i=1; i<this->total_tracks; i++) { /* FIXME: check if track 0 contains valid data */ - char mrl[1024]; - - memset(&mrl, 0, sizeof (mrl)); - sprintf(mrl, "vcdo:/%d",i); - if((i-1) >= this->mrls_allocated_entries) { ++this->mrls_allocated_entries; /* note: 1 extra pointer for terminating NULL */ this->mrls = realloc(this->mrls, (this->mrls_allocated_entries+1) * sizeof(xine_mrl_t*)); - this->mrls[(i-1)] = (xine_mrl_t *) xine_xmalloc(sizeof(xine_mrl_t)); + this->mrls[(i-1)] = calloc(1, sizeof(xine_mrl_t)); } else { memset(this->mrls[(i-1)], 0, sizeof(xine_mrl_t)); } - - if(this->mrls[(i-1)]->mrl) { - this->mrls[(i-1)]->mrl = (char *) - realloc(this->mrls[(i-1)]->mrl, strlen(mrl) + 1); - } - else { - this->mrls[(i-1)]->mrl = (char *) xine_xmalloc(strlen(mrl) + 1); - } - - this->mrls[i-1]->origin = NULL; - sprintf(this->mrls[i-1]->mrl, "%s", mrl); - this->mrls[i-1]->link = NULL; - this->mrls[i-1]->type = (0 | mrl_vcd); + + asprintf(&(this->mrls[i-1]->mrl), "vcdo:/%d", i); + + this->mrls[i-1]->type = mrl_vcd; /* hack */ this->mrls[i-1]->size = vcd_plugin_get_length ((input_plugin_t *) this); @@ -1024,13 +1023,13 @@ static xine_mrl_t **vcd_class_get_dir (input_class_t *this_gen, const char *file } this->mrls[*num_files] = NULL; - + return this->mrls; } static char ** vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) { - vcd_input_class_t *this = (vcd_input_class_t *) this_gen; + vcd_input_class_t *this = (vcd_input_class_t *) this_gen; int i, fd; @@ -1055,20 +1054,15 @@ static char ** vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_fi fd = -1; *num_files = this->total_tracks - 1; - - /* printf ("%d tracks\n", this->total_tracks); */ - for (i = 1; i < this->total_tracks; i++) { /* FIXME: check if track 0 contains valid data */ + vcd_filelist_dispose(this); + this->filelist = calloc(this->total_tracks+1, sizeof(char*)); - if(this->filelist[i - 1] == NULL) - this->filelist[i - 1] = (char *) realloc(this->filelist[i - 1], sizeof(char *) * 256); + /* FIXME: check if track 0 contains valid data */ + for (i = 1; i < this->total_tracks; i++) + asprintf(&this->filelist[i-1], "vcdo:/%d", i); - sprintf (this->filelist[i - 1], "vcdo:/%d",i); - /* printf ("list[%d] : %d %s\n", i, this->filelist[i-1], this->filelist[i-1]); */ - } - - this->filelist[i - 1] = (char *) realloc(this->filelist[i-1], sizeof(char *)); - this->filelist[i - 1] = NULL; + /* printf ("%d tracks\n", this->total_tracks); */ return this->filelist; } @@ -1077,9 +1071,8 @@ static void *init_class (xine_t *xine, void *data) { vcd_input_class_t *this; config_values_t *config = xine->config; - int i; - this = (vcd_input_class_t *) xine_xmalloc (sizeof (vcd_input_class_t)); + this = calloc(1, sizeof (vcd_input_class_t)); this->xine = xine; @@ -1097,13 +1090,9 @@ static void *init_class (xine_t *xine, void *data) { "you intend to play your VideoCDs with."), 10, device_change_cb, (void *)this); - this->mrls = (xine_mrl_t **) xine_xmalloc(sizeof(xine_mrl_t*)); + this->mrls = calloc(1, sizeof(xine_mrl_t*)); this->mrls_allocated_entries = 0; - for (i = 0; i < 100; i++) { - this->filelist[i] = (char *) xine_xmalloc(sizeof(char *) * 256); - } - return this; } @@ -1112,7 +1101,7 @@ static void *init_class (xine_t *xine, void *data) { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, "VCDO", XINE_VERSION_CODE, NULL, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/input/libdvdnav/Makefile.am b/src/input/libdvdnav/Makefile.am index 412828261..1cf60a0e2 100644 --- a/src/input/libdvdnav/Makefile.am +++ b/src/input/libdvdnav/Makefile.am @@ -46,4 +46,4 @@ noinst_HEADERS = \ dvd_reader.h \ dvd_input.h \ dvd_udf.h \ - bswap.h + bswap.h diff --git a/src/input/libdvdnav/bswap.h b/src/input/libdvdnav/bswap.h index 2a2d222fe..23f0251d6 100644 --- a/src/input/libdvdnav/bswap.h +++ b/src/input/libdvdnav/bswap.h @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <config.h> +#include "config.h" #if defined(WORDS_BIGENDIAN) /* All bigendian systems are fine, just ignore the swaps. */ diff --git a/src/input/libdvdnav/diff_against_cvs.patch b/src/input/libdvdnav/diff_against_cvs.patch index 202474fef..6df704e2a 100644 --- a/src/input/libdvdnav/diff_against_cvs.patch +++ b/src/input/libdvdnav/diff_against_cvs.patch @@ -323,7 +323,7 @@ diff -u -p -u -r1.5 dvd_reader.h -#ifdef _MSC_VER +#ifdef HAVE_CONFIG_H - #include <config.h> + #include "config.h" +#endif +#ifdef _MSC_VER diff --git a/src/input/libdvdnav/dvd_reader.c b/src/input/libdvdnav/dvd_reader.c index 200a1dbec..1e0d3016b 100644 --- a/src/input/libdvdnav/dvd_reader.c +++ b/src/input/libdvdnav/dvd_reader.c @@ -30,7 +30,9 @@ #include <string.h> #include <unistd.h> #include <limits.h> +#ifdef HAVE_DIRENT_H #include <dirent.h> +#endif #ifndef HAVE_GETTIMEOFDAY # ifdef WIN32 @@ -1037,6 +1039,28 @@ int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset ) return offset; } +int32_t DVDFileSeekForce( dvd_file_t *dvd_file, int offset, int force_size ) +{ + /* Check arguments. */ + if( dvd_file == NULL || offset < 0 ) + return -1; + + if( dvd_file->dvd->isImageFile ) { + if( force_size < 0 ) + force_size = (offset - 1) / DVD_VIDEO_LB_LEN + 1; + if( dvd_file->filesize < force_size) { + dvd_file->filesize = force_size; + fprintf(stderr, "libdvdread: Ignored UDF provided size of file.\n"); + } + } + + if( offset > dvd_file->filesize * DVD_VIDEO_LB_LEN ) { + return -1; + } + dvd_file->seek_pos = (uint32_t) offset; + return offset; +} + ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) { unsigned char *secbuf_base, *secbuf; @@ -1077,7 +1101,7 @@ ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size ) memcpy( data, &(secbuf[ seek_byte ]), byte_size ); free( secbuf_base ); - dvd_file->seek_pos += byte_size; + DVDFileSeekForce(dvd_file, dvd_file->seek_pos + byte_size, -1); return byte_size; } diff --git a/src/input/libdvdnav/dvd_reader.h b/src/input/libdvdnav/dvd_reader.h index bb3f5053b..c7b3f9df8 100644 --- a/src/input/libdvdnav/dvd_reader.h +++ b/src/input/libdvdnav/dvd_reader.h @@ -22,7 +22,7 @@ */ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #ifdef _MSC_VER @@ -171,6 +171,8 @@ ssize_t DVDReadBlocks( dvd_file_t *, int, size_t, unsigned char * ); */ int32_t DVDFileSeek( dvd_file_t *, int32_t ); +int32_t DVDFileSeekForce( dvd_file_t *, int, int ); + /** * Reads the given number of bytes from the file. This call can only be used * on the information files, and may not be used for reading from a VOB. This diff --git a/src/input/libdvdnav/ifo_read.c b/src/input/libdvdnav/ifo_read.c index 8f47d2a54..bc1ba580b 100644 --- a/src/input/libdvdnav/ifo_read.c +++ b/src/input/libdvdnav/ifo_read.c @@ -93,6 +93,10 @@ static inline int DVDFileSeek_( dvd_file_t *dvd_file, uint32_t offset ) { return (DVDFileSeek(dvd_file, (int)offset) == (int)offset); } +static inline int32_t DVDFileSeekForce_( dvd_file_t *dvd_file, uint32_t offset, int force_size ) { + return (DVDFileSeekForce(dvd_file, (int)offset, force_size) == (int)offset); +} + ifo_handle_t *ifoOpen(dvd_reader_t *dvd, int title) { ifo_handle_t *ifofile; @@ -1507,7 +1511,7 @@ static int ifoRead_VOBU_ADMAP_internal(ifo_handle_t *ifofile, unsigned int i; int info_length; - if(!DVDFileSeek_(ifofile->file, sector * DVD_BLOCK_LEN)) + if(!DVDFileSeekForce_(ifofile->file, sector * DVD_BLOCK_LEN, sector)) return 0; if(!(DVDReadBytes(ifofile->file, vobu_admap, VOBU_ADMAP_SIZE))) diff --git a/src/input/libdvdnav/md5.c b/src/input/libdvdnav/md5.c index 2bfdddee4..16b7b0690 100644 --- a/src/input/libdvdnav/md5.c +++ b/src/input/libdvdnav/md5.c @@ -21,7 +21,7 @@ /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ #ifdef HAVE_CONFIG_H -# include <config.h> +# include "config.h" #endif #include <sys/types.h> diff --git a/src/input/libdvdnav/remap.c b/src/input/libdvdnav/remap.c index 43c81c66f..df0be29ce 100644 --- a/src/input/libdvdnav/remap.c +++ b/src/input/libdvdnav/remap.c @@ -216,6 +216,7 @@ remap_t* remap_loadmap( char *title) { remap_add_node( map, tmp); } } + close (fp); /* ignoring errors... */ if (map->nblocks == 0 && map->debug == 0) return NULL; return map; diff --git a/src/input/libreal/asmrp.c b/src/input/libreal/asmrp.c index f7206b583..2c02c2f13 100644 --- a/src/input/libreal/asmrp.c +++ b/src/input/libreal/asmrp.c @@ -2,7 +2,7 @@ * Copyright (C) 2002-2004 the xine project * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -32,6 +32,10 @@ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -81,7 +85,7 @@ typedef struct { int sym; int num; - + char str[ASMRP_MAX_ID]; /* private part */ @@ -95,7 +99,7 @@ typedef struct { } asmrp_t; -static asmrp_t *asmrp_new () { +static asmrp_t *XINE_MALLOC asmrp_new () { asmrp_t *p; @@ -111,7 +115,7 @@ static void asmrp_dispose (asmrp_t *p) { int i; - for (i=0; i<p->sym_tab_num; i++) + for (i=0; i<p->sym_tab_num; i++) free (p->sym_tab[i].id); free (p); @@ -129,7 +133,7 @@ static void asmrp_init (asmrp_t *p, const char *str) { p->buf = strdup (str); p->pos = 0; - + asmrp_getch (p); } @@ -163,10 +167,10 @@ static void asmrp_string (asmrp_t *p) { asmrp_getch (p); } p->str[l]=0; - + if (p->ch=='"') asmrp_getch (p); - + p->sym = ASMRP_SYM_STRING; } @@ -185,7 +189,7 @@ static void asmrp_identifier (asmrp_t *p) { asmrp_getch (p); } p->str[l]=0; - + p->sym = ASMRP_SYM_ID; } @@ -383,10 +387,10 @@ static int asmrp_set_id (asmrp_t *p, char *s, int v) { lprintf ("new symbol '%s'\n", s); - } + } p->sym_tab[i].v = v; - + lprintf ("symbol '%s' assigned %d\n", s, v); return i; @@ -397,7 +401,7 @@ static int asmrp_condition (asmrp_t *p) ; static int asmrp_operand (asmrp_t *p) { int i, ret; - + lprintf ("operand\n"); ret = 0; @@ -407,7 +411,7 @@ static int asmrp_operand (asmrp_t *p) { case ASMRP_SYM_DOLLAR: asmrp_get_sym (p); - + if (p->sym != ASMRP_SYM_ID) { printf ("error: identifier expected.\n"); _x_abort(); @@ -449,7 +453,7 @@ static int asmrp_operand (asmrp_t *p) { } lprintf ("operand done, =%d\n", ret); - + return ret; } @@ -499,7 +503,7 @@ static int asmrp_comp_expression (asmrp_t *p) { } static int asmrp_condition (asmrp_t *p) { - + int a; lprintf ("condition\n"); @@ -538,7 +542,7 @@ static void asmrp_assignment (asmrp_t *p) { lprintf ("empty assignment\n"); return; } - + if (p->sym != ASMRP_SYM_ID) { printf ("error: identifier expected\n"); _x_abort (); @@ -551,7 +555,7 @@ static void asmrp_assignment (asmrp_t *p) { } asmrp_get_sym (p); - if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) + if ( (p->sym != ASMRP_SYM_NUM) && (p->sym != ASMRP_SYM_STRING) && (p->sym != ASMRP_SYM_ID)) { printf ("error: number or string expected\n"); _x_abort (); @@ -562,22 +566,22 @@ static void asmrp_assignment (asmrp_t *p) { } static int asmrp_rule (asmrp_t *p) { - + int ret; lprintf ("rule\n"); ret = 1; - + if (p->sym == ASMRP_SYM_HASH) { asmrp_get_sym (p); ret = asmrp_condition (p); while (p->sym == ASMRP_SYM_COMMA) { - + asmrp_get_sym (p); - + asmrp_assignment (p); } diff --git a/src/input/libreal/real.c b/src/input/libreal/real.c index df50f0440..9b72c7e57 100644 --- a/src/input/libreal/real.c +++ b/src/input/libreal/real.c @@ -21,6 +21,10 @@ * adopted from joschkas real tools. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> @@ -48,26 +52,23 @@ static const unsigned char xor_table[] = { #define _X_BE_32C(x,y) do { *(uint32_t *)(x) = be2me_32((y)); } while(0) #define _X_LE_32C(x,y) do { *(uint32_t *)(x) = le2me_32((y)); } while(0) -#define MAX(x,y) ((x>y) ? x : y) - - static void hash(char *field, char *param) { uint32_t a, b, c, d; - + /* fill variables */ a = _X_LE_32(field); b = _X_LE_32(field+4); c = _X_LE_32(field+8); d = _X_LE_32(field+12); - + lprintf("hash input: %x %x %x %x\n", a, b, c, d); lprintf("hash parameter:\n"); #ifdef LOG xine_hexdump(param, 64); #endif - + a = ((b & c) | (~b & d)) + _X_LE_32((param+0x00)) + a - 0x28955B88; a = ((a << 0x07) | (a >> 0x19)) + b; d = ((a & b) | (~a & c)) + _X_LE_32((param+0x04)) + d - 0x173848AA; @@ -100,7 +101,7 @@ static void hash(char *field, char *param) { c = ((c << 0x11) | (c >> 0x0f)) + d; b = ((c & d) | (~c & a)) + _X_LE_32((param+0x3c)) + b + 0x49B40821; b = ((b << 0x16) | (b >> 0x0a)) + c; - + a = ((b & d) | (~d & c)) + _X_LE_32((param+0x04)) + a - 0x09E1DA9E; a = ((a << 0x05) | (a >> 0x1b)) + b; d = ((a & c) | (~c & b)) + _X_LE_32((param+0x18)) + d - 0x3FBF4CC0; @@ -133,7 +134,7 @@ static void hash(char *field, char *param) { c = ((c << 0x0e) | (c >> 0x12)) + d; b = ((c & a) | (~a & d)) + _X_LE_32((param+0x30)) + b - 0x72D5B376; b = ((b << 0x14) | (b >> 0x0c)) + c; - + a = (b ^ c ^ d) + _X_LE_32((param+0x14)) + a - 0x0005C6BE; a = ((a << 0x04) | (a >> 0x1c)) + b; d = (a ^ b ^ c) + _X_LE_32((param+0x20)) + d - 0x788E097F; @@ -166,42 +167,42 @@ static void hash(char *field, char *param) { c = ((c << 0x10) | (c >> 0x10)) + d; b = (c ^ d ^ a) + _X_LE_32((param+0x08)) + b - 0x3B53A99B; b = ((b << 0x17) | (b >> 0x09)) + c; - + a = ((~d | b) ^ c) + _X_LE_32((param+0x00)) + a - 0x0BD6DDBC; - a = ((a << 0x06) | (a >> 0x1a)) + b; + a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + _X_LE_32((param+0x1c)) + d + 0x432AFF97; - d = ((d << 0x0a) | (d >> 0x16)) + a; + d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + _X_LE_32((param+0x38)) + c - 0x546BDC59; - c = ((c << 0x0f) | (c >> 0x11)) + d; + c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + _X_LE_32((param+0x14)) + b - 0x036C5FC7; - b = ((b << 0x15) | (b >> 0x0b)) + c; + b = ((b << 0x15) | (b >> 0x0b)) + c; a = ((~d | b) ^ c) + _X_LE_32((param+0x30)) + a + 0x655B59C3; - a = ((a << 0x06) | (a >> 0x1a)) + b; + a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + _X_LE_32((param+0x0C)) + d - 0x70F3336E; - d = ((d << 0x0a) | (d >> 0x16)) + a; + d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + _X_LE_32((param+0x28)) + c - 0x00100B83; - c = ((c << 0x0f) | (c >> 0x11)) + d; + c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + _X_LE_32((param+0x04)) + b - 0x7A7BA22F; - b = ((b << 0x15) | (b >> 0x0b)) + c; + b = ((b << 0x15) | (b >> 0x0b)) + c; a = ((~d | b) ^ c) + _X_LE_32((param+0x20)) + a + 0x6FA87E4F; - a = ((a << 0x06) | (a >> 0x1a)) + b; + a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + _X_LE_32((param+0x3c)) + d - 0x01D31920; - d = ((d << 0x0a) | (d >> 0x16)) + a; + d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + _X_LE_32((param+0x18)) + c - 0x5CFEBCEC; - c = ((c << 0x0f) | (c >> 0x11)) + d; + c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + _X_LE_32((param+0x34)) + b + 0x4E0811A1; - b = ((b << 0x15) | (b >> 0x0b)) + c; + b = ((b << 0x15) | (b >> 0x0b)) + c; a = ((~d | b) ^ c) + _X_LE_32((param+0x10)) + a - 0x08AC817E; - a = ((a << 0x06) | (a >> 0x1a)) + b; + a = ((a << 0x06) | (a >> 0x1a)) + b; d = ((~c | a) ^ b) + _X_LE_32((param+0x2c)) + d - 0x42C50DCB; - d = ((d << 0x0a) | (d >> 0x16)) + a; + d = ((d << 0x0a) | (d >> 0x16)) + a; c = ((~b | d) ^ a) + _X_LE_32((param+0x08)) + c + 0x2AD7D2BB; - c = ((c << 0x0f) | (c >> 0x11)) + d; + c = ((c << 0x0f) | (c >> 0x11)) + d; b = ((~a | c) ^ d) + _X_LE_32((param+0x24)) + b - 0x14792C6F; - b = ((b << 0x15) | (b >> 0x0b)) + c; + b = ((b << 0x15) | (b >> 0x0b)) + c; lprintf("hash output: %x %x %x %x\n", a, b, c, d); - + a += _X_LE_32(field); b += _X_LE_32(field+4); c += _X_LE_32(field+8); @@ -217,15 +218,15 @@ static void call_hash (char *key, char *challenge, unsigned int len) { char *ptr1, *ptr2; uint32_t a, b, c, d, tmp; - + ptr1=(key+16); ptr2=(key+20); - + a = _X_LE_32(ptr1); b = (a >> 3) & 0x3f; a += len * 8; _X_LE_32C(ptr1, a); - + if (a < (len << 3)) { lprintf("not verified: (len << 3) > a true\n"); @@ -235,7 +236,7 @@ static void call_hash (char *key, char *challenge, unsigned int len) { tmp = _X_LE_32(ptr2) + (len >> 0x1d); _X_LE_32C(ptr2, tmp); a = 64 - b; - c = 0; + c = 0; if (a <= len) { @@ -243,7 +244,7 @@ static void call_hash (char *key, char *challenge, unsigned int len) { hash(key, key+24); c = a; d = c + 0x3f; - + while ( d < len ) { lprintf("not verified: while ( d < len )\n"); hash(key, challenge+d-0x3f); @@ -252,7 +253,7 @@ static void call_hash (char *key, char *challenge, unsigned int len) { } b = 0; } - + memcpy(key+b+24, challenge+c, len-c); } @@ -264,11 +265,11 @@ static void calc_response (char *result, char *field) { memset (buf1, 0, 64); *buf1 = 128; - + memcpy (buf2, field+16, 8); - + i = ( _X_LE_32((buf2)) >> 3 ) & 0x3f; - + if (i < 56) { i = 56 - i; } else { @@ -285,7 +286,7 @@ static void calc_response (char *result, char *field) { static void calc_response_string (char *result, char *challenge) { - + char field[128] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, @@ -294,15 +295,15 @@ static void calc_response_string (char *result, char *challenge) { }; char zres[20]; int i; - + /* calculate response */ call_hash(field, challenge, 64); calc_response(zres,field); - + /* convert zres to ascii string */ for (i=0; i<16; i++ ) { char a, b; - + a = (zres[i] >> 4) & 15; b = zres[i] & 15; @@ -313,7 +314,7 @@ static void calc_response_string (char *result, char *challenge) { void real_calc_response_and_checksum (char *response, char *chksum, char *challenge) { - int ch_len, resp_len; + size_t ch_len, resp_len; int i; char *ptr; char buf[128]; @@ -341,11 +342,11 @@ void real_calc_response_and_checksum (char *response, char *chksum, char *challe ch_len=32; } if ( ch_len > 56 ) ch_len=56; - + /* copy challenge to buf */ memcpy(ptr, challenge, ch_len); } - + /* xor challenge bytewise with xor_table */ for (i=0; i<XOR_TABLE_LEN; i++) ptr[i] = ptr[i] ^ xor_table[i]; @@ -371,7 +372,7 @@ static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection int numrules, codec, size; int i; - + /* MLTI chunk should begin with MLTI */ if ((mlti_chunk[0] != 'M') @@ -409,13 +410,13 @@ static int select_mlti_data(const char *mlti_chunk, int mlti_size, int selection } mlti_chunk+=2; - + /* now seek to selected codec */ for (i=0; i<codec; i++) { size=_X_BE_32(mlti_chunk); mlti_chunk+=size+4; } - + size=_X_BE_32(mlti_chunk); #ifdef LOG @@ -440,16 +441,16 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt int max_packet_size=0; int avg_packet_size=0; int duration=0; - + if (!data) return NULL; desc=sdpplin_parse(data); if (!desc) return NULL; - + buf=xine_buffer_init(2048); - header = xine_xmalloc(sizeof(rmff_header_t)); + header = calloc(1, sizeof(rmff_header_t)); header->fileheader=rmff_new_fileheader(4+desc->stream_count); header->cont=rmff_new_cont( @@ -458,7 +459,7 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt desc->copyright, desc->abstract); header->data=rmff_new_dataheader(0,0); - header->streams = xine_xmalloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1)); + header->streams = calloc((desc->stream_count+1), sizeof(rmff_mdpr_t*)); lprintf("number of streams: %u\n", desc->stream_count); for (i=0; i<desc->stream_count; i++) { @@ -483,7 +484,7 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt } else len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf); - + header->streams[i]=rmff_new_mdpr( desc->stream[i]->stream_id, desc->stream[i]->max_bit_rate, @@ -507,7 +508,7 @@ rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidt else avg_packet_size=desc->stream[i]->avg_packet_size; } - + if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',') (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */ @@ -576,12 +577,12 @@ int real_get_rdt_chunk(rtsp_t *rtsp_session, unsigned char **buffer) { n=rtsp_read_data(rtsp_session, header, 6); if (n<6) return 0; ts=_X_BE_32(header); - - lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n", + + lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n", ts, size, flags1, unknown1, header[4], header[5]); size+=2; - + ph.object_version=0; ph.length=size; ph.stream_number=(flags1>>1)&1; @@ -592,7 +593,7 @@ int real_get_rdt_chunk(rtsp_t *rtsp_session, unsigned char **buffer) { rmff_dump_pheader(&ph, *buffer); size-=12; n=rtsp_read_data(rtsp_session, (*buffer)+12, size); - + return (n <= 0) ? 0 : n+12; } @@ -611,11 +612,11 @@ rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwid char *mrl=rtsp_get_mrl(rtsp_session); unsigned int size; int status; - + /* get challenge */ challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1")); lprintf("Challenge1: %s\n", challenge1); - + /* request stream description */ rtsp_schedule_field(rtsp_session, "Accept: application/sdp"); sprintf(buf, "Bandwidth: %u", bandwidth); @@ -657,10 +658,10 @@ rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwid lprintf("real: got no ETag!\n"); else session_id=strdup(rtsp_search_answers(rtsp_session,"ETag")); - + lprintf("Stream description size: %i\n", size); - description = malloc(sizeof(char)*(size+1)); + description = malloc(size+1); if( rtsp_read_data(rtsp_session, description, size) <= 0) { xine_buffer_free(buf); @@ -681,7 +682,7 @@ rmff_header_t *real_setup_and_get_header(rtsp_t *rtsp_session, uint32_t bandwid lprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n", h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams); - + /* setup our streams */ real_calc_response_and_checksum (challenge2, checksum, challenge1); xine_buffer_ensure_size(buf, strlen(challenge2) + strlen(checksum) + 32); diff --git a/src/input/libreal/real.h b/src/input/libreal/real.h index edcd170f8..f299b909b 100644 --- a/src/input/libreal/real.h +++ b/src/input/libreal/real.h @@ -20,7 +20,7 @@ * special functions for real streams. * adopted from joschkas real tools. */ - + #ifndef HAVE_REAL_H #define HAVE_REAL_H diff --git a/src/input/libreal/rmff.c b/src/input/libreal/rmff.c index 159b81ee6..6a2b761e1 100644 --- a/src/input/libreal/rmff.c +++ b/src/input/libreal/rmff.c @@ -21,6 +21,10 @@ * adopted from joschkas real tools */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "rmff" #define LOG_VERBOSE /* @@ -35,15 +39,19 @@ * writes header data to a buffer */ -static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) { +static int rmff_dump_fileheader(rmff_fileheader_t *fileheader, uint8_t *buffer, int bufsize) { + + if (!fileheader) return 0; + + if (bufsize < RMFF_FILEHEADER_SIZE) + return -1; - if (!fileheader) return; fileheader->object_id=_X_BE_32(&fileheader->object_id); fileheader->size=_X_BE_32(&fileheader->size); fileheader->object_version=_X_BE_16(&fileheader->object_version); fileheader->file_version=_X_BE_32(&fileheader->file_version); fileheader->num_headers=_X_BE_32(&fileheader->num_headers); - + memcpy(buffer, fileheader, 8); memcpy(&buffer[8], &fileheader->object_version, 2); memcpy(&buffer[10], &fileheader->file_version, 8); @@ -53,11 +61,17 @@ static void rmff_dump_fileheader(rmff_fileheader_t *fileheader, char *buffer) { fileheader->file_version=_X_BE_32(&fileheader->file_version); fileheader->num_headers=_X_BE_32(&fileheader->num_headers); fileheader->object_id=_X_BE_32(&fileheader->object_id); + + return RMFF_FILEHEADER_SIZE; } -static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) { +static int rmff_dump_prop(rmff_prop_t *prop, uint8_t *buffer, int bufsize) { + + if (!prop) return 0; + + if (bufsize < RMFF_PROPHEADER_SIZE) + return -1; - if (!prop) return; prop->object_id=_X_BE_32(&prop->object_id); prop->size=_X_BE_32(&prop->size); prop->object_version=_X_BE_16(&prop->object_version); @@ -78,7 +92,7 @@ static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) { memcpy(&buffer[10], &prop->max_bit_rate, 36); memcpy(&buffer[46], &prop->num_streams, 2); memcpy(&buffer[48], &prop->flags, 2); - + prop->size=_X_BE_32(&prop->size); prop->object_version=_X_BE_16(&prop->object_version); prop->max_bit_rate=_X_BE_32(&prop->max_bit_rate); @@ -93,13 +107,19 @@ static void rmff_dump_prop(rmff_prop_t *prop, char *buffer) { prop->num_streams=_X_BE_16(&prop->num_streams); prop->flags=_X_BE_16(&prop->flags); prop->object_id=_X_BE_32(&prop->object_id); + + return RMFF_PROPHEADER_SIZE; } -static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) { +static int rmff_dump_mdpr(rmff_mdpr_t *mdpr, uint8_t *buffer, int bufsize) { int s1, s2, s3; - if (!mdpr) return; + if (!mdpr) return 0; + + if (bufsize < RMFF_MDPRHEADER_SIZE + mdpr->type_specific_len + mdpr->stream_name_size + mdpr->mime_type_size) + return -1; + mdpr->object_id=_X_BE_32(&mdpr->object_id); mdpr->size=_X_BE_32(&mdpr->size); mdpr->object_version=_X_BE_16(&mdpr->object_version); @@ -123,7 +143,7 @@ static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) { memcpy(&buffer[41+s1], &mdpr->mime_type_size, 1); s2=mdpr->mime_type_size; memcpy(&buffer[42+s1], mdpr->mime_type, s2); - + mdpr->type_specific_len=_X_BE_32(&mdpr->type_specific_len); memcpy(&buffer[42+s1+s2], &mdpr->type_specific_len, 4); mdpr->type_specific_len=_X_BE_32(&mdpr->type_specific_len); @@ -141,20 +161,26 @@ static void rmff_dump_mdpr(rmff_mdpr_t *mdpr, char *buffer) { mdpr->duration=_X_BE_32(&mdpr->duration); mdpr->object_id=_X_BE_32(&mdpr->object_id); + return RMFF_MDPRHEADER_SIZE + s1 + s2 + s3; } -static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) { +static int rmff_dump_cont(rmff_cont_t *cont, uint8_t *buffer, int bufsize) { int p; - if (!cont) return; + if (!cont) return 0; + + if (bufsize < RMFF_CONTHEADER_SIZE + cont->title_len + cont->author_len + + cont->copyright_len + cont->comment_len) + return -1; + cont->object_id=_X_BE_32(&cont->object_id); cont->size=_X_BE_32(&cont->size); cont->object_version=_X_BE_16(&cont->object_version); memcpy(buffer, cont, 8); memcpy(&buffer[8], &cont->object_version, 2); - + cont->title_len=_X_BE_16(&cont->title_len); memcpy(&buffer[10], &cont->title_len, 2); cont->title_len=_X_BE_16(&cont->title_len); @@ -181,11 +207,18 @@ static void rmff_dump_cont(rmff_cont_t *cont, char *buffer) { cont->size=_X_BE_32(&cont->size); cont->object_version=_X_BE_16(&cont->object_version); cont->object_id=_X_BE_32(&cont->object_id); + + return RMFF_CONTHEADER_SIZE + cont->title_len + cont->author_len + + cont->copyright_len + cont->comment_len; } -static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) { +static int rmff_dump_dataheader(rmff_data_t *data, uint8_t *buffer, int bufsize) { + + if (!data) return 0; + + if (bufsize < RMFF_DATAHEADER_SIZE) + return -1; - if (!data) return; data->object_id=_X_BE_32(&data->object_id); data->size=_X_BE_32(&data->size); data->object_version=_X_BE_16(&data->object_version); @@ -195,37 +228,49 @@ static void rmff_dump_dataheader(rmff_data_t *data, char *buffer) { memcpy(buffer, data, 8); memcpy(&buffer[8], &data->object_version, 2); memcpy(&buffer[10], &data->num_packets, 8); - + data->num_packets=_X_BE_32(&data->num_packets); data->next_data_header=_X_BE_32(&data->next_data_header); data->size=_X_BE_32(&data->size); data->object_version=_X_BE_16(&data->object_version); data->object_id=_X_BE_32(&data->object_id); + + return RMFF_DATAHEADER_SIZE; } -int rmff_dump_header(rmff_header_t *h, char *buffer, int max) { +int rmff_dump_header(rmff_header_t *h, void *buf_gen, int max) { + uint8_t *buffer = buf_gen; - int written=0; + int written=0, size; rmff_mdpr_t **stream=h->streams; - rmff_dump_fileheader(h->fileheader, &buffer[written]); - written+=h->fileheader->size; - rmff_dump_prop(h->prop, &buffer[written]); - written+=h->prop->size; - rmff_dump_cont(h->cont, &buffer[written]); - written+=h->cont->size; + if ((size=rmff_dump_fileheader(h->fileheader, &buffer[written], max)) < 0) + return -1; + written+=size; + max -= size; + if ((size=rmff_dump_prop(h->prop, &buffer[written], max)) < 0) + return -1; + written+=size; + max -= size; + if ((size=rmff_dump_cont(h->cont, &buffer[written], max)) < 0) + return -1; + written+=size; + max -= size; if (stream) { while(*stream) { - rmff_dump_mdpr(*stream, &buffer[written]); - written+=(*stream)->size; + if ((size=rmff_dump_mdpr(*stream, &buffer[written], max)) < 0) + return -1; + written+=size; + max -= size; stream++; } } - - rmff_dump_dataheader(h->data, &buffer[written]); - written+=18; + + if ((size=rmff_dump_dataheader(h->data, &buffer[written], max)) < 0) + return -1; + written+=size; return written; } @@ -289,12 +334,14 @@ static rmff_prop_t *rmff_scan_prop(const char *data) { return prop; } -static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { - - rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t)); +static rmff_mdpr_t *rmff_scan_mdpr(const char *data) +{ + rmff_mdpr_t *mdpr = calloc(sizeof(rmff_mdpr_t), 1); mdpr->object_id=_X_BE_32(data); mdpr->size=_X_BE_32(&data[4]); + if (mdpr->size < 46) + goto fail; mdpr->object_version=_X_BE_16(&data[8]); if (mdpr->object_version != 0) { @@ -308,23 +355,42 @@ static rmff_mdpr_t *rmff_scan_mdpr(const char *data) { mdpr->start_time=_X_BE_32(&data[28]); mdpr->preroll=_X_BE_32(&data[32]); mdpr->duration=_X_BE_32(&data[36]); - + mdpr->stream_name_size=data[40]; - mdpr->stream_name = malloc(sizeof(char)*(mdpr->stream_name_size+1)); + if (mdpr->size < 46 + mdpr->stream_name_size) + goto fail; + mdpr->stream_name = malloc(mdpr->stream_name_size+1); + if (!mdpr->stream_name) + goto fail; memcpy(mdpr->stream_name, &data[41], mdpr->stream_name_size); mdpr->stream_name[mdpr->stream_name_size]=0; - + mdpr->mime_type_size=data[41+mdpr->stream_name_size]; - mdpr->mime_type = malloc(sizeof(char)*(mdpr->mime_type_size+1)); + if (mdpr->size < 46 + mdpr->stream_name_size + mdpr->mime_type_size) + goto fail; + mdpr->mime_type = malloc(mdpr->mime_type_size+1); + if (!mdpr->mime_type) + goto fail; memcpy(mdpr->mime_type, &data[42+mdpr->stream_name_size], mdpr->mime_type_size); mdpr->mime_type[mdpr->mime_type_size]=0; - + mdpr->type_specific_len=_X_BE_32(&data[42+mdpr->stream_name_size+mdpr->mime_type_size]); - mdpr->type_specific_data = malloc(sizeof(char)*(mdpr->type_specific_len)); - memcpy(mdpr->type_specific_data, + if (mdpr->size < 46 + mdpr->stream_name_size + mdpr->mime_type_size + mdpr->type_specific_data) + goto fail; + mdpr->type_specific_data = malloc(mdpr->type_specific_len); + if (!mdpr->type_specific_data) + goto fail; + memcpy(mdpr->type_specific_data, &data[46+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len); - + return mdpr; + +fail: + free (mdpr->stream_name); + free (mdpr->mime_type); + free (mdpr->type_specific_data); + free (mdpr); + return NULL; } static rmff_cont_t *rmff_scan_cont(const char *data) { @@ -340,22 +406,22 @@ static rmff_cont_t *rmff_scan_cont(const char *data) { lprintf("warning: unknown object version in CONT: 0x%04x\n", cont->object_version); } cont->title_len=_X_BE_16(&data[10]); - cont->title = malloc(sizeof(char)*(cont->title_len+1)); + cont->title = malloc(cont->title_len+1); memcpy(cont->title, &data[12], cont->title_len); cont->title[cont->title_len]=0; pos=cont->title_len+12; cont->author_len=_X_BE_16(&data[pos]); - cont->author = malloc(sizeof(char)*(cont->author_len+1)); + cont->author = malloc(cont->author_len+1); memcpy(cont->author, &data[pos+2], cont->author_len); cont->author[cont->author_len]=0; pos=pos+2+cont->author_len; cont->copyright_len=_X_BE_16(&data[pos]); - cont->copyright = malloc(sizeof(char)*(cont->copyright_len+1)); + cont->copyright = malloc(cont->copyright_len+1); memcpy(cont->copyright, &data[pos+2], cont->copyright_len); cont->copyright[cont->copyright_len]=0; pos=pos+2+cont->copyright_len; cont->comment_len=_X_BE_16(&data[pos]); - cont->comment = malloc(sizeof(char)*(cont->comment_len+1)); + cont->comment = malloc(cont->comment_len+1); memcpy(cont->comment, &data[pos+2], cont->comment_len); cont->comment[cont->comment_len]=0; @@ -378,7 +444,7 @@ static rmff_data_t *rmff_scan_dataheader(const char *data) { return dh; } - + rmff_header_t *rmff_scan_header(const char *data) { rmff_header_t *header = malloc(sizeof(rmff_header_t)); @@ -402,21 +468,18 @@ rmff_header_t *rmff_scan_header(const char *data) { } header->fileheader=rmff_scan_fileheader(ptr); ptr += header->fileheader->size; - - header->streams = malloc(sizeof(rmff_mdpr_t*)*(header->fileheader->num_headers)); - for (i=0; i<header->fileheader->num_headers; i++) { - header->streams[i]=NULL; - } - + + header->streams = calloc(header->fileheader->num_headers, sizeof(rmff_mdpr_t*)); + for (i=1; i<header->fileheader->num_headers; i++) { chunk_type = _X_BE_32(ptr); - + if (ptr[0] == 0) { lprintf("rmff: warning: only %d of %d header found.\n", i, header->fileheader->num_headers); break; } - + chunk_size=1; switch (chunk_type) { case PROP_TAG: @@ -425,8 +488,11 @@ rmff_header_t *rmff_scan_header(const char *data) { break; case MDPR_TAG: mdpr=rmff_scan_mdpr(ptr); - chunk_size=mdpr->size; - header->streams[mdpr->stream_number]=mdpr; + if (mdpr) /* FIXME: what to do if NULL? */ + { + chunk_size=mdpr->size; + header->streams[mdpr->stream_number]=mdpr; + } break; case CONT_TAG: header->cont=rmff_scan_cont(ptr); @@ -544,7 +610,7 @@ rmff_prop_t *rmff_new_prop ( prop->data_offset=data_offset; prop->num_streams=num_streams; prop->flags=flags; - + return prop; } @@ -563,7 +629,7 @@ rmff_mdpr_t *rmff_new_mdpr( const char *type_specific_data ) { rmff_mdpr_t *mdpr = malloc(sizeof(rmff_mdpr_t)); - + mdpr->object_id=MDPR_TAG; mdpr->object_version=0; @@ -586,10 +652,10 @@ rmff_mdpr_t *rmff_new_mdpr( mdpr->mime_type_size=strlen(mime_type); } mdpr->type_specific_len=type_specific_len; - mdpr->type_specific_data = malloc(sizeof(char)*type_specific_len); + mdpr->type_specific_data = malloc(type_specific_len); memcpy(mdpr->type_specific_data,type_specific_data,type_specific_len); mdpr->mlti_data=NULL; - + mdpr->size=mdpr->stream_name_size+mdpr->mime_type_size+mdpr->type_specific_len+46; return mdpr; @@ -606,7 +672,7 @@ rmff_cont_t *rmff_new_cont(const char *title, const char *author, const char *co cont->author=NULL; cont->copyright=NULL; cont->comment=NULL; - + cont->title_len=0; cont->author_len=0; cont->copyright_len=0; @@ -645,11 +711,11 @@ rmff_data_t *rmff_new_dataheader(uint32_t num_packets, uint32_t next_data_header return data; } - + void rmff_print_header(rmff_header_t *h) { rmff_mdpr_t **stream; - + if(!h) { printf("rmff_print_header: NULL given\n"); return; @@ -710,7 +776,7 @@ void rmff_print_header(rmff_header_t *h) { printf("size : %i\n", h->data->size); printf("packets : %i\n", h->data->num_packets); printf("next DATA : 0x%08x\n", h->data->next_data_header); - } + } } void rmff_fix_header(rmff_header_t *h) { @@ -738,7 +804,7 @@ void rmff_fix_header(rmff_header_t *h) { streams++; } } - + if (h->prop) { if (h->prop->size != 50) { @@ -775,7 +841,7 @@ void rmff_fix_header(rmff_header_t *h) { } num_headers++; - + if (!h->fileheader) { lprintf("rmff_fix_header: no fileheader, creating one"); @@ -790,31 +856,31 @@ void rmff_fix_header(rmff_header_t *h) { num_headers++; if(h->fileheader->num_headers != num_headers) { - lprintf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers); + lprintf("rmff_fix_header: setting num_headers from %i to %i\n", h->fileheader->num_headers, num_headers); h->fileheader->num_headers=num_headers; } if(h->prop) { if (h->prop->data_offset != header_size) { - lprintf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size); + lprintf("rmff_fix_header: setting prop.data_offset from %i to %i\n", h->prop->data_offset, header_size); h->prop->data_offset=header_size; } if (h->prop->num_packets == 0) { int p=(int)(h->prop->avg_bit_rate/8.0*(h->prop->duration/1000.0)/h->prop->avg_packet_size); - lprintf("rmff_fix_header: assuming prop.num_packets=%i\n", p); + lprintf("rmff_fix_header: assuming prop.num_packets=%i\n", p); h->prop->num_packets=p; } if (h->data->num_packets == 0) { - lprintf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets); + lprintf("rmff_fix_header: assuming data.num_packets=%i\n", h->prop->num_packets); h->data->num_packets=h->prop->num_packets; } - - lprintf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size); + + lprintf("rmff_fix_header: assuming data.size=%i\n", h->prop->num_packets*h->prop->avg_packet_size); h->data->size=h->prop->num_packets*h->prop->avg_packet_size; } @@ -826,7 +892,7 @@ int rmff_get_header_size(rmff_header_t *h) { if (!h->prop) return -1; return h->prop->data_offset+18; - + } void rmff_free_header(rmff_header_t *h) { diff --git a/src/input/libreal/rmff.h b/src/input/libreal/rmff.h index d39942088..20b8b8960 100644 --- a/src/input/libreal/rmff.h +++ b/src/input/libreal/rmff.h @@ -32,13 +32,19 @@ #include <string.h> #include <inttypes.h> - #ifndef HAVE_RMFF_H #define HAVE_RMFF_H +#include "attributes.h" #define RMFF_HEADER_SIZE 0x12 +#define RMFF_FILEHEADER_SIZE 18 +#define RMFF_PROPHEADER_SIZE 50 +#define RMFF_MDPRHEADER_SIZE 46 +#define RMFF_CONTHEADER_SIZE 18 +#define RMFF_DATAHEADER_SIZE 18 + #define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \ (((long)(unsigned char)(ch3) ) | \ ( (long)(unsigned char)(ch2) << 8 ) | \ @@ -92,7 +98,7 @@ typedef struct { uint32_t data_offset; uint16_t num_streams; uint16_t flags; - + } rmff_prop_t; typedef struct { @@ -135,11 +141,11 @@ typedef struct { char *copyright; uint16_t comment_len; char *comment; - + } rmff_cont_t; typedef struct { - + uint32_t object_id; uint32_t size; uint16_t object_version; @@ -172,7 +178,7 @@ typedef struct { /* * constructors for header structs */ - + rmff_fileheader_t *rmff_new_fileheader(uint32_t num_headers); rmff_prop_t *rmff_new_prop ( @@ -214,7 +220,7 @@ rmff_data_t *rmff_new_dataheader( /* * reads header infos from data and returns a newly allocated header struct */ -rmff_header_t *rmff_scan_header(const char *data); +rmff_header_t *rmff_scan_header(const char *data) XINE_MALLOC; /* * scans a data packet header. Notice, that this function does not allocate @@ -225,7 +231,7 @@ void rmff_scan_pheader(rmff_pheader_t *h, char *data); /* * reads header infos from stream and returns a newly allocated header struct */ -rmff_header_t *rmff_scan_header_stream(int fd); +rmff_header_t *rmff_scan_header_stream(int fd) XINE_MALLOC; /* * prints header information in human readible form to stdout @@ -241,11 +247,11 @@ void rmff_fix_header(rmff_header_t *h); * returns the size of the header (incl. first data-header) */ int rmff_get_header_size(rmff_header_t *h); - + /* * dumps the header <h> to <buffer>. <max> is the size of <buffer> */ -int rmff_dump_header(rmff_header_t *h, char *buffer, int max); +int rmff_dump_header(rmff_header_t *h, void *buf_gen, int max); /* * dumps a packet header diff --git a/src/input/libreal/sdpplin.c b/src/input/libreal/sdpplin.c index c62b6bbc1..b7e5218cb 100644 --- a/src/input/libreal/sdpplin.c +++ b/src/input/libreal/sdpplin.c @@ -19,7 +19,11 @@ * * sdp/sdpplin parser. */ - + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "sdpplin" #define LOG_VERBOSE /* @@ -58,9 +62,10 @@ static char *b64_decode(const char *in, char *out, int *size) dtable['='] = 0; k=0; - + /*CONSTANTCONDITION*/ - for (j=0; j<strlen(in); j+=4) + const size_t in_len = strlen(in); + for (j=0; j<in_len; j+=4) { char a[4], b[4]; @@ -99,12 +104,12 @@ static char *nl(char *data) { static int filter(const char *in, const char *filter, char **out) { - int flen=strlen(filter); + size_t flen=strlen(filter); size_t len; - + if (!in) return 0; - + len = (strchr(in,'\n')) ? (size_t)(strchr(in,'\n')-in) : strlen(in); if (!strncmp(in,filter,flen)) @@ -117,16 +122,16 @@ static int filter(const char *in, const char *filter, char **out) { return len-flen; } - + return 0; } -static sdpplin_stream_t *sdpplin_parse_stream(char **data) { +static sdpplin_stream_t *XINE_MALLOC sdpplin_parse_stream(char **data) { - sdpplin_stream_t *desc = xine_xmalloc(sizeof(sdpplin_stream_t)); + sdpplin_stream_t *desc = calloc(1, sizeof(sdpplin_stream_t)); char *buf=xine_buffer_init(32); char *decoded=xine_buffer_init(32); int handled; - + if (filter(*data, "m=", &buf)) { desc->id = strdup(buf); } else @@ -141,9 +146,16 @@ static sdpplin_stream_t *sdpplin_parse_stream(char **data) { while (*data && **data && *data[0]!='m') { handled=0; - + if(filter(*data,"a=control:streamid=",&buf)) { - desc->stream_id=atoi(buf); + /* This way negative values are mapped to unfeasibly high + * values, and will be discarded afterward + */ + unsigned long tmp = strtoul(buf, NULL, 10); + if ( tmp > UINT16_MAX ) + lprintf("stream id out of bound: %lu\n", tmp); + else + desc->stream_id=tmp; handled=1; *data=nl(*data); } @@ -163,7 +175,7 @@ static sdpplin_stream_t *sdpplin_parse_stream(char **data) { handled=1; *data=nl(*data); } - + if(filter(*data,"a=StartTime:integer;",&buf)) { desc->start_time=atoi(buf); handled=1; @@ -199,14 +211,14 @@ static sdpplin_stream_t *sdpplin_parse_stream(char **data) { if(filter(*data,"a=OpaqueData:buffer;",&buf)) { decoded = b64_decode(buf, decoded, &(desc->mlti_data_size)); if ( decoded != NULL ) { - desc->mlti_data = malloc(sizeof(char)*desc->mlti_data_size); + desc->mlti_data = malloc(desc->mlti_data_size); memcpy(desc->mlti_data, decoded, desc->mlti_data_size); handled=1; *data=nl(*data); lprintf("mlti_data_size: %i\n", desc->mlti_data_size); } } - + if(filter(*data,"a=ASMRuleBook:string;",&buf)) { desc->asm_rule_book=strdup(buf); handled=1; @@ -226,13 +238,13 @@ static sdpplin_stream_t *sdpplin_parse_stream(char **data) { xine_buffer_free(buf); xine_buffer_free(decoded); - + return desc; } sdpplin_t *sdpplin_parse(char *data) { - sdpplin_t *desc = xine_xmalloc(sizeof(sdpplin_t)); + sdpplin_t *desc = calloc(1, sizeof(sdpplin_t)); sdpplin_stream_t *stream; char *buf=xine_buffer_init(32); char *decoded=xine_buffer_init(32); @@ -244,7 +256,7 @@ sdpplin_t *sdpplin_parse(char *data) { while (data && *data) { handled=0; - + if (filter(data, "m=", &buf)) { if ( ! desc->stream ) { fprintf(stderr, "sdpplin.c: stream identifier found before stream count, skipping."); @@ -252,7 +264,10 @@ sdpplin_t *sdpplin_parse(char *data) { } stream=sdpplin_parse_stream(&data); lprintf("got data for stream id %u\n", stream->stream_id); - desc->stream[stream->stream_id]=stream; + if ( stream->stream_id >= desc->stream_count ) + lprintf("stream id %u is greater than stream count %u\n", stream->stream_id, desc->stream_count); + else + desc->stream[stream->stream_id]=stream; continue; } @@ -264,7 +279,7 @@ sdpplin_t *sdpplin_parse(char *data) { data=nl(data); } } - + if(filter(data,"a=Author:buffer;",&buf)) { decoded=b64_decode(buf, decoded, &len); if ( decoded != NULL ) { @@ -273,7 +288,7 @@ sdpplin_t *sdpplin_parse(char *data) { data=nl(data); } } - + if(filter(data,"a=Copyright:buffer;",&buf)) { decoded=b64_decode(buf, decoded, &len); if ( decoded != NULL ) { @@ -282,7 +297,7 @@ sdpplin_t *sdpplin_parse(char *data) { data=nl(data); } } - + if(filter(data,"a=Abstract:buffer;",&buf)) { decoded=b64_decode(buf, decoded, &len); if ( decoded != NULL ) { @@ -291,10 +306,17 @@ sdpplin_t *sdpplin_parse(char *data) { data=nl(data); } } - + if(filter(data,"a=StreamCount:integer;",&buf)) { - desc->stream_count=atoi(buf); - desc->stream = malloc(sizeof(sdpplin_stream_t*)*desc->stream_count); + /* This way negative values are mapped to unfeasibly high + * values, and will be discarded afterward + */ + unsigned long tmp = strtoul(buf, NULL, 10); + if ( tmp > UINT16_MAX ) + lprintf("stream count out of bound: %lu\n", tmp); + else + desc->stream_count = tmp; + desc->stream = calloc(desc->stream_count, sizeof(sdpplin_stream_t*)); handled=1; data=nl(data); } @@ -318,7 +340,7 @@ sdpplin_t *sdpplin_parse(char *data) { xine_buffer_free(buf); xine_buffer_free(decoded); - + return desc; } diff --git a/src/input/libreal/sdpplin.h b/src/input/libreal/sdpplin.h index cb3b434d4..2296c31e7 100644 --- a/src/input/libreal/sdpplin.h +++ b/src/input/libreal/sdpplin.h @@ -19,7 +19,7 @@ * * sdp/sdpplin parser. */ - + #ifndef HAVE_SDPPLIN_H #define HAVE_SDPPLIN_H @@ -37,7 +37,7 @@ typedef struct { char *id; char *bandwidth; - int stream_id; + uint16_t stream_id; char *range; char *length; char *rtpmap; @@ -81,7 +81,7 @@ typedef struct { int flags; int is_real_data_type; - int stream_count; + uint16_t stream_count; char *title; char *author; char *copyright; @@ -98,10 +98,10 @@ typedef struct { int duration; sdpplin_stream_t **stream; - + } sdpplin_t; -sdpplin_t *sdpplin_parse(char *data); +sdpplin_t *sdpplin_parse(char *data) XINE_MALLOC; void sdpplin_free(sdpplin_t *description); diff --git a/src/input/librtsp/rtsp.c b/src/input/librtsp/rtsp.c index 530ffc6cf..ebac49079 100644 --- a/src/input/librtsp/rtsp.c +++ b/src/input/librtsp/rtsp.c @@ -21,6 +21,10 @@ * *not* RFC 2326 compilant yet. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <unistd.h> #include <stdio.h> #include <assert.h> @@ -40,7 +44,7 @@ #define LOG_VERBOSE /* #define LOG -*/ +*/ #include "rtsp.h" #include "io_helper.h" @@ -65,7 +69,7 @@ struct rtsp_s { char *server; unsigned int server_state; uint32_t server_caps; - + unsigned int cseq; char *session; @@ -101,17 +105,17 @@ const char rtsp_protocol_version[]="RTSP/1.0"; * rtsp_get gets a line from stream * and returns a null terminated string (must be freed). */ - + static char *rtsp_get(rtsp_t *s) { char *buffer = malloc(BUF_SIZE); char *string = NULL; - + if ( _x_io_tcp_read_line(s->stream, s->s, buffer, BUF_SIZE) >= 0 ) { lprintf("<< '%s'\n", buffer); string = strdup( buffer ); } - + free(buffer); return string; } @@ -120,10 +124,10 @@ static char *rtsp_get(rtsp_t *s) { /* * rtsp_put puts a line on stream */ - + static void rtsp_put(rtsp_t *s, const char *string) { - int len=strlen(string); + size_t len=strlen(string); char *buf = malloc(sizeof(char)*len+2); lprintf(">> '%s'", string); @@ -133,7 +137,7 @@ static void rtsp_put(rtsp_t *s, const char *string) { buf[len+1]=0x0a; _x_io_tcp_write(s->stream, s->s, buf, len+2); - + lprintf("done.\n"); free(buf); @@ -147,7 +151,7 @@ static int rtsp_get_code(rtsp_t *s, const char *string) { char buf[4]; int code=0; - + if (!strncmp(string, rtsp_protocol_version, strlen(rtsp_protocol_version))) { memcpy(buf, string+strlen(rtsp_protocol_version)+1, 3); @@ -158,7 +162,7 @@ static int rtsp_get_code(rtsp_t *s, const char *string) { return RTSP_STATUS_SET_PARAMETER; } - if(code != 200) + if(code != 200) xprintf(s->stream->xine, XINE_VERBOSITY_DEBUG, "librtsp: server responds: '%s'\n", string); return code; @@ -172,10 +176,8 @@ static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) { char **payload=s->scheduled; char *buf; - - buf = malloc(strlen(type)+strlen(what)+strlen(rtsp_protocol_version)+3); - - sprintf(buf,"%s %s %s",type, what, rtsp_protocol_version); + + asprintf(&buf,"%s %s %s",type, what, rtsp_protocol_version); rtsp_put(s,buf); free(buf); if (payload) @@ -194,14 +196,13 @@ static void rtsp_send_request(rtsp_t *s, const char *type, const char *what) { static void rtsp_schedule_standard(rtsp_t *s) { char tmp[17]; - + sprintf(tmp, "Cseq: %u", s->cseq); rtsp_schedule_field(s, tmp); - + if (s->session) { char *buf; - buf = malloc(strlen(s->session)+15); - sprintf(buf, "Session: %s", s->session); + asprintf(&buf, "Session: %s", s->session); rtsp_schedule_field(s, buf); free(buf); } @@ -209,7 +210,7 @@ static void rtsp_schedule_standard(rtsp_t *s) { /* * get the answers, if server responses with something != 200, return NULL */ - + static int rtsp_get_answers(rtsp_t *s) { char *answer=NULL; @@ -217,7 +218,7 @@ static int rtsp_get_answers(rtsp_t *s) { char **answer_ptr=s->answers; int code; int ans_count = 0; - + answer=rtsp_get(s); if (!answer) return 0; @@ -225,55 +226,49 @@ static int rtsp_get_answers(rtsp_t *s) { free(answer); rtsp_free_answers(s); - + do { /* while we get answer lines */ - + answer=rtsp_get(s); if (!answer) return 0; - - if (!strncasecmp(answer,"Cseq:",5)) { - sscanf(answer,"%*s %u",&answer_seq); + + if (!strncasecmp(answer,"Cseq: ",6)) { + sscanf(answer+6,"%u",&answer_seq); if (s->cseq != answer_seq) { lprintf("warning: Cseq mismatch. got %u, assumed %u", answer_seq, s->cseq); s->cseq=answer_seq; } } - if (!strncasecmp(answer,"Server:",7)) { - char *buf = xine_xmalloc(strlen(answer)); - sscanf(answer,"%*s %s",buf); - if (s->server) free(s->server); - s->server=strdup(buf); - free(buf); + if (!strncasecmp(answer,"Server: ",8)) { + free(s->server); + s->server = strdup(answer + 8); } - if (!strncasecmp(answer,"Session:",8)) { - char *buf = xine_xmalloc(strlen(answer)); - sscanf(answer,"%*s %s",buf); + if (!strncasecmp(answer,"Session: ",9)) { + char *tmp = answer + 9; if (s->session) { - if (strcmp(buf, s->session)) { - xprintf(s->stream->xine, XINE_VERBOSITY_DEBUG, - "rtsp: warning: setting NEW session: %s\n", buf); - free(s->session); - s->session=strdup(buf); + if (strcmp(tmp, s->session)) { + xprintf(s->stream->xine, XINE_VERBOSITY_DEBUG, + "rtsp: warning: setting NEW session: %s\n", tmp); + s->session=strdup(tmp); } } else { - lprintf("setting session id to: %s\n", buf); + lprintf("setting session id to: %s\n", tmp); - s->session=strdup(buf); + s->session=strdup(tmp); } - free(buf); } *answer_ptr=answer; answer_ptr++; } while ((strlen(answer)!=0) && (++ans_count < MAX_FIELDS)); - + s->cseq++; - + *answer_ptr=NULL; rtsp_schedule_standard(s); - + return code; } @@ -283,7 +278,7 @@ static int rtsp_get_answers(rtsp_t *s) { int rtsp_send_ok(rtsp_t *s) { char cseq[16]; - + rtsp_put(s, "RTSP/1.0 200 OK"); sprintf(cseq,"CSeq: %u", s->cseq); rtsp_put(s, cseq); @@ -304,8 +299,7 @@ int rtsp_request_options(rtsp_t *s, const char *what) { buf=strdup(what); } else { - buf = malloc(sizeof(char)*(strlen(s->host)+16)); - sprintf(buf,"rtsp://%s:%i", s->host, s->port); + asprintf(&buf,"rtsp://%s:%i", s->host, s->port); } rtsp_send_request(s,"OPTIONS",buf); free(buf); @@ -321,19 +315,18 @@ int rtsp_request_describe(rtsp_t *s, const char *what) { buf=strdup(what); } else { - buf = malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16)); - sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); + asprintf(&buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); } rtsp_send_request(s,"DESCRIBE",buf); free(buf); - + return rtsp_get_answers(s); } int rtsp_request_setup(rtsp_t *s, const char *what) { rtsp_send_request(s,"SETUP",what); - + return rtsp_get_answers(s); } @@ -345,12 +338,11 @@ int rtsp_request_setparameter(rtsp_t *s, const char *what) { buf=strdup(what); } else { - buf = malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16)); - sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); + asprintf(&buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); } rtsp_send_request(s,"SET_PARAMETER",buf); free(buf); - + return rtsp_get_answers(s); } @@ -362,19 +354,18 @@ int rtsp_request_play(rtsp_t *s, const char *what) { buf=strdup(what); } else { - buf = malloc(sizeof(char)*(strlen(s->host)+strlen(s->path)+16)); - sprintf(buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); + asprintf(&buf,"rtsp://%s:%i/%s", s->host, s->port, s->path); } rtsp_send_request(s,"PLAY",buf); free(buf); - + return rtsp_get_answers(s); } int rtsp_request_tearoff(rtsp_t *s, const char *what) { rtsp_send_request(s,"TEAROFF",what); - + return rtsp_get_answers(s); } @@ -394,7 +385,7 @@ int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) { char *rest=rtsp_get(s); if (!rest) return -1; - + seq=-1; do { free(rest); @@ -412,8 +403,7 @@ int rtsp_read_data(rtsp_t *s, char *buffer, unsigned int size) { } /* lets make the server happy */ rtsp_put(s, "RTSP/1.0 451 Parameter Not Understood"); - rest = malloc(sizeof(char)*17); - sprintf(rest,"CSeq: %u", seq); + asprintf(&rest,"CSeq: %u", seq); rtsp_put(s, rest); free(rest); rtsp_put(s, ""); @@ -442,14 +432,14 @@ rtsp_t *rtsp_connect(xine_stream_t *stream, const char *mrl, const char *user_ag char *slash, *colon; int hostend, i; size_t pathbegin; - + if (strncmp(mrl,"rtsp://",7)) { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp: bad mrl: %s\n"), mrl); free(s); return NULL; } - + mrl_ptr+=7; for (i=0; i<MAX_FIELDS; i++) { @@ -463,14 +453,14 @@ rtsp_t *rtsp_connect(xine_stream_t *stream, const char *mrl, const char *user_ag s->path=NULL; s->mrl=NULL; s->mrl=strdup(mrl); - + s->server=NULL; s->server_state=0; s->server_caps=0; - + s->cseq=0; s->session=NULL; - + if (user_agent) s->user_agent=strdup(user_agent); else @@ -480,20 +470,18 @@ rtsp_t *rtsp_connect(xine_stream_t *stream, const char *mrl, const char *user_ag colon=strchr(mrl_ptr,':'); if(!slash) slash=mrl_ptr+strlen(mrl_ptr)+1; - if(!colon) colon=slash; + if(!colon) colon=slash; if(colon > slash) colon=slash; pathbegin=slash-mrl_ptr; hostend=colon-mrl_ptr; - s->host = malloc(sizeof(char)*hostend+1); - strncpy(s->host, mrl_ptr, hostend); - s->host[hostend]=0; + s->host = strndup(mrl_ptr, hostend); if (pathbegin < strlen(mrl_ptr)) s->path=strdup(mrl_ptr+pathbegin+1); if (colon != slash) { char buffer[pathbegin-hostend]; - + strncpy(buffer,mrl_ptr+hostend+1, pathbegin-hostend-1); buffer[pathbegin-hostend-1]=0; s->port=atoi(buffer); @@ -529,7 +517,7 @@ rtsp_t *rtsp_connect(xine_stream_t *stream, const char *mrl, const char *user_ag /* - * closes an rtsp connection + * closes an rtsp connection */ void rtsp_close(rtsp_t *s) { @@ -542,7 +530,7 @@ void rtsp_close(rtsp_t *s) { if (s->user_agent) free(s->user_agent); rtsp_free_answers(s); rtsp_unschedule_all(s); - free(s); + free(s); } /* @@ -554,7 +542,7 @@ char *rtsp_search_answers(rtsp_t *s, const char *tag) { char **answer; char *ptr; - + if (!s->answers) return NULL; answer=s->answers; @@ -603,7 +591,7 @@ char *rtsp_get_mrl(rtsp_t *s) { void rtsp_schedule_field(rtsp_t *s, const char *string) { int i=0; - + if (!string) return; while(s->scheduled[i]) { @@ -613,13 +601,13 @@ void rtsp_schedule_field(rtsp_t *s, const char *string) { } /* - * removes the first scheduled field which prefix matches string. + * removes the first scheduled field which prefix matches string. */ void rtsp_unschedule_field(rtsp_t *s, const char *string) { char **ptr=s->scheduled; - + if (!string) return; while(*ptr) { @@ -640,7 +628,7 @@ void rtsp_unschedule_field(rtsp_t *s, const char *string) { void rtsp_unschedule_all(rtsp_t *s) { char **ptr; - + if (!s->scheduled) return; ptr=s->scheduled; @@ -657,7 +645,7 @@ void rtsp_unschedule_all(rtsp_t *s) { void rtsp_free_answers(rtsp_t *s) { char **answer; - + if (!s->answers) return; answer=s->answers; diff --git a/src/input/librtsp/rtsp.h b/src/input/librtsp/rtsp.h index dc2624459..a00035aef 100644 --- a/src/input/librtsp/rtsp.h +++ b/src/input/librtsp/rtsp.h @@ -20,7 +20,7 @@ * a minimalistic implementation of rtsp protocol, * *not* RFC 2326 compilant yet. */ - + #ifndef HAVE_RTSP_H #define HAVE_RTSP_H @@ -40,7 +40,7 @@ typedef struct rtsp_s rtsp_t; -rtsp_t* rtsp_connect (xine_stream_t *stream, const char *mrl, const char *user_agent); +rtsp_t* rtsp_connect (xine_stream_t *stream, const char *mrl, const char *user_agent) XINE_MALLOC; int rtsp_request_options(rtsp_t *s, const char *what); int rtsp_request_describe(rtsp_t *s, const char *what); diff --git a/src/input/librtsp/rtsp_session.c b/src/input/librtsp/rtsp_session.c index f3ddb59bc..2ae002662 100644 --- a/src/input/librtsp/rtsp_session.c +++ b/src/input/librtsp/rtsp_session.c @@ -20,6 +20,10 @@ * high level interface to rtsp servers. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -78,14 +82,14 @@ const char *rtsp_bandwidth_strs[]={"14.4 Kbps (Modem)", "19.2 Kbps (Modem)", rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl) { - rtsp_session_t *rtsp_session = xine_xmalloc(sizeof(rtsp_session_t)); + rtsp_session_t *rtsp_session = calloc(1, sizeof(rtsp_session_t)); xine_t *xine = stream->xine; char *server; char *mrl_line=strdup(mrl); rmff_header_t *h; int bandwidth_id; uint32_t bandwidth; - + bandwidth_id = xine->config->register_enum(xine->config, "media.network.bandwidth", 10, (char **)rtsp_bandwidth_strs, _("network bandwidth"), @@ -96,7 +100,7 @@ rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl) { bandwidth = rtsp_bandwidths[bandwidth_id]; rtsp_session->recv = xine_buffer_init(BUF_SIZE); - + connect: /* connect to server */ @@ -145,18 +149,24 @@ connect: return NULL; } } - - rtsp_session->header_left = + + rtsp_session->header_left = rtsp_session->header_len = rmff_dump_header(h,rtsp_session->header,HEADER_SIZE); + if (rtsp_session->header_len < 0) { + xprintf (stream->xine, XINE_VERBOSITY_LOG, + _("rtsp_session: rtsp server returned overly-large headers, session can not be established.\n")); + goto session_abort; + } xine_buffer_copyin(rtsp_session->recv, 0, rtsp_session->header, rtsp_session->header_len); rtsp_session->recv_size = rtsp_session->header_len; rtsp_session->recv_read = 0; - + } else { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("rtsp_session: rtsp server type '%s' not supported yet. sorry.\n"), server); + session_abort: rtsp_close(rtsp_session->s); free(server); xine_buffer_free(rtsp_session->recv); @@ -164,29 +174,29 @@ connect: return NULL; } free(server); - + return rtsp_session; } void rtsp_session_set_start_time (rtsp_session_t *this, int start_time) { - + if (start_time >= 0) this->start_time = start_time; } static void rtsp_session_play (rtsp_session_t *this) { - + char buf[256]; - - snprintf (buf, sizeof(buf), "Range: npt=%d.%03d-", + + snprintf (buf, sizeof(buf), "Range: npt=%d.%03d-", this->start_time/1000, this->start_time%1000); - + rtsp_schedule_field (this->s, buf); rtsp_request_play (this->s,NULL); } int rtsp_session_read (rtsp_session_t *this, char *data, int len) { - + int to_copy; char *dest=data; char *source=this->recv + this->recv_read; @@ -194,22 +204,22 @@ int rtsp_session_read (rtsp_session_t *this, char *data, int len) { if (len < 0) return 0; - + if (this->header_left) { if (len > this->header_left) len = this->header_left; - + this->header_left -= len; } - + to_copy = len; while (to_copy > fill) { - + if (!this->playing) { rtsp_session_play (this); this->playing = 1; } - + memcpy(dest, source, fill); to_copy -= fill; dest += fill; @@ -224,7 +234,7 @@ int rtsp_session_read (rtsp_session_t *this, char *data, int len) { return len-to_copy; } } - + memcpy(dest, source, to_copy); this->recv_read += to_copy; diff --git a/src/input/librtsp/rtsp_session.h b/src/input/librtsp/rtsp_session.h index b47db0730..33ac579e1 100644 --- a/src/input/librtsp/rtsp_session.h +++ b/src/input/librtsp/rtsp_session.h @@ -25,7 +25,7 @@ typedef struct rtsp_session_s rtsp_session_t; -rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl); +rtsp_session_t *rtsp_session_start(xine_stream_t *stream, char *mrl) XINE_MALLOC; void rtsp_session_set_start_time(rtsp_session_t *this, int start_time); diff --git a/src/input/media_helper.c b/src/input/media_helper.c index 288ed4205..e19ca63e6 100644 --- a/src/input/media_helper.c +++ b/src/input/media_helper.c @@ -1,18 +1,18 @@ -/* - * Copyright (C) 2000-2003 the xine project, - * +/* + * Copyright (C) 2000-2003 the xine project, + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -66,14 +66,14 @@ static int media_umount_media(const char *device) if(waitpid(pid, &status, 0) == -1) { if (errno != EINTR) return -1; - } + } else { return WEXITSTATUS(status); } } while(1); - + return -1; -} +} #endif int media_eject_media (xine_t *xine, const char *device) @@ -91,7 +91,7 @@ int media_eject_media (xine_t *xine, const char *device) return 0; -#else +#else int fd; @@ -109,14 +109,14 @@ int media_eject_media (xine_t *xine, const char *device) case CDS_TRAY_OPEN: if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) { #ifdef LOG_MEDIA_EJECT - printf("input_dvd: CDROMCLOSETRAY failed: %s\n", strerror(errno)); + printf("input_dvd: CDROMCLOSETRAY failed: %s\n", strerror(errno)); #endif } break; case CDS_DISC_OK: if((ret = ioctl(fd, CDROMEJECT)) != 0) { #ifdef LOG_MEDIA_EJECT - printf("input_dvd: CDROMEJECT failed: %s\n", strerror(errno)); + printf("input_dvd: CDROMEJECT failed: %s\n", strerror(errno)); #endif } break; diff --git a/src/input/mms.c b/src/input/mms.c index f11a89cf3..c84ce7beb 100644 --- a/src/input/mms.c +++ b/src/input/mms.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2002-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -54,7 +54,7 @@ #define LOG_MODULE "mms" #define LOG_VERBOSE /* -#define LOG +#define LOG */ #include "xine_internal.h" #include "xineutils.h" @@ -65,8 +65,8 @@ #include "../demuxers/asfheader.h" -/* - * mms specific types +/* + * mms specific types */ #define MMST_PORT 1755 @@ -107,9 +107,9 @@ struct mms_packet_header_s { struct mms_s { xine_stream_t *stream; - + int s; - + /* url parsing */ char *url; char *proto; @@ -123,12 +123,12 @@ struct mms_s { char scmd[CMD_HEADER_LEN + CMD_BODY_LEN]; char *scmd_body; /* pointer to &scmd[CMD_HEADER_LEN] */ int scmd_len; /* num bytes written in header */ - + /* receive buffer */ uint8_t buf[BUF_SIZE]; int buf_size; int buf_read; - + asf_header_t *asf_header; uint8_t asf_header_buffer[ASF_HEADER_LEN]; uint32_t asf_header_len; @@ -137,13 +137,13 @@ struct mms_s { int seq_num; char guid[37]; int bandwidth; - + off_t current_pos; int eos; uint8_t live_flag; - - uint8_t playing; + + uint8_t playing; double start_time; }; @@ -202,9 +202,9 @@ static void mms_buffer_put_64 (mms_buffer_t *mms_buffer, uint64_t value) { } +#ifdef LOG static void print_command (char *data, int len) { -#ifdef LOG int i; int dir = _X_LE_32 (data + 36) >> 16; int comm = _X_LE_32 (data + 36) & 0xFFFF; @@ -230,18 +230,20 @@ static void print_command (char *data, int len) { for (i = (CMD_HEADER_LEN + CMD_PREFIX_LEN); i < (CMD_HEADER_LEN + CMD_PREFIX_LEN + len); i += 1) { unsigned char c = data[i]; - + if ((c >= 32) && (c < 128)) printf ("%c", c); else printf (" %02x ", c); - + } if (len > CMD_HEADER_LEN) printf ("\n"); printf ("----------------------------------------------\n"); +} +#else +# define print_command(data, len) #endif -} @@ -269,7 +271,7 @@ static int send_command (mms_t *this, int command, mms_buffer_put_32 (&command_buffer, len8 + 2); mms_buffer_put_32 (&command_buffer, 0x00030000 | command); /* dir | command */ /* end of the 40 byte command header */ - + mms_buffer_put_32 (&command_buffer, prefix1); mms_buffer_put_32 (&command_buffer, prefix2); @@ -288,7 +290,7 @@ static int send_command (mms_t *this, int command, #ifdef USE_ICONV static iconv_t string_utf16_open() { - return iconv_open("UTF-16LE", nl_langinfo(CODESET)); + return iconv_open("UTF-16LE", "UTF-8"); } static void string_utf16_close(iconv_t url_conv) { @@ -352,14 +354,14 @@ static int get_packet_header (mms_t *this, mms_packet_header_t *header) { len = _x_io_tcp_read (this->stream, this->s, (char*)this->buf, 8); if (len != 8) goto error; - + if (_X_LE_32(this->buf + 4) == 0xb00bface) { /* command packet */ header->flags = this->buf[3]; len = _x_io_tcp_read (this->stream, this->s, (char*)(this->buf + 8), 4); if (len != 4) goto error; - + header->packet_len = _X_LE_32(this->buf + 8) + 4; if (header->packet_len > BUF_SIZE - 12) { header->packet_len = 0; @@ -381,7 +383,7 @@ static int get_packet_header (mms_t *this, mms_packet_header_t *header) { } } return packet_type; - + error: lprintf("read error, len=%zd\n", len); return MMS_PACKET_ERR; @@ -393,7 +395,7 @@ static int get_packet_command (mms_t *this, uint32_t packet_len) { int command = 0; size_t len; - + /* always enter this loop */ lprintf("packet_len: %d bytes\n", packet_len); @@ -403,18 +405,18 @@ static int get_packet_command (mms_t *this, uint32_t packet_len) { } print_command ((char*)this->buf, len); - + /* check protocol type ("MMS ") */ if (_X_LE_32(this->buf + 12) != 0x20534D4D) { lprintf("unknown protocol type: %c%c%c%c (0x%08X)\n", this->buf[12], this->buf[13], this->buf[14], this->buf[15], - _X_LE_32(this->buf + 12)); + _X_LE_32(this->buf + 12)); return 0; } command = _X_LE_32 (this->buf + 36) & 0xFFFF; lprintf("command = 0x%2x\n", command); - + return command; } @@ -429,9 +431,9 @@ static int get_answer (mms_t *this) { break; case MMS_PACKET_COMMAND: command = get_packet_command (this, header.packet_len); - + if (command == 0x1b) { - + if (!send_command (this, 0x1b, 0, 0, 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "libmms: failed to send command\n"); @@ -450,7 +452,7 @@ static int get_answer (mms_t *this) { "libmms: unexpected asf packet\n"); break; } - + return command; } @@ -459,7 +461,7 @@ static int get_asf_header (mms_t *this) { off_t len; int stop = 0; - + this->asf_header_read = 0; this->asf_header_len = 0; @@ -475,9 +477,9 @@ static int get_asf_header (mms_t *this) { break; case MMS_PACKET_COMMAND: command = get_packet_command (this, header.packet_len); - + if (command == 0x1b) { - + if (!send_command (this, 0x1b, 0, 0, 0)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "libmms: failed to send command\n"); @@ -558,11 +560,11 @@ static void report_progress (xine_stream_t *stream, int p) { prg.description = _("Connecting MMS server (over tcp)..."); prg.percent = p; - + event.type = XINE_EVENT_PROGRESS; event.data = &prg; event.data_length = sizeof (xine_progress_data_t); - + xine_event_send (stream, &event); } @@ -572,11 +574,11 @@ static void report_progress (xine_stream_t *stream, int p) { */ static int mms_tcp_connect(mms_t *this) { int progress, res; - + if (!this->port) this->port = MMST_PORT; - /* - * try to connect + /* + * try to connect */ lprintf("try to connect to %s on port %d \n", this->host, this->port); this->s = _x_io_tcp_connect (this->stream, this->host, this->port); @@ -624,7 +626,7 @@ static int mms_choose_best_streams(mms_t *this) { /* choose the best quality for the audio stream */ asf_header_choose_streams (this->asf_header, this->bandwidth, &video_stream, &audio_stream); - + lprintf("selected streams: audio %d, video %d\n", audio_stream, video_stream); lprintf("disabling other streams\n"); memset (this->scmd_body, 0, 40); @@ -645,8 +647,8 @@ static int mms_choose_best_streams(mms_t *this) { } /* command 0x33 */ - if (!send_command (this, 0x33, this->asf_header->stream_count, - 0xFFFF | this->asf_header->streams[0]->stream_number << 16, + if (!send_command (this, 0x33, this->asf_header->stream_count, + 0xFFFF | this->asf_header->streams[0]->stream_number << 16, this->asf_header->stream_count * 6 + 2)) { xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "libmms: mms_choose_best_streams failed\n"); @@ -674,11 +676,11 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { mms_t *this; char str[1024]; int res; - + if (!url) return NULL; - this = (mms_t*) xine_xmalloc (sizeof (mms_t)); + this = calloc(1, sizeof (mms_t)); this->stream = stream; this->url = strdup (url); @@ -694,23 +696,23 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { this->eos = 0; report_progress (stream, 0); - + if (!_x_parse_url (this->url, &this->proto, &this->host, &this->port, - &this->user, &this->password, &this->uri)) { + &this->user, &this->password, &this->uri, NULL)) { lprintf ("invalid url\n"); goto fail; } - + if (!mmst_valid_proto(this->proto)) { lprintf ("unsupported protocol\n"); goto fail; } - + if (mms_tcp_connect(this)) { goto fail; } report_progress (stream, 30); - + #ifdef USE_ICONV url_conv = string_utf16_open(); #endif @@ -730,13 +732,13 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { "libmms: failed to send command 0x01\n"); goto fail; } - + if ((res = get_answer (this)) != 0x01) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "libmms: unexpected response: %02x (0x01)\n", res); goto fail; } - + report_progress (stream, 40); /* TODO: insert network timing request here */ @@ -769,32 +771,38 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { /* command 0x5 */ { mms_buffer_t command_buffer; - char *path; - int pathlen; + char *path, *unescaped; + size_t pathlen; + + unescaped = strdup (this->uri); + if (!unescaped) + goto fail; + _x_mrl_unescape (unescaped); /* remove the first '/' */ - path = this->uri; - pathlen = strlen(path); + path = unescaped; + pathlen = strlen (path); if (pathlen > 1) { path++; pathlen--; } - + lprintf("send command 0x05\n"); mms_buffer_init(&command_buffer, this->scmd_body); mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ mms_buffer_put_32 (&command_buffer, 0x00000000); /* ?? */ string_utf16 (url_conv, this->scmd_body + command_buffer.pos, path, pathlen); + free (unescaped); if (!send_command (this, 5, 1, 0xffffffff, pathlen * 2 + 12)) goto fail; } - + switch (res = get_answer (this)) { case 0x06: { int xx, yy; /* no authentication required */ - + /* Warning: sdp is not right here */ xx = this->buf[62]; yy = this->buf[63]; @@ -837,7 +845,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { goto fail; } } - + if ((res = get_answer (this)) != 0x11) { xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "libmms: unexpected response: %02x (0x11)\n", res); @@ -890,7 +898,7 @@ mms_t *mms_connect (xine_stream_t *stream, const char *url, int bandwidth) { #endif lprintf("mms_connect: passed\n" ); - + return this; fail: @@ -916,19 +924,19 @@ fail: static int get_media_packet (mms_t *this) { mms_packet_header_t header; off_t len; - + switch (get_packet_header (this, &header)) { case MMS_PACKET_ERR: xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "libmms: failed to read mms packet header\n"); return 0; break; - + case MMS_PACKET_COMMAND: { int command; command = get_packet_command (this, header.packet_len); - + switch (command) { case 0x1e: { @@ -942,10 +950,10 @@ static int get_media_packet (mms_t *this) { this->eos = 1; return 0; } - + } break; - + case 0x20: { lprintf ("new stream.\n"); @@ -968,7 +976,7 @@ static int get_media_packet (mms_t *this) { mms_buffer_t command_buffer; mms_buffer_init(&command_buffer, this->scmd_body); mms_buffer_put_32 (&command_buffer, 0x00000000); /* 64 byte float timestamp */ - mms_buffer_put_32 (&command_buffer, 0x00000000); + mms_buffer_put_32 (&command_buffer, 0x00000000); mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* ?? */ mms_buffer_put_32 (&command_buffer, 0xFFFFFFFF); /* first packet sequence */ mms_buffer_put_8 (&command_buffer, 0xFF); /* max stream time limit (3 bytes) */ @@ -995,10 +1003,10 @@ static int get_media_packet (mms_t *this) { } } break; - + case 0x05: break; - + default: xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "unexpected mms command %02x\n", command); @@ -1039,7 +1047,7 @@ static int get_media_packet (mms_t *this) { } break; } - + lprintf ("get media packet succ\n"); return 1; @@ -1077,13 +1085,13 @@ int mms_read (mms_t *this, char *data, int len) { this->asf_header_read += n; total += n; this->current_pos += n; - + if (this->asf_header_read == this->asf_header_len) break; } else { int n, bytes_left ; - + if (!this->playing) { /* send command 0x07 with initial timestamp */ mms_buffer_t command_buffer; diff --git a/src/input/mms.h b/src/input/mms.h index a483fa0c6..eaf9a46f4 100644 --- a/src/input/mms.h +++ b/src/input/mms.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2002-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/input/mmsh.c b/src/input/mmsh.c index ae1c62bc1..de2d6ebab 100644 --- a/src/input/mmsh.c +++ b/src/input/mmsh.c @@ -138,8 +138,8 @@ #endif -/* - * mmsh specific types +/* + * mmsh specific types */ @@ -161,10 +161,10 @@ struct mmsh_s { char str[SCRATCH_SIZE]; /* scratch buffer to built strings */ asf_header_t *asf_header; - int stream_type; + int stream_type; /* receive buffer */ - + /* chunk */ uint16_t chunk_type; uint16_t chunk_length; @@ -178,23 +178,21 @@ struct mmsh_s { uint32_t asf_header_len; uint32_t asf_header_read; int seq_num; - + int video_stream; int audio_stream; off_t current_pos; int user_bandwidth; - + int playing; unsigned int start_time; }; static int send_command (mmsh_t *this, char *cmd) { - int length; - lprintf ("send_command:\n%s\n", cmd); - length = strlen(cmd); + const size_t length = strlen(cmd); if (_x_io_tcp_write(this->stream, this->s, cmd, length) != length) { xprintf (this->stream->xine, XINE_LOG_MSG, _("libmmsh: send error\n")); return 0; @@ -203,7 +201,7 @@ static int send_command (mmsh_t *this, char *cmd) { } static int get_answer (mmsh_t *this) { - + int done, len, linenum; char *features; @@ -224,14 +222,14 @@ static int get_answer (mmsh_t *this) { this->buf[len] = '\0'; len--; - + if ((len >= 0) && (this->buf[len] == '\015')) { this->buf[len] = '\0'; len--; } linenum++; - + lprintf ("answer: >%s<\n", this->buf); if (linenum == 1) { @@ -265,7 +263,7 @@ static int get_answer (mmsh_t *this) { _("libmmsh: Location redirection not implemented\n")); return 0; } - + if (!strncasecmp((char*)this->buf, "Pragma:", 7)) { features = strstr((char*)(this->buf + 7), "features="); if (features) { @@ -281,7 +279,7 @@ static int get_answer (mmsh_t *this) { } } } - + if (len == -1) { done = 1; } else { @@ -316,7 +314,7 @@ static int get_chunk_header (mmsh_t *this) { } this->chunk_type = _X_LE_16 (&chunk_header[0]); this->chunk_length = _X_LE_16 (&chunk_header[2]); - + switch (this->chunk_type) { case CHUNK_TYPE_DATA: ext_header_len = 8; @@ -342,7 +340,7 @@ static int get_chunk_header (mmsh_t *this) { return 0; } } - + switch (this->chunk_type) { case CHUNK_TYPE_DATA: this->chunk_seq_number = _X_LE_32 (&ext_header[0]); @@ -386,7 +384,7 @@ static int get_header (mmsh_t *this) { lprintf("get_header\n"); this->asf_header_len = 0; - + /* read chunk */ while (1) { if (get_chunk_header(this)) { @@ -486,11 +484,11 @@ static void report_progress (xine_stream_t *stream, int p) { */ static int mmsh_tcp_connect(mmsh_t *this) { int progress, res; - + if (!this->port) this->port = MMSH_PORT; - - /* - * try to connect + + /* + * try to connect */ lprintf("try to connect to %s on port %d \n", this->host, this->port); @@ -524,24 +522,24 @@ static int mmsh_connect_int(mmsh_t *this, int bandwidth) { /* * let the negotiations begin... */ - + /* first request */ lprintf("first http request\n"); - + snprintf (this->str, SCRATCH_SIZE, mmsh_FirstRequest, this->uri, this->host, this->port, 1); if (!send_command (this, this->str)) return 0; - if (!get_answer (this)) + if (!get_answer (this)) return 0; get_header (this); /* FIXME: it returns 0 */ if (!interp_header (this)) return 0; - + close (this->s); report_progress (this->stream, 20); @@ -550,13 +548,13 @@ static int mmsh_connect_int(mmsh_t *this, int bandwidth) { lprintf("audio stream %d, video stream %d\n", this->audio_stream, this->video_stream); - + asf_header_disable_streams (this->asf_header, this->video_stream, this->audio_stream); - + if (mmsh_tcp_connect(this)) return 0; - + return 1; } @@ -567,7 +565,7 @@ static int mmsh_connect_int2(mmsh_t *this, int bandwidth) { int i; char stream_selection[10 * ASF_MAX_NUM_STREAMS]; /* 10 chars per stream */ int offset; - + /* second request */ lprintf("second http request\n"); @@ -608,7 +606,7 @@ static int mmsh_connect_int2(mmsh_t *this, int bandwidth) { if (!send_command (this, this->str)) return 0; - + lprintf("before read \n"); if (!get_answer (this)) @@ -616,11 +614,11 @@ static int mmsh_connect_int2(mmsh_t *this, int bandwidth) { if (!get_header (this)) return 0; - + #if 0 if (!interp_header (this)) return 0; - + asf_header_disable_streams (this->asf_header, this->video_stream, this->audio_stream); #endif @@ -630,13 +628,13 @@ static int mmsh_connect_int2(mmsh_t *this, int bandwidth) { mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) { mmsh_t *this; - + if (!url) return NULL; report_progress (stream, 0); - this = (mmsh_t*) xine_xmalloc (sizeof (mmsh_t)); + this = calloc(1, sizeof (mmsh_t)); this->stream = stream; this->url = strdup(url); @@ -649,28 +647,28 @@ mmsh_t *mmsh_connect (xine_stream_t *stream, const char *url, int bandwidth) { this->user_bandwidth = bandwidth; report_progress (stream, 0); - + if (!_x_parse_url (this->url, &this->proto, &this->host, &this->port, - &this->user, &this->password, &this->uri)) { + &this->user, &this->password, &this->uri, NULL)) { xine_log (this->stream->xine, XINE_LOG_MSG, _("invalid url\n")); goto fail; } - + if (!mmsh_valid_proto(this->proto)) { xine_log (this->stream->xine, XINE_LOG_MSG, _("unsupported protocol\n")); goto fail; } - + if (mmsh_tcp_connect(this)) goto fail; - + report_progress (stream, 30); if (!mmsh_connect_int(this, this->user_bandwidth)) goto fail; report_progress (stream, 100); - + lprintf("mmsh_connect: passed\n" ); return this; @@ -719,7 +717,7 @@ static int get_media_packet (mmsh_t *this) { */ if (this->chunk_seq_number == 0) return 0; - + close(this->s); if (mmsh_tcp_connect(this)) @@ -727,20 +725,20 @@ static int get_media_packet (mmsh_t *this) { if (!mmsh_connect_int(this, this->user_bandwidth)) return 0; - + this->playing = 0; /* mmsh_connect_int reads the first data packet */ - /* this->buf_size is set by mmsh_connect_int */ + /* this->buf_size is set by mmsh_connect_int */ return 2; case CHUNK_TYPE_DATA: /* nothing to do */ break; - + case CHUNK_TYPE_RESET: /* next chunk is an ASF header */ - + if (this->chunk_length != 0) { /* that's strange, don't know what to do */ return 0; @@ -749,7 +747,7 @@ static int get_media_packet (mmsh_t *this) { return 0; interp_header(this); return 2; - + default: xprintf (this->stream->xine, XINE_VERBOSITY_LOG, "libmmsh: unexpected chunk type\n"); @@ -757,7 +755,7 @@ static int get_media_packet (mmsh_t *this) { } len = _x_io_tcp_read (this->stream, this->s, (char*)this->buf, this->chunk_length); - + if (len == this->chunk_length) { /* explicit padding with 0 */ if (this->chunk_length > this->asf_header->file->packet_size) { @@ -814,13 +812,13 @@ int mmsh_read (mmsh_t *this, char *data, int len) { this->asf_header_read += n; total += n; this->current_pos += n; - + if (this->asf_header_read == this->asf_header_len) - break; + break; } else { int n, bytes_left ; - + if (!this->playing) { if (!mmsh_connect_int2 (this, this->user_bandwidth)) break; diff --git a/src/input/mmsh.h b/src/input/mmsh.h index 633d3b5f6..09b305adb 100644 --- a/src/input/mmsh.h +++ b/src/input/mmsh.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2002-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/input/net_buf_ctrl.c b/src/input/net_buf_ctrl.c index 624af4081..bd0e5ce13 100644 --- a/src/input/net_buf_ctrl.c +++ b/src/input/net_buf_ctrl.c @@ -118,9 +118,9 @@ void nbc_check_buffers (nbc_t *this) { } static void display_stats (nbc_t *this) { - const char *buffering[2] = {" ", "buf"}; - const char *enabled[2] = {"off", "on "}; - + const char buffering[2][4] = {" ", "buf"}; + const char enabled[2][4] = {"off", "on "}; + printf("bufing: %d, enb: %d\n", this->buffering, this->enabled); printf("net_buf_ctrl: vid %3d%% %4.1fs %4" PRId64 "kbps %1d, "\ "aud %3d%% %4.1fs %4" PRId64 "kbps %1d, %s %s\r", @@ -168,7 +168,7 @@ static void nbc_compute_fifo_length(nbc_t *this, this->video_fifo_free = fifo_free; this->video_fifo_fill = (100 * fifo_fill) / fifo_div; this->video_fifo_size = fifo->fifo_data_size; - + if (buf->pts && (this->video_in_disc == 0)) { if (action == FIFO_PUT) { this->video_last_pts = buf->pts; @@ -180,7 +180,7 @@ static void nbc_compute_fifo_length(nbc_t *this, this->video_first_pts = buf->pts; } } - + if (video_br) { this->video_br = video_br; this->video_fifo_length_int = (8000 * this->video_fifo_size) / this->video_br; @@ -201,7 +201,7 @@ static void nbc_compute_fifo_length(nbc_t *this, this->audio_fifo_free = fifo_free; this->audio_fifo_fill = (100 * fifo_fill) / fifo_div; this->audio_fifo_size = fifo->fifo_data_size; - + if (buf->pts && (this->audio_in_disc == 0)) { if (action == FIFO_PUT) { this->audio_last_pts = buf->pts; @@ -213,7 +213,7 @@ static void nbc_compute_fifo_length(nbc_t *this, this->audio_first_pts = buf->pts; } } - + if (audio_br) { this->audio_br = audio_br; this->audio_fifo_length_int = (8000 * this->audio_fifo_size) / this->audio_br; @@ -230,7 +230,7 @@ static void nbc_compute_fifo_length(nbc_t *this, } } } - + /* decoder buffer compensation */ if (has_audio && has_video) { diff = this->video_first_pts - this->audio_first_pts; @@ -271,7 +271,7 @@ static void nbc_alloc_cb (fifo_buffer_t *fifo, void *this_gen) { /* Put callback * the fifo mutex is locked */ -static void nbc_put_cb (fifo_buffer_t *fifo, +static void nbc_put_cb (fifo_buffer_t *fifo, buf_element_t *buf, void *this_gen) { nbc_t *this = (nbc_t*)this_gen; int64_t progress = 0; @@ -285,7 +285,7 @@ static void nbc_put_cb (fifo_buffer_t *fifo, if ((buf->type & BUF_MAJOR_MASK) != BUF_CONTROL_BASE) { if (this->enabled) { - + nbc_compute_fifo_length(this, fifo, buf, FIFO_PUT); if (this->buffering) { @@ -311,8 +311,8 @@ static void nbc_put_cb (fifo_buffer_t *fifo, xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_put_cb: stops buffering\n"); nbc_set_speed_normal(this); - - this->high_water_mark += this->high_water_mark / 2; + + this->high_water_mark += this->high_water_mark / 2; } else { /* compute the buffering progress @@ -439,7 +439,7 @@ static void nbc_get_cb (fifo_buffer_t *fifo, if (this->enabled) { nbc_compute_fifo_length(this, fifo, buf, FIFO_GET); - + if (!this->buffering) { /* start buffering if one fifo is empty */ @@ -454,7 +454,7 @@ static void nbc_get_cb (fifo_buffer_t *fifo, this->progress = 0; report_progress (this->stream, 0); - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "\nnet_buf_ctrl: nbc_get_cb: starts buffering, vid: %d, aud: %d\n", this->video_fifo_fill, this->audio_fifo_fill); nbc_set_speed_pause(this); @@ -495,8 +495,8 @@ static void nbc_get_cb (fifo_buffer_t *fifo, } nbc_t *nbc_init (xine_stream_t *stream) { - - nbc_t *this = (nbc_t *) xine_xmalloc (sizeof (nbc_t)); + + nbc_t *this = calloc(1, sizeof (nbc_t)); fifo_buffer_t *video_fifo = stream->video_fifo; fifo_buffer_t *audio_fifo = stream->audio_fifo; double video_fifo_factor, audio_fifo_factor; @@ -508,7 +508,7 @@ nbc_t *nbc_init (xine_stream_t *stream) { this->stream = stream; this->video_fifo = video_fifo; this->audio_fifo = audio_fifo; - + /* when the FIFO sizes are increased compared to the default configuration, * apply a factor to the high water mark */ entry = stream->xine->config->lookup_entry(stream->xine->config, "engine.buffers.video_num_buffers"); diff --git a/src/input/net_buf_ctrl.h b/src/input/net_buf_ctrl.h index 79f698008..6eac63e52 100644 --- a/src/input/net_buf_ctrl.h +++ b/src/input/net_buf_ctrl.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -27,14 +27,14 @@ typedef struct nbc_s nbc_t; -nbc_t *nbc_init (xine_stream_t *xine); +nbc_t *nbc_init (xine_stream_t *xine) XINE_MALLOC; -void nbc_check_buffers (nbc_t *this); +void nbc_check_buffers (nbc_t *this) XINE_DEPRECATED; void nbc_close (nbc_t *this); -void nbc_set_high_water_mark(nbc_t *this, int value); +void nbc_set_high_water_mark(nbc_t *this, int value) XINE_DEPRECATED; -void nbc_set_low_water_mark(nbc_t *this, int value); +void nbc_set_low_water_mark(nbc_t *this, int value) XINE_DEPRECATED; #endif diff --git a/src/input/pnm.c b/src/input/pnm.c index 38d65b850..bf24e5f8f 100644 --- a/src/input/pnm.c +++ b/src/input/pnm.c @@ -17,10 +17,14 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * pnm protocol implementation + * pnm protocol implementation * based upon code from joschka */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include <unistd.h> #include <stdio.h> #include <sys/socket.h> @@ -90,7 +94,7 @@ struct pnm_s { /* header of rm files */ #define RM_HEADER_SIZE 0x12 -const unsigned char rm_header[]={ +static const unsigned char rm_header[]={ 0x2e, 0x52, 0x4d, 0x46, /* object_id ".RMF" */ 0x00, 0x00, 0x00, 0x12, /* header_size 0x12 */ 0x00, 0x00, /* object_version 0x00 */ @@ -100,7 +104,7 @@ const unsigned char rm_header[]={ /* data chunk header */ #define PNM_DATA_HEADER_SIZE 18 -const unsigned char pnm_data_header[]={ +static const unsigned char pnm_data_header[]={ 'D','A','T','A', 0,0,0,0, /* data chunk size */ 0,0, /* object version */ @@ -140,26 +144,26 @@ static const unsigned char pnm_header[] = { #define PNM_CLIENT_CAPS_SIZE 126 static const unsigned char pnm_client_caps[] = { - 0x07, 0x8a, 'p','n','r','v', - 0, 0x90, 'p','n','r','v', - 0, 0x64, 'd','n','e','t', - 0, 0x46, 'p','n','r','v', - 0, 0x32, 'd','n','e','t', - 0, 0x2b, 'p','n','r','v', - 0, 0x28, 'd','n','e','t', - 0, 0x24, 'p','n','r','v', - 0, 0x19, 'd','n','e','t', - 0, 0x18, 'p','n','r','v', - 0, 0x14, 's','i','p','r', - 0, 0x14, 'd','n','e','t', - 0, 0x24, '2','8','_','8', - 0, 0x12, 'p','n','r','v', - 0, 0x0f, 'd','n','e','t', - 0, 0x0a, 's','i','p','r', - 0, 0x0a, 'd','n','e','t', - 0, 0x08, 's','i','p','r', - 0, 0x06, 's','i','p','r', - 0, 0x12, 'l','p','c','J', + 0x07, 0x8a, 'p','n','r','v', + 0, 0x90, 'p','n','r','v', + 0, 0x64, 'd','n','e','t', + 0, 0x46, 'p','n','r','v', + 0, 0x32, 'd','n','e','t', + 0, 0x2b, 'p','n','r','v', + 0, 0x28, 'd','n','e','t', + 0, 0x24, 'p','n','r','v', + 0, 0x19, 'd','n','e','t', + 0, 0x18, 'p','n','r','v', + 0, 0x14, 's','i','p','r', + 0, 0x14, 'd','n','e','t', + 0, 0x24, '2','8','_','8', + 0, 0x12, 'p','n','r','v', + 0, 0x0f, 'd','n','e','t', + 0, 0x0a, 's','i','p','r', + 0, 0x0a, 'd','n','e','t', + 0, 0x08, 's','i','p','r', + 0, 0x06, 's','i','p','r', + 0, 0x12, 'l','p','c','J', 0, 0x07, '0','5','_','6' }; static const uint32_t pnm_default_bandwidth=10485800; @@ -175,7 +179,7 @@ static const unsigned char pnm_twentyfour[]={ static const int after_chunks_length=6; static const unsigned char after_chunks[]={ 0x00, 0x00, /* mark */ - + 0x50, 0x84, /* seems to be fixated */ 0x1f, 0x3a /* varies on each request (checksum ?)*/ }; @@ -197,7 +201,7 @@ static const unsigned char after_chunks[]={ * if we have an PNA_TAG, we need a different parsing; see below. */ -static unsigned int pnm_get_chunk(pnm_t *p, +static unsigned int pnm_get_chunk(pnm_t *p, unsigned int max, unsigned int *chunk_type, char *data, int *need_response) { @@ -208,7 +212,7 @@ static unsigned int pnm_get_chunk(pnm_t *p, if( max < PREAMBLE_SIZE ) return -1; - + /* get first PREAMBLE_SIZE bytes and ignore checksum */ _x_io_tcp_read (p->stream, p->s, data, CHECKSUM_SIZE); if (data[0] == 0x72) @@ -217,7 +221,7 @@ static unsigned int pnm_get_chunk(pnm_t *p, _x_io_tcp_read (p->stream, p->s, data+CHECKSUM_SIZE, PREAMBLE_SIZE-CHECKSUM_SIZE); max -= PREAMBLE_SIZE; - + *chunk_type = be2me_32(*((uint32_t *)data)); chunk_size = be2me_32(*((uint32_t *)(data+4))); @@ -233,10 +237,10 @@ static unsigned int pnm_get_chunk(pnm_t *p, while(1) { /* The pna chunk is devided into subchunks. - * expecting following chunk format (in big endian): - * 0x4f - * uint8_t chunk_size - * uint8_t data[chunk_size] + * expecting following chunk format (in big endian): + * 0x4f + * uint8_t chunk_size + * uint8_t data[chunk_size] * * if first byte is 'X', we got a message from server * if first byte is 'F', we got an error @@ -246,7 +250,7 @@ static unsigned int pnm_get_chunk(pnm_t *p, return -1; _x_io_tcp_read (p->stream, p->s, ptr, 2); max -= 2; - + if (*ptr == 'X') /* checking for server message */ { xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, "input_pnm: got a message from server:\n"); @@ -269,7 +273,7 @@ static unsigned int pnm_get_chunk(pnm_t *p, xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, "%s\n", ptr+3); return -1; } - + if (*ptr == 'F') /* checking for server error */ { /* some error codes after 'F' were ignored */ @@ -315,7 +319,7 @@ static unsigned int pnm_get_chunk(pnm_t *p, break; default: *chunk_type = 0; - chunk_size = PREAMBLE_SIZE; + chunk_size = PREAMBLE_SIZE; break; } @@ -330,7 +334,7 @@ static unsigned int pnm_get_chunk(pnm_t *p, * uint8_t data[length] */ -static int pnm_write_chunk(uint16_t chunk_id, uint16_t length, +static int pnm_write_chunk(uint16_t chunk_id, uint16_t length, const char *chunk, char *data) { uint16_t be_id, be_len; @@ -341,7 +345,7 @@ static int pnm_write_chunk(uint16_t chunk_id, uint16_t length, memcpy(data , &be_id , 2); memcpy(data+2, &be_len, 2); memcpy(data+4, chunk , length); - + return length+4; } @@ -379,7 +383,7 @@ static void pnm_send_request(pnm_t *p, uint32_t bandwidth) { pnm_guid,&p->buffer[c]); c+=pnm_write_chunk(PNA_TWENTYFOUR,PNM_TWENTYFOUR_SIZE, (char*)pnm_twentyfour,&p->buffer[c]); - + /* data after chunks */ memcpy(&p->buffer[c],after_chunks,after_chunks_length); c+=after_chunks_length; @@ -402,7 +406,7 @@ static void pnm_send_request(pnm_t *p, uint32_t bandwidth) { /* some trailing bytes */ p->buffer[c]='y'; p->buffer[c+1]='B'; - + _x_io_tcp_write(p->stream,p->s,p->buffer,c+2); } @@ -411,8 +415,8 @@ static void pnm_send_request(pnm_t *p, uint32_t bandwidth) { */ static void pnm_send_response(pnm_t *p, const char *response) { - - int size=strlen(response); + /** @TODO should check that sze is always < 256 */ + size_t size=strlen(response); p->buffer[0]=0x23; p->buffer[1]=0; @@ -472,7 +476,7 @@ static int pnm_get_headers(pnm_t *p, int *need_response) { xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, "input_pnm: error while parsing headers.\n"); return 0; } - + /* set data offset */ { uint32_t be_size; @@ -480,7 +484,7 @@ static int pnm_get_headers(pnm_t *p, int *need_response) { be_size = be2me_32(size-1); memcpy(prop_hdr+42, &be_size, 4); } - + /* read challenge */ memcpy (p->buffer, ptr, PREAMBLE_SIZE); _x_io_tcp_read (p->stream, p->s, &p->buffer[PREAMBLE_SIZE], 64); @@ -488,18 +492,18 @@ static int pnm_get_headers(pnm_t *p, int *need_response) { /* now write a data header */ memcpy(ptr, pnm_data_header, PNM_DATA_HEADER_SIZE); size+=PNM_DATA_HEADER_SIZE; -/* +/* h=rmff_scan_header(p->header); rmff_fix_header(h); p->header_len=rmff_get_header_size(h); rmff_dump_header(h, p->header, HEADER_SIZE); */ p->header_len=size; - + return 1; } -/* +/* * determine correct stream number by looking at indices * FIXME: this doesn't work with all streams! There must be * another way to determine correct stream numbers! @@ -565,7 +569,7 @@ static int pnm_calc_stream(pnm_t *p) { return 0; break; } - xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, "input_pnm: wow, something very nasty happened in pnm_calc_stream\n"); return 2; } @@ -582,7 +586,7 @@ static int pnm_get_stream_chunk(pnm_t *p) { /* send a keepalive */ /* realplayer seems to do that every 43th package */ - if ((p->packet%43) == 42) + if ((p->packet%43) == 42) { _x_io_tcp_write(p->stream,p->s,&keepalive,1); } @@ -592,10 +596,10 @@ static int pnm_get_stream_chunk(pnm_t *p) { * <i1> is a 16 bit index (big endian) * <i2> is a 8 bit index which counts from 0x10 to somewhere */ - + n = _x_io_tcp_read (p->stream, p->s, p->buffer, 8); if (n<8) return 0; - + /* skip 8 bytes if 0x62 is read */ if (p->buffer[0] == 0x62) { @@ -603,7 +607,7 @@ static int pnm_get_stream_chunk(pnm_t *p) { if (n<8) return 0; lprintf("had to seek 8 bytes on 0x62\n"); } - + /* a server message */ if (p->buffer[0] == 'X') { @@ -611,7 +615,7 @@ static int pnm_get_stream_chunk(pnm_t *p) { _x_io_tcp_read (p->stream, p->s, &p->buffer[8], size-5); p->buffer[size+3]=0; - xprintf(p->stream->xine, XINE_VERBOSITY_LOG, + xprintf(p->stream->xine, XINE_VERBOSITY_LOG, _("input_pnm: got message from server while reading stream:\n%s\n"), &p->buffer[3]); return 0; } @@ -627,10 +631,7 @@ static int pnm_get_stream_chunk(pnm_t *p) { */ n=0; while (p->buffer[0] != 0x5a) { - int i; - for (i=1; i<8; i++) { - p->buffer[i-1]=p->buffer[i]; - } + memmove(p->buffer, &p->buffer[1], 8); _x_io_tcp_read (p->stream, p->s, &p->buffer[7], 1); n++; } @@ -654,14 +655,14 @@ static int pnm_get_stream_chunk(pnm_t *p) { fof2=be2me_16(*(uint16_t*)(&p->buffer[3])); if (fof1 != fof2) { - xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(p->stream->xine, XINE_VERBOSITY_DEBUG, "input_pnm: frame offsets are different: 0x%04x 0x%04x\n", fof1, fof2); return 0; } /* get first index */ p->seq_current[0]=be2me_16(*(uint16_t*)(&p->buffer[5])); - + /* now read the rest of stream chunk */ n = _x_io_tcp_read (p->stream, p->s, (char*)&p->recv[5], fof1-5); if (n<(fof1-5)) return 0; @@ -671,15 +672,15 @@ static int pnm_get_stream_chunk(pnm_t *p) { /* get timestamp */ p->ts_current=be2me_32(*(uint32_t*)(&p->recv[6])); - + /* get stream number */ stream=pnm_calc_stream(p); /* saving timestamp */ p->ts_last[stream]=p->ts_current; - + /* constructing a data packet header */ - + p->recv[0]=0; /* object version */ p->recv[1]=0; @@ -690,7 +691,7 @@ static int pnm_get_stream_chunk(pnm_t *p) { p->recv[4]=0; /* stream number */ p->recv[5]=stream; - + p->recv[10]=p->recv[10] & 0xfe; /* streambox seems to do that... */ p->packet++; @@ -701,22 +702,22 @@ static int pnm_get_stream_chunk(pnm_t *p) { } pnm_t *pnm_connect(xine_stream_t *stream, const char *mrl) { - + char *mrl_ptr=strdup(mrl); char *slash, *colon; size_t pathbegin, hostend; pnm_t *p; int fd; int need_response=0; - + if (strncmp(mrl,"pnm://",6)) { return NULL; } - + mrl_ptr+=6; - p = xine_xmalloc(sizeof(pnm_t)); + p = calloc(1, sizeof(pnm_t)); p->stream = stream; p->port=7070; p->url=strdup(mrl); @@ -726,15 +727,13 @@ pnm_t *pnm_connect(xine_stream_t *stream, const char *mrl) { colon=strchr(mrl_ptr,':'); if(!slash) slash=mrl_ptr+strlen(mrl_ptr)+1; - if(!colon) colon=slash; + if(!colon) colon=slash; if(colon > slash) colon=slash; pathbegin=slash-mrl_ptr; hostend=colon-mrl_ptr; - p->host = malloc(sizeof(char)*hostend+1); - strncpy(p->host, mrl_ptr, hostend); - p->host[hostend]=0; + p->host = strndup(mrl_ptr, hostend); if (pathbegin < strlen(mrl_ptr)) p->path=strdup(mrl_ptr+pathbegin+1); if (colon != slash) { @@ -746,7 +745,7 @@ pnm_t *pnm_connect(xine_stream_t *stream, const char *mrl) { free(mrl_ptr-6); lprintf("got mrl: %s %i %s\n",p->host,p->port,p->path); - + fd = _x_io_tcp_connect (stream, p->host, p->port); if (fd == -1) { @@ -772,7 +771,7 @@ pnm_t *pnm_connect(xine_stream_t *stream, const char *mrl) { pnm_send_response(p, pnm_response); p->ts_last[0]=0; p->ts_last[1]=0; - + /* copy header to recv */ memcpy(p->recv, p->header, p->header_len); @@ -783,15 +782,15 @@ pnm_t *pnm_connect(xine_stream_t *stream, const char *mrl) { } int pnm_read (pnm_t *this, char *data, int len) { - + int to_copy=len; char *dest=data; char *source=(char*)(this->recv + this->recv_read); int fill=this->recv_size - this->recv_read; - + if (len < 0) return 0; while (to_copy > fill) { - + memcpy(dest, source, fill); to_copy -= fill; dest += fill; diff --git a/src/input/pnm.h b/src/input/pnm.h index 838fbadcc..df1f47290 100644 --- a/src/input/pnm.h +++ b/src/input/pnm.h @@ -19,7 +19,7 @@ * * pnm util functions header by joschka */ - + #ifndef HAVE_PNM_H #define HAVE_PNM_H diff --git a/src/input/sha1.c b/src/input/sha1.c index b70e50d5f..c30825a19 100644 --- a/src/input/sha1.c +++ b/src/input/sha1.c @@ -1,14 +1,14 @@ /* (PD) 2001 The Bitzi Corporation - * Please see file COPYING or http://bitzi.com/publicdomain + * Please see file COPYING or http://bitzi.com/publicdomain * for more info. * - * NIST Secure Hash Algorithm - * heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> - * from Peter C. Gutmann's implementation as found in - * Applied Cryptography by Bruce Schneier - * Further modifications to include the "UNRAVEL" stuff, below + * NIST Secure Hash Algorithm + * heavily modified by Uwe Hollerbach <uh@alumni.caltech edu> + * from Peter C. Gutmann's implementation as found in + * Applied Cryptography by Bruce Schneier + * Further modifications to include the "UNRAVEL" stuff, below * - * This code is in the public domain + * This code is in the public domain */ #include <string.h> diff --git a/src/input/sha1.h b/src/input/sha1.h index 9f2659d60..a81af673b 100644 --- a/src/input/sha1.h +++ b/src/input/sha1.h @@ -34,7 +34,7 @@ char *sha_version(void); #define SHA_VERSION 1 -#ifdef HAVE_CONFIG_H +#ifdef HAVE_CONFIG_H #include "config.h" #ifdef WORDS_BIGENDIAN diff --git a/src/input/vcd/Makefile.am b/src/input/vcd/Makefile.am index 31ec6a44c..61eac753b 100644 --- a/src/input/vcd/Makefile.am +++ b/src/input/vcd/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = libcdio libvcd diff --git a/src/input/vcd/libcdio/FreeBSD/freebsd.c b/src/input/vcd/libcdio/FreeBSD/freebsd.c index 5a3443e95..bcfe674a5 100644 --- a/src/input/vcd/libcdio/FreeBSD/freebsd.c +++ b/src/input/vcd/libcdio/FreeBSD/freebsd.c @@ -29,11 +29,11 @@ static const char _rcsid[] = "$Id: freebsd.c,v 1.1 2005/01/01 02:43:57 rockyb Exp $"; -#include <arpa/inet.h> #include "freebsd.h" #ifdef HAVE_FREEBSD_CDROM +#include <arpa/inet.h> #include <cdio/sector.h> static access_mode_t diff --git a/src/input/vcd/libcdio/MSWindows/aspi32.c b/src/input/vcd/libcdio/MSWindows/aspi32.c index 238a4b4e9..e62f8a089 100644 --- a/src/input/vcd/libcdio/MSWindows/aspi32.c +++ b/src/input/vcd/libcdio/MSWindows/aspi32.c @@ -162,9 +162,9 @@ have_aspi( HMODULE *hASPI, return false; } - (FARPROC) *lpGetSupport = GetProcAddress( *hASPI, + *lpGetSupport = (FARPROC)GetProcAddress( *hASPI, "GetASPI32SupportInfo" ); - (FARPROC) *lpSendCommand = GetProcAddress( *hASPI, + *lpSendCommand = (FARPROC)GetProcAddress( *hASPI, "SendASPI32Command" ); /* make sure that we've got both function addresses */ diff --git a/src/input/vcd/libcdio/cdio/Makefile.am b/src/input/vcd/libcdio/cdio/Makefile.am index 0910d60e5..4f0d53cc8 100644 --- a/src/input/vcd/libcdio/cdio/Makefile.am +++ b/src/input/vcd/libcdio/cdio/Makefile.am @@ -16,4 +16,4 @@ noinst_HEADERS = \ types.h \ util.h \ version.h \ - xa.h + xa.h diff --git a/src/input/vcd/libvcd/Makefile.am b/src/input/vcd/libvcd/Makefile.am index 01b100aa4..fddbb390f 100644 --- a/src/input/vcd/libvcd/Makefile.am +++ b/src/input/vcd/libvcd/Makefile.am @@ -21,7 +21,7 @@ libvcd_SRCS = \ sector.c \ stream.c \ stream_stdio.c \ - util.c + util.c libvcdinfo_SRCS = \ info.c \ diff --git a/src/input/vcd/xine-extra.c b/src/input/vcd/xine-extra.c index 79c962a79..d211f46a4 100644 --- a/src/input/vcd/xine-extra.c +++ b/src/input/vcd/xine-extra.c @@ -1,23 +1,23 @@ -/* - +/* + Copyright (C) 2002 Rocky Bernstein <rocky@panix.com> - + Program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - + These are routines that probably should be in xine, but for whatever - reason aren't - yet. + reason aren't - yet. */ #ifdef HAVE_CONFIG_H @@ -42,11 +42,13 @@ static xine_t *my_xine = NULL; In short this writes a message to buffer 'buf' and to stdout. */ -void +void xine_vlog_msg(xine_t *this, int buf, const char *format, va_list args) { + va_list copy; + va_copy (copy, args); xine_vlog(this, buf, format, args); - vfprintf(stdout, format, args); + vfprintf(stdout, format, copy); } /*! This routine is like xine_log, except it takes a va_list instead @@ -56,16 +58,18 @@ xine_vlog_msg(xine_t *this, int buf, const char *format, va_list args) In short this writes a message to buffer 'buf' and to stderr. */ -void +void xine_vlog_err(xine_t *this, int buf, const char *format, va_list args) { + va_list copy; + va_copy (copy, args); xine_vlog(this, buf, format, args); - vfprintf(stderr, format, args); + vfprintf(stderr, format, copy); } /*! Call this before calling any of the xine_log_msg or xine_log_err routines. It sets up the xine buffer that will be used in error - logging. + logging. \return true if everything went okay; false is returned if logging was already initialized, in which case nothing is done. @@ -81,12 +85,12 @@ xine_log_init(xine_t *this) /*! This routine is like xine_log without any xine-specific paramenters. Before calling this routine you should have set up a xine log buffer via - xine_log_init(). + xine_log_init(). In short this writes a message to buffer 'buf' and to stdout. - \return true if everything went okay; false is there was - an error, such as logging wasn't initialized. On error, nothing is + \return true if everything went okay; false is there was + an error, such as logging wasn't initialized. On error, nothing is logged. */ bool @@ -103,12 +107,12 @@ xine_log_msg(const char *format, ...) /*! This routine is like xine_log without any xine-specific paramenters. Before calling this routine you should have set up a xine log buffer via - xine_log_init(). + xine_log_init(). In short this writes a message to buffer 'buf' and to stdout. - \return true if everything went okay; false is there was - an error, such as logging wasn't initialized. On error, nothing is + \return true if everything went okay; false is there was + an error, such as logging wasn't initialized. On error, nothing is logged. */ bool @@ -116,15 +120,15 @@ xine_log_err(const char *format, ...) { va_list args; - va_start(args, format); if (NULL == my_xine) return false; + va_start(args, format); xine_vlog_err(my_xine, XINE_LOG_MSG, format, args); va_end(args); return true; } void -xine_free_mrls(int *num_mrls, xine_mrl_t **mrls) +xine_free_mrls(int *num_mrls, xine_mrl_t **mrls) { (*num_mrls)--; for ( ; *num_mrls >= 0; (*num_mrls)-- ) { diff --git a/src/input/vcd/xine-extra.h b/src/input/vcd/xine-extra.h index 0650f863d..8acf1f291 100644 --- a/src/input/vcd/xine-extra.h +++ b/src/input/vcd/xine-extra.h @@ -1,23 +1,23 @@ -/* - +/* + Copyright (C) 2002 Rocky Bernstein <rocky@panix.com> - + Program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - + These are routines that probably should be in xine, but for whatever - reason aren't - yet. + reason aren't - yet. */ #ifndef XINE_EXTRA_H @@ -47,7 +47,7 @@ In short this writes a message to buffer 'buf' and to stdout. */ -void +void xine_vlog_msg(xine_t *this, int buf, const char *format, va_list args) XINE_FORMAT_PRINTF(3, 0); /*! This routine is like xine_log, except it takes a va_list instead @@ -61,7 +61,7 @@ void xine_vlog_err(xine_t *this, int buf, const char *format, va_list args) XINE /*! Call this before calling any of the xine_log_msg or xine_log_err routines. It sets up the xine buffer that will be used in error - logging. + logging. \return true if everything went okay; false is returned if logging was already initialized, in which case nothing is done. @@ -71,24 +71,24 @@ bool xine_log_init(xine_t *this); /*! This routine is like xine_log without any xine-specific paramenters. Before calling this routine you should have set up a xine log buffer via - xine_log_init(). + xine_log_init(). In short this writes a message to buffer 'buf' and to stdout. - \return true if everything went okay; false is there was - an error, such as logging wasn't initialized. On error, nothing is + \return true if everything went okay; false is there was + an error, such as logging wasn't initialized. On error, nothing is logged. */ bool xine_log_msg(const char *format, ...) XINE_FORMAT_PRINTF(1, 2); /*! This routine is like xine_log without any xine-specific paramenters. Before calling this routine you should have set up a xine log buffer via - xine_log_init(). + xine_log_init(). In short this writes a message to buffer 'buf' and to stdout. - \return true if everything went okay; false is there was - an error, such as logging wasn't initialized. On error, nothing is + \return true if everything went okay; false is there was + an error, such as logging wasn't initialized. On error, nothing is logged. */ bool xine_log_err(const char *format, ...) XINE_FORMAT_PRINTF(1, 2); diff --git a/src/input/vcd/xineplug_inp_vcd.c b/src/input/vcd/xineplug_inp_vcd.c index 2e52ccc0f..e238460db 100644 --- a/src/input/vcd/xineplug_inp_vcd.c +++ b/src/input/vcd/xineplug_inp_vcd.c @@ -1,26 +1,26 @@ /* - + Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein <rocky@panix.com> - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ -/* +/* These are plugin routines called by the xine engine. See Chapter 4. Extending xine's input - http://xinehq.de/index.php/hackersguide/index.php?resource=5.3&action=default#INPUT + http://www.xine-project.org/hackersguide#INPUT and the comments in input_plugin.h This is what is referred to below a "the xine plugin spec" @@ -83,8 +83,8 @@ #define BUF_DEMUX_BLOCK 0x05000000 #endif -/* - Convert an autoplay enumeration into an vcdinfo itemtype enumeration. +/* + Convert an autoplay enumeration into an vcdinfo itemtype enumeration. See definitions in vcdplayer.h and vcdinfo.h to get the below correct. */ static const vcdinfo_item_enum_t autoplay2itemtype[]={ @@ -94,7 +94,7 @@ static const vcdinfo_item_enum_t autoplay2itemtype[]={ VCDINFO_ITEM_TYPE_LID /* VCDPLAYER_AUTOPLAY_PBC */ }; -typedef struct vcd_config_s +typedef struct vcd_config_s { char *title_format; /* Format string of GUI display title */ char *comment_format; /* Format string of stream comment meta */ @@ -106,7 +106,7 @@ typedef struct vcd_input_class_s { input_class_t input_class; xine_t *xine; config_values_t *config; /* Pointer to XineRC config file. */ - vcd_input_plugin_t *ip; + vcd_input_plugin_t *ip; vcd_config_t v_config; /* config stuff passed to child */ xine_mrl_t **mrls; /* list of mrl entries for medium */ @@ -114,10 +114,10 @@ typedef struct vcd_input_class_s { char *vcd_device;/* Device name to use when none specified in MRL */ /*-------------------------------------------------------------- - Media resource locator (MRL) info. + Media resource locator (MRL) info. For the below offsets, use play_item + mrl_xxx_offset to get index - into "mrls" array + into "mrls" array ---------------------------------------------------------------*/ int mrl_track_offset; /* perhaps -1 for tracks staring with 1*/ int mrl_entry_offset; /* i_tracks for entries starting with 0 */ @@ -130,10 +130,10 @@ typedef struct vcd_input_class_s { vcd_input_class_t *vcd_class; struct vcd_input_plugin_tag { - input_plugin_t input_plugin; /* input plugin interface as defined by - by player. For xine it contains a + input_plugin_t input_plugin; /* input plugin interface as defined by + by player. For xine it contains a structure of functions that need - to be implemented. + to be implemented. */ xine_stream_t *stream; xine_event_queue_t *event_queue; @@ -155,7 +155,7 @@ struct vcd_input_plugin_tag { the mouse is not in any "button" region then this has value -1. */ - bool b_mouse_in; /* True if mouse is inside a "button" + bool b_mouse_in; /* True if mouse is inside a "button" region; false otherwise */ vcdplayer_t player ; @@ -168,13 +168,13 @@ vcd_input_plugin_t my_vcd; static bool vcd_handle_events (void); static void vcd_close(vcd_input_class_t *class); #if LIBVCD_VERSION_NUM >= 23 -static void send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, +static void send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, bool b_mouse_in); #endif -/* - If class->vcd_device is NULL or the empty string, - Use libcdio to find a CD drive with a VCD in it. +/* + If class->vcd_device is NULL or the empty string, + Use libcdio to find a CD drive with a VCD in it. */ static bool vcd_get_default_device(vcd_input_class_t *class, bool log_msg_if_fail) @@ -184,7 +184,7 @@ vcd_get_default_device(vcd_input_class_t *class, bool log_msg_if_fail) if (NULL == class->vcd_device || strlen(class->vcd_device)==0) { char **cd_drives=NULL; - cd_drives = cdio_get_devices_with_cap(NULL, + cd_drives = cdio_get_devices_with_cap(NULL, (CDIO_FS_ANAL_SVCD|CDIO_FS_ANAL_CVD|CDIO_FS_ANAL_VIDEOCD|CDIO_FS_UNKNOWN), true); if (NULL == cd_drives || NULL == cd_drives[0]) { @@ -201,8 +201,8 @@ vcd_get_default_device(vcd_input_class_t *class, bool log_msg_if_fail) } -static void -meta_info_assign(int field, xine_stream_t *stream, const char * info) +static void +meta_info_assign(int field, xine_stream_t *stream, const char * info) { if (NULL != info) { dbg_print(INPUT_DBG_META, "meta[%d]: %s\n", field, info); @@ -215,10 +215,10 @@ meta_info_assign(int field, xine_stream_t *stream, const char * info) /* Set stream information. */ static void -vcd_set_meta_info (vcd_input_plugin_t *xine_vcd) +vcd_set_meta_info (vcd_input_plugin_t *xine_vcd) { vcdinfo_obj_t *p_vcdinfo= xine_vcd->player.vcd; - meta_info_assign(XINE_META_INFO_ALBUM, xine_vcd->stream, + meta_info_assign(XINE_META_INFO_ALBUM, xine_vcd->stream, vcdinfo_get_album_id(p_vcdinfo)); meta_info_assign(XINE_META_INFO_ARTIST, xine_vcd->stream, vcdinfo_get_preparer_id(p_vcdinfo)); @@ -230,40 +230,40 @@ vcd_set_meta_info (vcd_input_plugin_t *xine_vcd) } static void -vcd_force_redisplay (void) +vcd_force_redisplay (void) { #if 1 my_vcd.stream->xine->clock->adjust_clock(my_vcd.stream->xine->clock, - my_vcd.stream->xine->clock->get_current_time(my_vcd.stream->xine->clock) + my_vcd.stream->xine->clock->get_current_time(my_vcd.stream->xine->clock) + 30 * 90000 ); #else /* Alternate method that causes too much disruption... */ - xine_set_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO, + xine_set_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO, (xine_get_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO))); #endif } static void -vcd_set_aspect_ratio (int i_aspect_ratio) +vcd_set_aspect_ratio (int i_aspect_ratio) { /* Alternate method that causes too much disruption... */ xine_set_param(my_vcd.stream, XINE_PARAM_VO_ASPECT_RATIO, i_aspect_ratio); } -/*! Add another MRL to the MRL list inside "this" to be displayed. - mrl is the string name to add; size is the size of the entry in bytes. - The number of mrls in "this" is incremented. +/*! Add another MRL to the MRL list inside "this" to be displayed. + mrl is the string name to add; size is the size of the entry in bytes. + The number of mrls in "this" is incremented. */ static void -vcd_add_mrl_slot(vcd_input_class_t *this, const char *mrl, off_t size, +vcd_add_mrl_slot(vcd_input_class_t *this, const char *mrl, off_t size, unsigned int *i) { - dbg_print(INPUT_DBG_MRL, "called to add slot %d: %s, size %u\n", + dbg_print(INPUT_DBG_MRL, "called to add slot %d: %s, size %u\n", *i, mrl, (unsigned int) size); - + this->mrls[*i] = malloc(sizeof(xine_mrl_t)); if (NULL==this->mrls[*i]) { - LOG_ERR("Can't malloc %zu bytes for MRL slot %u (%s)", + LOG_ERR("Can't malloc %zu bytes for MRL slot %u (%s)", sizeof(xine_mrl_t), *i, mrl); return; } @@ -271,12 +271,10 @@ vcd_add_mrl_slot(vcd_input_class_t *this, const char *mrl, off_t size, this->mrls[*i]->origin = NULL; this->mrls[*i]->type = mrl_vcd; this->mrls[*i]->size = size * M2F2_SECTOR_SIZE; - - this->mrls[*i]->mrl = (char *) malloc(strlen(mrl) + 1); + + this->mrls[*i]->mrl = strdup(mrl); if (NULL==this->mrls[*i]->mrl) { LOG_ERR("Can't malloc %zu bytes for MRL name %s", sizeof(xine_mrl_t), mrl); - } else { - sprintf(this->mrls[*i]->mrl, "%s", mrl); } (*i)++; } @@ -284,9 +282,9 @@ vcd_add_mrl_slot(vcd_input_class_t *this, const char *mrl, off_t size, /*! Return the associated mrl_offset for the given type. */ -static int -vcd_get_mrl_type_offset(vcd_input_plugin_t *inp, - vcdinfo_item_enum_t type, int *size) +static int +vcd_get_mrl_type_offset(vcd_input_plugin_t *inp, + vcdinfo_item_enum_t type, int *size) { switch (type) { case VCDINFO_ITEM_TYPE_ENTRY: @@ -299,7 +297,7 @@ vcd_get_mrl_type_offset(vcd_input_plugin_t *inp, case VCDINFO_ITEM_TYPE_TRACK: *size = inp->class->mrl_entry_offset; return inp->class->mrl_track_offset; - case VCDINFO_ITEM_TYPE_LID: + case VCDINFO_ITEM_TYPE_LID: /* Play list number (LID) */ *size = (inp->player.i_lids > 0) ? 1 : 0; return inp->class->mrl_play_offset; @@ -340,10 +338,10 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) if (!vcd_get_default_device(class, true)) return false; vcd_device = class->vcd_device; } - + if (!vcdio_open(vcdplayer, vcd_device)) { /* Error should have been logged in vcdio_open. If not do the below: - LOG_ERR(vcdplayer, "%s: %s.\n", _("unable to open"), + LOG_ERR(vcdplayer, "%s: %s.\n", _("unable to open"), class->vcd_device, strerror(errno)); */ return false; @@ -361,13 +359,13 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) didn't have to possibly remove rejected LIDs from list done in the loop below. */ - class->num_mrls = vcdplayer->i_tracks + vcdplayer->i_entries + class->num_mrls = vcdplayer->i_tracks + vcdplayer->i_entries + vcdplayer->i_segments + vcdplayer->i_lids; if (!vcdplayer->show_rejected && vcdinfo_get_lot(vcdplayer->vcd)) { /* Remove rejected LIDs from count. */ for (n=0; n<vcdplayer->i_lids; n++) { - if ( vcdinf_get_lot_offset(vcdinfo_get_lot(vcdplayer->vcd), n) + if ( vcdinf_get_lot_offset(vcdinfo_get_lot(vcdplayer->vcd), n) == PSD_OFS_DISABLED ) class->num_mrls--; } @@ -383,24 +381,24 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) } /* Record MRL's for tracks */ - for (n=1; n<=vcdplayer->i_tracks; n++) { + for (n=1; n<=vcdplayer->i_tracks; n++) { memset(&mrl, 0, sizeof (mrl)); snprintf(mrl, sizeof(mrl), "%s%s@T%u", MRL_PREFIX, vcd_device, n); vcd_add_mrl_slot(class, mrl, vcdplayer->track[n-1].size, &i); } - + class->mrl_entry_offset = vcdplayer->i_tracks; class->mrl_play_offset = class->mrl_entry_offset + i_entries - 1; /* Record MRL's for entries */ if (i_entries > 0) { - for (n=0; n<i_entries; n++) { + for (n=0; n<i_entries; n++) { memset(&mrl, 0, sizeof (mrl)); snprintf(mrl, sizeof(mrl), "%s%s@E%u", MRL_PREFIX, vcd_device, n); vcd_add_mrl_slot(class, mrl, vcdplayer->entry[n].size, &i); } } - + /* Record MRL's for LID entries or selection entries*/ class->mrl_segment_offset = class->mrl_play_offset; if (vcdinfo_get_lot(vcdplayer->vcd)) { @@ -408,7 +406,7 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) uint16_t ofs = vcdinf_get_lot_offset(vcdinfo_get_lot(vcdplayer->vcd), n); if (ofs != PSD_OFS_DISABLED || vcdplayer->show_rejected) { memset(&mrl, 0, sizeof (mrl)); - snprintf(mrl, sizeof(mrl), "%s%s@P%u%s", MRL_PREFIX, vcd_device, n+1, + snprintf(mrl, sizeof(mrl), "%s%s@P%u%s", MRL_PREFIX, vcd_device, n+1, ofs == PSD_OFS_DISABLED ? "*" : ""); vcd_add_mrl_slot(class, mrl, 0, &i); class->mrl_segment_offset++; @@ -420,7 +418,7 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) { segnum_t i_segments = vcdplayer->i_segments; for (n=0; n<i_segments; n++) { - vcdinfo_video_segment_type_t segtype + vcdinfo_video_segment_type_t segtype = vcdinfo_get_video_type(p_vcdinfo, n); char c='S'; switch (segtype) { @@ -444,10 +442,10 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) vcd_add_mrl_slot(class, mrl, vcdplayer->segment[n].size, &i); } } - - dbg_print(INPUT_DBG_MRL, - "offsets are track: %d, entry: %d, play: %d seg: %d\n", - class->mrl_track_offset, class->mrl_entry_offset, + + dbg_print(INPUT_DBG_MRL, + "offsets are track: %d, entry: %d, play: %d seg: %d\n", + class->mrl_track_offset, class->mrl_entry_offset, class->mrl_play_offset, class->mrl_segment_offset); return true; @@ -455,9 +453,9 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) /*! parses a MRL which has the format - + vcd://[vcd_path][@[EPTS]?number]\*? - + Examples vcd:// - Play (navigate) default device: /dev/cdrom vcd://@ - same as above @@ -469,7 +467,7 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) vcd://dev/cdrom@E0 - Play Entry id 0 from default device vcd://@P1 - probably same as above. If there is no playback control, MRL will - get converted into vcd://@E0 + get converted into vcd://@E0 vcd://@P1* - probably same as above. vcd://@S0 - Play segment 0 from default device vcd://@3 - Play track 3 from default device @@ -477,7 +475,7 @@ vcd_build_mrl_list(vcd_input_class_t *class, char *vcd_device) vcd:///tmp/ntsc.bin@ - Play default item from /tmp/ntsc.bin vcd:///tmp/ntsc.bin/@E0 - Play entry 0 of /tmp/ntsc.bin -parameters: +parameters: mrl : mrl to parse default_vcd_device: name of device to use when none given auto_type : type of selection (entry, track, LID) when none given @@ -485,10 +483,10 @@ parameters: */ static bool -vcd_parse_mrl(/*in*/ const char *default_vcd_device, /*in*/ char *mrl, +vcd_parse_mrl(/*in*/ const char *default_vcd_device, /*in*/ char *mrl, /*out*/ char *device_str, /*out*/ vcdinfo_itemid_t *itemid, - /*in */ vcdplayer_autoplay_t auto_type, - /*out*/ bool *used_default) + /*in */ vcdplayer_autoplay_t auto_type, + /*out*/ bool *used_default) { char type_str[2]; int count; @@ -509,15 +507,15 @@ vcd_parse_mrl(/*in*/ const char *default_vcd_device, /*in*/ char *mrl, device_str[0] = '/'; device_str[1] = 0; - count = sscanf (p, "%1023[^@]@%1[EePpSsTt]%u", + count = sscanf (p, "%1023[^@]@%1[EePpSsTt]%u", device_str + 1, type_str, &num); itemid->num = num; - + switch (count) { case 1: /* Matched device, but nothing beyond that */ if (strlen(device_str)!=0 && device_str[0] != ':') { - /* See if we have old-style MRL with no type specifier. + /* See if we have old-style MRL with no type specifier. If so, we assume "track". */ count = sscanf (p, "%u", &num); itemid->num = num; @@ -536,7 +534,7 @@ vcd_parse_mrl(/*in*/ const char *default_vcd_device, /*in*/ char *mrl, _x_mrl_unescape (device_str); case 0: - case EOF: + case EOF: { /* No device/file given, so use the default device and try again. */ if (NULL == default_vcd_device) return false; @@ -545,16 +543,16 @@ vcd_parse_mrl(/*in*/ const char *default_vcd_device, /*in*/ char *mrl, count = sscanf (p, "%1[EePpSsTt]%u", type_str, &num); type_str[0] = toupper(type_str[0]); itemid->num = num; - + switch (count) { case EOF: /* Default PBC navigation. */ return true; case 0: - /* See if we have old-style MRL with no type specifier. + /* See if we have old-style MRL with no type specifier. If so, we assume "track". */ count = sscanf (p, "%u", &num); - if (1==count) { + if (1==count) { type_str[0] = 'T'; break; } @@ -570,45 +568,45 @@ vcd_parse_mrl(/*in*/ const char *default_vcd_device, /*in*/ char *mrl, /* We have some sort of track/selection/entry number */ switch (type_str[0]) { - case 'E': + case 'E': itemid->type = VCDINFO_ITEM_TYPE_ENTRY; break; - case '\0': + case '\0': /* None specified, use config value. */ itemid->type = (vcdinfo_item_enum_t) auto_type; *used_default = true; break; - case 'P': + case 'P': itemid->type = VCDINFO_ITEM_TYPE_LID; break; - case 'S': + case 'S': itemid->type = VCDINFO_ITEM_TYPE_SEGMENT; break; - case 'T': + case 'T': itemid->type = VCDINFO_ITEM_TYPE_TRACK; break; default: ; } - - if ( 0==itemid->num - && ( (VCDINFO_ITEM_TYPE_LID == itemid->type) + + if ( 0==itemid->num + && ( (VCDINFO_ITEM_TYPE_LID == itemid->type) || (VCDINFO_ITEM_TYPE_TRACK == itemid->type) ) ) itemid->num = 1; return true; } -/*! +/*! From xine plugin spec: return capabilities of input source */ -static uint32_t +static uint32_t vcd_plugin_get_capabilities (input_plugin_t *this_gen) { - uint32_t ret = - INPUT_CAP_AUDIOLANG | INPUT_CAP_BLOCK | + uint32_t ret = + INPUT_CAP_AUDIOLANG | INPUT_CAP_BLOCK | INPUT_CAP_CHAPTERS | INPUT_CAP_PREVIEW | (my_vcd.player.i_still ? 0: INPUT_CAP_SEEKABLE) | INPUT_CAP_SPULANG; @@ -620,14 +618,14 @@ vcd_plugin_get_capabilities (input_plugin_t *this_gen) # if FINISHED /* If needed, will fill out later... */ -static void +static void vcd_read_ahead_cb(void *this_gen, xine_cfg_entry_t *entry) { return; } #endif -static void +static void vcd_flush_buffers(void) { _x_demux_flush_engine(my_vcd.stream); @@ -638,11 +636,11 @@ vcd_flush_buffers(void) read nlen bytes, return number of bytes read. */ -static off_t +static off_t vcd_plugin_read (input_plugin_t *this_gen, char *buf, const off_t nlen) { - dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), + dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "Called with nlen %u\n", (unsigned int) nlen); /* FIXME: Tricking the demux_mpeg_block plugin */ @@ -654,7 +652,7 @@ vcd_plugin_read (input_plugin_t *this_gen, char *buf, const off_t nlen) } /* Allocate and return a no-op buffer. This signals the outside - to do nothing, but in contrast to returning NULL, it doesn't + to do nothing, but in contrast to returning NULL, it doesn't mean the stream has ended. We use this say for still frames. */ #define RETURN_NOOP_BUF \ @@ -679,8 +677,8 @@ vcd_plugin_read (input_plugin_t *this_gen, char *buf, const off_t nlen) function */ static buf_element_t * -vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, - const off_t i_len) +vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, + const off_t i_len) { vcd_input_plugin_t *vcd_input_plugin= (vcd_input_plugin_t *) this_gen; vcdplayer_t *p_vcdplayer = &my_vcd.player; @@ -720,7 +718,7 @@ vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, SLEEP_AND_HANDLE_EVENTS; } } - + read_block: switch (vcdplayer_read(p_vcdplayer, data, i_len)) { @@ -730,37 +728,37 @@ vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, case READ_ERROR: /* Some sort of error. */ return NULL; - case READ_STILL_FRAME: + case READ_STILL_FRAME: { dbg_print(INPUT_DBG_STILL, "Handled still event wait time %u\n", p_vcdplayer->i_still); vcd_input_plugin->pause_end_time = time(NULL) + p_vcdplayer->i_still; RETURN_NOOP_BUF; } - + default: case READ_BLOCK: /* Read buffer */ p_buf = fifo->buffer_pool_alloc (fifo); p_buf->type = BUF_DEMUX_BLOCK; } - + p_buf->content = p_buf->mem; if (STILL_READING == p_vcdplayer->i_still && 0 == my_vcd.i_old_still) { - my_vcd.i_old_deinterlace = xine_get_param(my_vcd.stream, + my_vcd.i_old_deinterlace = xine_get_param(my_vcd.stream, XINE_PARAM_VO_DEINTERLACE); xine_set_param(my_vcd.stream, XINE_PARAM_VO_DEINTERLACE, 0); - dbg_print(INPUT_DBG_STILL, "going into still, saving deinterlace %d\n", + dbg_print(INPUT_DBG_STILL, "going into still, saving deinterlace %d\n", my_vcd.i_old_deinterlace); } else if (0 == p_vcdplayer->i_still && 0 != my_vcd.i_old_still) { - dbg_print(INPUT_DBG_STILL, + dbg_print(INPUT_DBG_STILL, "going out of still, restoring deinterlace\n"); xine_set_param(my_vcd.stream, XINE_PARAM_VO_DEINTERLACE, my_vcd.i_old_deinterlace); } my_vcd.i_old_still = p_vcdplayer->i_still; - + /* Ideally this should probably be i_len. */ memcpy (p_buf->mem, data, M2F2_SECTOR_SIZE); @@ -770,12 +768,12 @@ vcd_plugin_read_block (input_plugin_t *this_gen, fifo_buffer_t *fifo, /*! From xine plugin spec: - seek position, return new position + seek position, return new position if seeking failed, -1 is returned */ -static off_t -vcd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) +static off_t +vcd_plugin_seek (input_plugin_t *this_gen, off_t offset, int origin) { return vcdio_seek (&my_vcd.player, offset, origin); } @@ -794,7 +792,7 @@ static off_t old_get_length = 0; static vcdplayer_slider_length_t old_slider_length; /* This routine is called a bit. Make reasonably fast. */ -static off_t +static off_t vcd_plugin_get_length (input_plugin_t *this_gen) { vcd_input_plugin_t *ip= (vcd_input_plugin_t *) this_gen; @@ -803,7 +801,7 @@ vcd_plugin_get_length (input_plugin_t *this_gen) { int n = vcdplayer->play_item.num; if (vcdplayer->play_item.num == old_play_item.num - && vcdplayer->play_item.type == old_play_item.type + && vcdplayer->play_item.type == old_play_item.type && vcdplayer->slider_length == old_slider_length) return old_get_length; @@ -835,7 +833,7 @@ vcd_plugin_get_length (input_plugin_t *this_gen) { /* This is the only situation where the size of the current play item is not static. It depends what the current play-item is. */ - old_get_length = (vcdplayer->end_lsn - vcdplayer->origin_lsn) * + old_get_length = (vcdplayer->end_lsn - vcdplayer->origin_lsn) * M2F2_SECTOR_SIZE; return old_get_length; break; @@ -845,11 +843,11 @@ vcd_plugin_get_length (input_plugin_t *this_gen) { /* FIXME? */ return -1; } - + if (n >= 0 && n < ip->class->num_mrls) { old_get_length = ip->class->mrls[n]->size; - dbg_print(INPUT_DBG_MRL, "item: %u, slot %u, size %ld\n", - vcdplayer->play_item.num, + dbg_print(INPUT_DBG_MRL, "item: %u, slot %u, size %ld\n", + vcdplayer->play_item.num, (unsigned int) n, (long int) old_get_length); } return old_get_length; @@ -860,7 +858,7 @@ vcd_plugin_get_length (input_plugin_t *this_gen) { * get current position in stream. * */ -static off_t +static off_t vcd_plugin_get_current_pos (input_plugin_t *this_gen){ // trace_print("Called\n"); return (vcd_plugin_seek (this_gen, 0, SEEK_CUR)); @@ -871,7 +869,7 @@ vcd_plugin_get_current_pos (input_plugin_t *this_gen){ * From xine plugin spec: * return block size of input source (if supported, 0 otherwise) */ -static uint32_t +static uint32_t vcd_plugin_get_blocksize (input_plugin_t *this_gen) { dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called\n"); @@ -887,7 +885,7 @@ vcd_plugin_get_blocksize (input_plugin_t *this_gen) { */ static xine_mrl_t ** -vcd_class_get_dir (input_class_t *this_gen, const char *filename, +vcd_class_get_dir (input_class_t *this_gen, const char *filename, int *num_files) { char intended_vcd_device[MAX_DEVICE_LEN+1]= { '\0', }; @@ -899,7 +897,7 @@ vcd_class_get_dir (input_class_t *this_gen, const char *filename, bool used_default; if (filename == NULL) { - dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), + dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called with NULL\n"); if ( class->mrls != NULL && NULL != class->mrls[0] ) goto have_mrls; @@ -908,12 +906,12 @@ vcd_class_get_dir (input_class_t *this_gen, const char *filename, } } else { char *mrl = strdup(filename); - dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), + dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called with %s\n", filename); if (!vcd_get_default_device(class, true)) goto no_mrls; - if (!vcd_parse_mrl(class->vcd_device, mrl, - intended_vcd_device, &itemid, - vcdplayer->default_autoplay, &used_default)) { + if (!vcd_parse_mrl(class->vcd_device, mrl, + intended_vcd_device, &itemid, + vcdplayer->default_autoplay, &used_default)) { free (mrl); goto no_mrls; } @@ -925,17 +923,17 @@ vcd_class_get_dir (input_class_t *this_gen, const char *filename, return class->mrls; no_mrls: - *num_files = 0; - return NULL; + *num_files = 0; + return NULL; } #define FREE_AND_NULL(ptr) if (NULL != ptr) free(ptr); ptr = NULL; static void -vcd_close(vcd_input_class_t *class) +vcd_close(vcd_input_class_t *class) { xine_free_mrls(&(class->num_mrls), class->mrls); - FREE_AND_NULL(my_vcd.mrl); + FREE_AND_NULL(my_vcd.mrl); if (my_vcd.player.b_opened) vcdio_close(&my_vcd.player); } @@ -947,15 +945,15 @@ vcd_close(vcd_input_class_t *class) * * returns 0 for temporary failures */ -static int -vcd_class_eject_media (input_class_t *this_gen) +static int +vcd_class_eject_media (input_class_t *this_gen) { int ret; CdIo_t *cdio=vcdinfo_get_cd_image(my_vcd.player.vcd); - + dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called\n"); if (NULL == cdio) return 0; - + ret = cdio_eject_media(&cdio); if ((ret == 0) || (ret == 2)) { if (my_vcd.player.b_opened) @@ -968,8 +966,8 @@ vcd_class_eject_media (input_class_t *this_gen) * From spec: * return current MRL */ -static char * -vcd_plugin_get_mrl (input_plugin_t *this_gen) +static const char * +vcd_plugin_get_mrl (input_plugin_t *this_gen) { vcd_input_plugin_t *t = (vcd_input_plugin_t *) this_gen; vcdplayer_t *vcdplayer = &my_vcd.player; @@ -987,28 +985,28 @@ vcd_plugin_get_mrl (input_plugin_t *this_gen) if (-2 == offset) { /* Bad type. */ - LOG_ERR("%s %d", _("Invalid current entry type"), + LOG_ERR("%s %d", _("Invalid current entry type"), vcdplayer->play_item.type); - return strdup(""); + return ""; } else { n += offset; if (n < t->class->num_mrls) { - dbg_print(INPUT_DBG_CALL, "Called, returning %s\n", + dbg_print(INPUT_DBG_CALL, "Called, returning %s\n", t->class->mrls[n]->mrl); return t->class->mrls[n]->mrl; } else { - return strdup(""); + return ""; } } } /*! From xine plugin spec: - + return human readable (verbose = 1 line) description for this plugin */ -static char * -vcd_class_get_description (input_class_t *this_gen) +static const char * +vcd_class_get_description (input_class_t *this_gen) { dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called\n"); return _("Video CD plugin with PBC and support for: (X)VCD, (X)SVCD, HQVCD, CVD ... "); @@ -1027,12 +1025,12 @@ vcd_class_get_identifier (input_class_t *this_gen) { return SHORT_PLUGIN_NAME; } -/* +/* Handle all queued keyboard/mouse events. Return TRUE if this causes a change in the play item. */ static bool -vcd_handle_events (void) +vcd_handle_events (void) { vcdplayer_t *p_vcdplayer = &my_vcd.player; xine_event_t *p_event; @@ -1040,7 +1038,7 @@ vcd_handle_events (void) /* What you add to the last input number entry. It accumulates all of the 10_ADD keypresses */ - static unsigned int number_addend = 0; + static unsigned int number_addend = 0; while ((p_event = xine_event_get(my_vcd.event_queue))) { @@ -1050,14 +1048,14 @@ vcd_handle_events (void) switch(p_event->type) { case XINE_EVENT_INPUT_NUMBER_10_ADD: - number_addend += 10; - dbg_print(INPUT_DBG_EVENT, "10 added to number. Is now: %d\n", + number_addend += 10; + dbg_print(INPUT_DBG_EVENT, "10 added to number. Is now: %d\n", number_addend); break; /* The method used below is oblivious to XINE_EVENT_INPUT encodings - In particular, it does not assume XINE_EVENT_INPUT_NUMBE_9 = - XINE_EVENT_INPUT_NUMBER_0 + 9. + In particular, it does not assume XINE_EVENT_INPUT_NUMBE_9 = + XINE_EVENT_INPUT_NUMBER_0 + 9. */ case XINE_EVENT_INPUT_NUMBER_9: digit_entered++; @@ -1081,7 +1079,7 @@ vcd_handle_events (void) { number_addend *= 10; number_addend += digit_entered; - dbg_print(INPUT_DBG_EVENT, + dbg_print(INPUT_DBG_EVENT, "digit added number is now: %d\n", number_addend); break; } @@ -1090,65 +1088,65 @@ vcd_handle_events (void) vcdplayer_debug = number_addend; number_addend = 0; break; - case XINE_EVENT_INPUT_MENU1: + case XINE_EVENT_INPUT_MENU1: case XINE_EVENT_INPUT_MENU2: - case XINE_EVENT_INPUT_NEXT: + case XINE_EVENT_INPUT_NEXT: case XINE_EVENT_INPUT_PREVIOUS: { int num = number_addend; vcdinfo_itemid_t itemid; - + number_addend = 0; - + /* If no number was given it's really the same as 1, not 0. */ if (num == 0) num++; - - dbg_print(INPUT_DBG_EVENT, - "RETURN/NEXT/PREV/DEFAULT (%d) iteration count %d\n", + + dbg_print(INPUT_DBG_EVENT, + "RETURN/NEXT/PREV/DEFAULT (%d) iteration count %d\n", p_event->type, num); for ( ; num > 0; num--) { itemid = p_vcdplayer->play_item; switch (p_event->type) { - case XINE_EVENT_INPUT_MENU1: + case XINE_EVENT_INPUT_MENU1: if (p_vcdplayer->return_entry == VCDINFO_INVALID_ENTRY) { LOG_MSG("%s\n", _("selection has no RETURN entry")); return false; } itemid.num = p_vcdplayer->return_entry; - dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), + dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), "RETURN to %d\n", itemid.num); /* Don't loop around -- doesn't make sense to loop a return*/ - num = 0; + num = 0; break; - case XINE_EVENT_INPUT_MENU2: + case XINE_EVENT_INPUT_MENU2: if (vcdplayer_pbc_is_on(p_vcdplayer)) { - lid_t lid=vcdinfo_get_multi_default_lid(p_vcdplayer->vcd, + lid_t lid=vcdinfo_get_multi_default_lid(p_vcdplayer->vcd, p_vcdplayer->i_lid, p_vcdplayer->i_lsn); if (VCDINFO_INVALID_LID != lid) { itemid.num = lid; - dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), + dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), "DEFAULT to %d\n", itemid.num); } else { - dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), - "no DEFAULT for LID %d\n", + dbg_print((INPUT_DBG_PBC|INPUT_DBG_EVENT), + "no DEFAULT for LID %d\n", p_vcdplayer->i_lid); } - + /* Don't loop around -- doesn't make sense to loop a return*/ - num = 0; + num = 0; } else { - /* PBC is not on. "default" selection beginning of current + /* PBC is not on. "default" selection beginning of current selection . Alternative: */ LOG_MSG("%s\n", _("DEFAULT selected, but PBC is not on.")); } break; - case XINE_EVENT_INPUT_NEXT: + case XINE_EVENT_INPUT_NEXT: if (p_vcdplayer->next_entry == VCDINFO_INVALID_ENTRY) { LOG_MSG("%s\n", _("selection has no NEXT entry")); return false; - } + } itemid.num = p_vcdplayer->next_entry; dbg_print(INPUT_DBG_PBC, "NEXT to %d\n", itemid.num); break; @@ -1160,7 +1158,7 @@ vcd_handle_events (void) itemid.num = p_vcdplayer->prev_entry; dbg_print(INPUT_DBG_PBC, "PREVIOUS to %d\n", itemid.num); break; - default: + default: LOG_MSG("%s %d\n", _("Unknown event type: "), p_event->type); } _x_demux_flush_engine(my_vcd.stream); @@ -1174,13 +1172,13 @@ vcd_handle_events (void) /* In the future will have to test to see if we are in a menu selection. But if not... */ vcdinfo_itemid_t itemid = p_vcdplayer->play_item; - + itemid.num = number_addend; number_addend = 0; - + if (vcdplayer_pbc_is_on(p_vcdplayer)) { - lid_t i_next=vcdinfo_selection_get_lid(p_vcdplayer->vcd, - p_vcdplayer->i_lid, + lid_t i_next=vcdinfo_selection_get_lid(p_vcdplayer->vcd, + p_vcdplayer->i_lid, itemid.num); if (VCDINFO_INVALID_LID != i_next) { itemid.num = i_next; @@ -1191,30 +1189,30 @@ vcd_handle_events (void) } break; } - case XINE_EVENT_INPUT_MOUSE_BUTTON: + case XINE_EVENT_INPUT_MOUSE_BUTTON: if (my_vcd.stream) { xine_input_data_t *p_input = p_event->data; - if (p_input->button == 1) + if (p_input->button == 1) { #if LIBVCD_VERSION_NUM >= 23 int i_selection; #endif - dbg_print(INPUT_DBG_EVENT, - "Button to x: %d, y: %d, scaled x: %d, scaled y %d\n", + dbg_print(INPUT_DBG_EVENT, + "Button to x: %d, y: %d, scaled x: %d, scaled y %d\n", p_input->x, p_input->y, p_input->x * 255 / p_vcdplayer->max_x, p_input->y * 255 / p_vcdplayer->max_y); - + #if LIBVCD_VERSION_NUM >= 23 /* xine_dvd_send_button_update(this, 1); */ - + if (my_vcd.b_mouse_in) send_mouse_enter_leave_event(&my_vcd, false); - i_selection = vcdinfo_get_area_selection(p_vcdplayer->vcd, - p_vcdplayer->i_lid, + i_selection = vcdinfo_get_area_selection(p_vcdplayer->vcd, + p_vcdplayer->i_lid, p_input->x, p_input->y, p_vcdplayer->max_x, @@ -1223,8 +1221,8 @@ vcd_handle_events (void) if (vcdplayer_pbc_is_on(p_vcdplayer)) { vcdinfo_itemid_t itemid = p_vcdplayer->play_item; - lid_t i_next=vcdinfo_selection_get_lid(p_vcdplayer->vcd, - p_vcdplayer->i_lid, + lid_t i_next=vcdinfo_selection_get_lid(p_vcdplayer->vcd, + p_vcdplayer->i_lid, i_selection); if (VCDINFO_INVALID_LID != i_next) { itemid.num = i_next; @@ -1237,33 +1235,33 @@ vcd_handle_events (void) } } break; - case XINE_EVENT_INPUT_BUTTON_FORCE: + case XINE_EVENT_INPUT_BUTTON_FORCE: break; - case XINE_EVENT_INPUT_MOUSE_MOVE: - if (my_vcd.stream) + case XINE_EVENT_INPUT_MOUSE_MOVE: + if (my_vcd.stream) { xine_input_data_t *p_input = p_event->data; #if LIBVCD_VERSION_NUM >= 23 - int32_t i_selection = vcdinfo_get_area_selection(p_vcdplayer->vcd, - p_vcdplayer->i_lid, + int32_t i_selection = vcdinfo_get_area_selection(p_vcdplayer->vcd, + p_vcdplayer->i_lid, p_input->x, p_input->y, p_vcdplayer->max_x, p_vcdplayer->max_y); - dbg_print(INPUT_DBG_EVENT, "Move to x: %d, y: %d\n", + dbg_print(INPUT_DBG_EVENT, "Move to x: %d, y: %d\n", p_input->x, p_input->y); - + if (my_vcd.i_mouse_button != i_selection) { - dbg_print(INPUT_DBG_EVENT, "Old selection: %d, selection: %d\n", + dbg_print(INPUT_DBG_EVENT, "Old selection: %d, selection: %d\n", my_vcd.i_mouse_button, i_selection); my_vcd.i_mouse_button = i_selection; - if (i_selection < 0) + if (i_selection < 0) send_mouse_enter_leave_event(&my_vcd, false); - else + else send_mouse_enter_leave_event(&my_vcd, true); } #else - dbg_print(INPUT_DBG_EVENT, "Move to x: %d, y: %d\n", + dbg_print(INPUT_DBG_EVENT, "Move to x: %d, y: %d\n", p_input->x, p_input->y); #endif } @@ -1294,19 +1292,19 @@ vcd_handle_events (void) request optional data from input plugin. */ -static int -vcd_get_optional_data (input_plugin_t *this_gen, +static int +vcd_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "called with %d\n", data_type); if (NULL == my_vcd.stream) return INPUT_OPTIONAL_UNSUPPORTED; /* Fill this out more fully... */ switch(data_type) { - - case INPUT_OPTIONAL_DATA_AUDIOLANG: + + case INPUT_OPTIONAL_DATA_AUDIOLANG: { uint8_t channel; channel = _x_get_audio_channel(my_vcd.stream); @@ -1330,8 +1328,8 @@ vcd_get_optional_data (input_plugin_t *this_gen, } return INPUT_OPTIONAL_SUCCESS; } - - case INPUT_OPTIONAL_DATA_SPULANG: + + case INPUT_OPTIONAL_DATA_SPULANG: { /*uint16_t lang;*/ int8_t channel; @@ -1342,12 +1340,12 @@ vcd_get_optional_data (input_plugin_t *this_gen, } else { sprintf(data, "%1d", channel); } - + } default: ; } - + return INPUT_OPTIONAL_UNSUPPORTED; } @@ -1365,7 +1363,7 @@ vcd_get_optional_data (input_plugin_t *this_gen, */ static char ** -vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) +vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) { vcd_input_class_t *class = (vcd_input_class_t *) this_gen; static char *filelist[MAX_DIR_ENTRIES]; @@ -1378,9 +1376,9 @@ vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) } else { int i; int size = 0; - vcdinfo_item_enum_t itemtype = + vcdinfo_item_enum_t itemtype = autoplay2itemtype[my_vcd.player.default_autoplay]; - + int offset = vcd_get_mrl_type_offset(&my_vcd, itemtype, &size); /* A VCD is not required to have PBC or LID's, default to entry if @@ -1391,7 +1389,7 @@ vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) offset = vcd_get_mrl_type_offset(&my_vcd, itemtype, &size); } - /* This is because entries start at 0 while other playable units + /* This is because entries start at 0 while other playable units start at 1. Can remove the below when everything has the same origin. */ @@ -1412,14 +1410,14 @@ vcd_class_get_autoplay_list (input_class_t *this_gen, int *num_files) } /*! - Things that need to be done when a stream is closed. + Things that need to be done when a stream is closed. */ -static void -vcd_plugin_dispose(input_plugin_t *this_gen) +static void +vcd_plugin_dispose(input_plugin_t *this_gen) { /* Not sure there's much more to do here... - In open_plugin we are given a stream which + In open_plugin we are given a stream which we save... */ dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called\n"); @@ -1435,10 +1433,10 @@ vcd_plugin_dispose(input_plugin_t *this_gen) static vcd_log_handler_t gl_default_vcd_log_handler = NULL; static cdio_log_handler_t gl_default_cdio_log_handler = NULL; -/*! This routine is called by libvcd routines on error. +/*! This routine is called by libvcd routines on error. Setup is done by init_input_plugin. */ -static void +static void vcd_log_handler (vcd_log_level_t level, const char message[]) { switch (level) { @@ -1455,19 +1453,19 @@ vcd_log_handler (vcd_log_level_t level, const char message[]) LOG_ERR("%s", message); break; default: - LOG_ERR("%s\n%s %d", - message, - _("The above message had unknown vcdimager log level"), + LOG_ERR("%s\n%s %d", + message, + _("The above message had unknown vcdimager log level"), level); } - + /* gl_default_vcd_log_handler (level, message); */ } -/*! This routine is called by libcdio routines on error. +/*! This routine is called by libcdio routines on error. Setup is done by init_input_plugin. */ -static void +static void cdio_log_handler (cdio_log_level_t level, const char message[]) { switch (level) { @@ -1480,10 +1478,10 @@ cdio_log_handler (cdio_log_level_t level, const char message[]) } } -/*! This routine is when xine is not around. +/*! This routine is when xine is not around. Setup is done by vcd_class_dispose. */ -static void +static void uninit_log_handler (vcd_log_level_t level, const char message[]) { switch (level) { @@ -1503,25 +1501,25 @@ uninit_log_handler (vcd_log_level_t level, const char message[]) break; default: fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d", - message, - _("The above message had unknown vcdimager log level"), + message, + _("The above message had unknown vcdimager log level"), level); } - + /* gl_default_vcd_log_handler (level, message); */ } /*! - Things that need to be done the vcd plugin is closed. + Things that need to be done the vcd plugin is closed. */ -static void +static void vcd_class_dispose (input_class_t *this_gen) { vcd_input_class_t *class = (vcd_input_class_t *) this_gen; class->xine->config->unregister_callback(class->xine->config, "media.vcd.device"); gl_default_vcd_log_handler = vcd_log_set_handler (uninit_log_handler); - gl_default_cdio_log_handler = + gl_default_cdio_log_handler = cdio_log_set_handler ((cdio_log_handler_t) uninit_log_handler); dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called\n"); @@ -1530,22 +1528,22 @@ vcd_class_dispose (input_class_t *this_gen) { } /* Update the xine player title text. */ -static void -vcd_update_title_display(void) +static void +vcd_update_title_display(void) { xine_event_t uevent; xine_ui_data_t data; char *title_str; - - title_str = vcdplayer_format_str(&my_vcd.player, + + title_str = vcdplayer_format_str(&my_vcd.player, my_vcd.v_config.title_format); meta_info_assign(XINE_META_INFO_TITLE, my_vcd.stream, title_str); meta_info_assign(XINE_META_INFO_COMMENT, my_vcd.stream, - vcdplayer_format_str(&my_vcd.player, + vcdplayer_format_str(&my_vcd.player, my_vcd.v_config.comment_format)); - stream_info_assign(XINE_STREAM_INFO_VIDEO_HAS_STILL, my_vcd.stream, + stream_info_assign(XINE_STREAM_INFO_VIDEO_HAS_STILL, my_vcd.stream, my_vcd.player.i_still); /* Set_str title/chapter display */ @@ -1563,8 +1561,8 @@ vcd_update_title_display(void) } #if LIBVCD_VERSION_NUM >= 23 -static void -send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, bool b_mouse_in) +static void +send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, bool b_mouse_in) { if (b_mouse_in && p_this->b_mouse_in) { /* Set up to enter the following "if" statement. */ @@ -1574,16 +1572,16 @@ send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, bool b_mouse_in) if (b_mouse_in != p_this->b_mouse_in) { xine_event_t event; xine_spu_button_t spu_event; - + spu_event.direction = b_mouse_in ? 1 : 0; spu_event.button = p_this->i_mouse_button; - + event.type = XINE_EVENT_SPU_BUTTON; event.stream = p_this->stream; event.data = &spu_event; event.data_length = sizeof(spu_event); xine_event_send(p_this->stream, &event); - + p_this->b_mouse_in = b_mouse_in; } @@ -1591,22 +1589,22 @@ send_mouse_enter_leave_event(vcd_input_plugin_t *p_this, bool b_mouse_in) p_this->i_mouse_button = -1; } #endif - -/* - Not much special initialization needed here. All of the initialization + +/* + Not much special initialization needed here. All of the initialization is either done in the class or when we have an actual MRL we want to deal with. */ -static int +static int vcd_plugin_open (input_plugin_t *this_gen ) { vcd_input_class_t *class = (vcd_input_class_t *) this_gen->input_class; gl_default_vcd_log_handler = vcd_log_set_handler (vcd_log_handler); gl_default_cdio_log_handler = cdio_log_set_handler (cdio_log_handler); - /* actually, this is also done by class initialization. But just in + /* actually, this is also done by class initialization. But just in case... */ - class->ip = &my_vcd; + class->ip = &my_vcd; my_vcd.i_old_still = 0; return 1; @@ -1617,17 +1615,17 @@ vcd_plugin_open (input_plugin_t *this_gen ) { routine is called, xine-lib can read blocks from the thing specified by the MRL, set the position of the thing specified by the MRL, get its size or read its current position... - + See vcdplayer_parses_mrl for the for the format that a valid MRL can take. - Return values: + Return values: pointer to input plugin NULL on failure */ static input_plugin_t * vcd_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, - const char *mrl) + const char *mrl) { vcd_input_class_t *class = (vcd_input_class_t *) class_gen; @@ -1636,9 +1634,9 @@ vcd_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, char *check_mrl=NULL; bool used_default; - if (mrl == NULL) + if (mrl == NULL) check_mrl = strdup(MRL_PREFIX); - else + else check_mrl = strdup(mrl); dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT), "called with %s\n", mrl); @@ -1649,7 +1647,7 @@ vcd_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, vcd_get_default_device(class, false); - if (!vcd_parse_mrl(class->vcd_device, check_mrl, + if (!vcd_parse_mrl(class->vcd_device, check_mrl, intended_vcd_device, &itemid, my_vcd.player.default_autoplay, &used_default)) { dbg_print(INPUT_DBG_MRL, "parsing MRL %s failed\n", check_mrl); @@ -1669,32 +1667,32 @@ vcd_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, my_vcd.player.user_data = (void *) class; /* Do we set PBC (via LID) on? */ - my_vcd.player.i_lid = - ( VCDINFO_ITEM_TYPE_LID == itemid.type + my_vcd.player.i_lid = + ( VCDINFO_ITEM_TYPE_LID == itemid.type && my_vcd.player.i_lids > itemid.num ) ? itemid.num : VCDINFO_INVALID_ENTRY; if ( VCDINFO_ITEM_TYPE_LID == itemid.type && used_default) { - /* LID was selected automatically but we don't have PBC for this VCD. + /* LID was selected automatically but we don't have PBC for this VCD. So silently change LID to track and continue. */ itemid.type=VCDINFO_ITEM_TYPE_TRACK; } - if ( 0==itemid.num - && ( (VCDINFO_ITEM_TYPE_LID == itemid.type) + if ( 0==itemid.num + && ( (VCDINFO_ITEM_TYPE_LID == itemid.type) || (VCDINFO_ITEM_TYPE_TRACK == itemid.type) ) ) itemid.num = 1; - dbg_print(INPUT_DBG_PBC, "Jumping to NUM >%i<, type >%i<\n", + dbg_print(INPUT_DBG_PBC, "Jumping to NUM >%i<, type >%i<\n", itemid.num, itemid.type); vcd_set_meta_info(&my_vcd); vcdplayer_play(&my_vcd.player, itemid); - - dbg_print(INPUT_DBG_MRL, "Successfully opened MRL %s.\n", + + dbg_print(INPUT_DBG_MRL, "Successfully opened MRL %s.\n", my_vcd.mrl); free (check_mrl); @@ -1733,30 +1731,30 @@ vcd_class_get_instance (input_class_t *class_gen, xine_stream_t *stream, var = strdup(entry->str_value); \ } -VCD_STR_CALLBACK(vcd_default_dev_changed_cb, +VCD_STR_CALLBACK(vcd_default_dev_changed_cb, my_vcd.class->vcd_device) -VCD_STR_CALLBACK(vcd_title_format_changed_cb, +VCD_STR_CALLBACK(vcd_title_format_changed_cb, my_vcd.v_config.title_format) -VCD_STR_CALLBACK(vcd_comment_format_changed_cb, +VCD_STR_CALLBACK(vcd_comment_format_changed_cb, my_vcd.v_config.comment_format) VCD_NUM_CALLBACK(vcd_show_rejected_cb, show_rejected) VCD_NUM_CALLBACK(vcd_autoadvance_cb, autoadvance) -VCD_ENUM_CALLBACK(vcd_slider_length_cb, vcdplayer_slider_length_t, +VCD_ENUM_CALLBACK(vcd_slider_length_cb, vcdplayer_slider_length_t, slider_length) VCD_ENUM_CALLBACK(vcd_default_autoplay_cb, vcdinfo_item_enum_t, default_autoplay) -static void -vcd_debug_cb(void *this_gen, xine_cfg_entry_t *entry) +static void +vcd_debug_cb(void *this_gen, xine_cfg_entry_t *entry) { dbg_print(INPUT_DBG_CALL, "Called setting %d\n", entry->num_value); - vcdplayer_debug = entry->num_value; + vcdplayer_debug = entry->num_value; } static void * @@ -1767,7 +1765,7 @@ vcd_init (xine_t *xine, void *data) dbg_print(INPUT_DBG_CALL, "Called\n"); - class = (vcd_input_class_t *) xine_xmalloc (sizeof (vcd_input_class_t)); + class = calloc(1, sizeof (vcd_input_class_t)); class->xine = xine; class->config = config = xine->config; @@ -1778,7 +1776,7 @@ vcd_init (xine_t *xine, void *data) class->input_class.get_instance = vcd_class_get_instance; class->input_class.get_identifier = vcd_class_get_identifier; class->input_class.get_description = vcd_class_get_description; - class->input_class.get_dir = vcd_class_get_dir; + class->input_class.get_dir = vcd_class_get_dir; class->input_class.get_autoplay_list = vcd_class_get_autoplay_list; class->input_class.dispose = vcd_class_dispose; class->input_class.eject_media = vcd_class_eject_media; @@ -1794,9 +1792,9 @@ vcd_init (xine_t *xine, void *data) my_vcd.player.log_msg = (generic_fn) &xine_log_msg; my_vcd.player.force_redisplay = &vcd_force_redisplay; my_vcd.player.set_aspect_ratio = &vcd_set_aspect_ratio; - + /*------------------------------------------------------------- - Playback control-specific fields + Playback control-specific fields --------------------------------------------------------------*/ my_vcd.player.i_lid = VCDINFO_INVALID_ENTRY; @@ -1812,58 +1810,58 @@ vcd_init (xine_t *xine, void *data) my_vcd.player.prev_entry = -1; my_vcd.player.return_entry = -1; my_vcd.player.default_entry = -1; - + /*-------------------------------------------------------------- Configuration variables ---------------------------------------------------------------*/ - { + { /*Note: these labels have to be listed in the same order as the - enumeration vcdplayer_autoplay_t in vcdplayer.h. + enumeration vcdplayer_autoplay_t in vcdplayer.h. */ - static const char *autoplay_modes[] = + static const char *autoplay_modes[] = { "MPEG track", "entry", "segment", "playback-control item", NULL }; - + /*Note: these labels have to be listed in the same order as the - enumeration vcdplayer_slider_length_t in vcdplayer.h. + enumeration vcdplayer_slider_length_t in vcdplayer.h. */ - static const char *length_reporting_modes[] = + static const char *length_reporting_modes[] = { "auto", "track", "entry", NULL }; - - my_vcd.player.default_autoplay = - config->register_enum(config, + + my_vcd.player.default_autoplay = + config->register_enum(config, "media.vcd.autoplay", VCDPLAYER_AUTOPLAY_PBC, (char **) autoplay_modes, _("VCD default type to use on autoplay"), _("The VCD play unit to use when none is specified in an MRL, e.g. " "vcd:// or vcd:///dev/dvd:"), - 10, + 10, vcd_default_autoplay_cb, class); - - - class->vcd_device = - strdup (config->register_filename(config, + + + class->vcd_device = + strdup (config->register_filename(config, "media.vcd.device", "", XINE_CONFIG_STRING_IS_DEVICE_NAME, _("CD-ROM drive used for VCD when none given"), -_("What to use if no drive specified. If the setting is empty, xine will scan for CD drives."), +_("What to use if no drive specified. If the setting is empty, xine will scan for CD drives."), 20, - vcd_default_dev_changed_cb, + vcd_default_dev_changed_cb, (void *) class)); my_vcd.player.slider_length = - config->register_enum(config, + config->register_enum(config, "media.vcd.length_reporting", - VCDPLAYER_SLIDER_LENGTH_AUTO, + VCDPLAYER_SLIDER_LENGTH_AUTO, (char **) length_reporting_modes, _("VCD position slider range"), _("range that the stream playback position slider represents playing a VCD."), - 10, + 10, vcd_slider_length_cb, NULL); #if READAHEAD_FINISHED - my_vcd.player.readahead = + my_vcd.player.readahead = config->register_bool(config, "vcd.use_readahead", (int) false, _("VCD read-ahead caching?"), @@ -1873,29 +1871,29 @@ _("range that the stream playback position slider represents playing a VCD."), vcd_read_ahead_cb, NULL); #endif - my_vcd.player.autoadvance = - config->register_bool(config, + my_vcd.player.autoadvance = + config->register_bool(config, "media.vcd.autoadvance", (int) true, _("automatically advance VCD track/entry"), _("If enabled, we should automatically advance to the next entry or track. Used only when playback control (PBC) is disabled."), - 10, - vcd_autoadvance_cb, - NULL); + 10, + vcd_autoadvance_cb, + NULL); - my_vcd.player.show_rejected = - config->register_bool(config, + my_vcd.player.show_rejected = + config->register_bool(config, "media.vcd.show_rejected", (int) false, _("show 'rejected' VCD LIDs"), _("Some playback list IDs (LIDs) are marked not showable, " "but you can see them in the MRL list if this is set. Rejected entries " "are marked with an asterisk (*) appended to the MRL."), - 10, - vcd_show_rejected_cb, - NULL); + 10, + vcd_show_rejected_cb, + NULL); - my_vcd.v_config.title_format = + my_vcd.v_config.title_format = strdup(config->register_string(config, "media.vcd.title_format", "%F - %I %N%L%S, disk %c of %C - %v %A", @@ -1921,7 +1919,7 @@ _("VCD format used in the GUI Title. Similar to the Unix date " vcd_title_format_changed_cb, NULL)); - my_vcd.v_config.comment_format = + my_vcd.v_config.comment_format = strdup(config->register_string(config, "media.vcd.comment_format", "%P - Track %T", @@ -1934,8 +1932,8 @@ _("VCD format used in the GUI Title. Similar to the Unix date " vcd_comment_format_changed_cb, NULL)); - vcdplayer_debug = - config->register_num(config, + vcdplayer_debug = + config->register_num(config, "media.vcd.debug", 0, _("VCD debug flag mask"), @@ -1954,12 +1952,12 @@ _("For tracking down bugs in the VCD plugin. Mask values are:\n" "2048: Debugging from VCDINFO\n" ), 20, - vcd_debug_cb, - class); + vcd_debug_cb, + class); } - + gl_default_vcd_log_handler = vcd_log_set_handler (uninit_log_handler); - gl_default_cdio_log_handler = + gl_default_cdio_log_handler = cdio_log_set_handler ((cdio_log_handler_t) uninit_log_handler); my_vcd.input_plugin.open = vcd_plugin_open; @@ -1979,7 +1977,7 @@ _("For tracking down bugs in the VCD plugin. Mask values are:\n" my_vcd.class = class; my_vcd.i_mouse_button = -1; my_vcd.b_mouse_in = false; - + my_vcd.player.psz_source = NULL; my_vcd.player.b_opened = false; @@ -1991,11 +1989,11 @@ _("For tracking down bugs in the VCD plugin. Mask values are:\n" return class; } -/* +/* Exported plugin catalog entries. All plugins listing only the current API number break when the API - number is increased. This is by design. + number is increased. This is by design. Sometimes in the rush to get out a buggy release, the API number is increased without communication let alone a concern for whether it @@ -2012,13 +2010,13 @@ _("For tracking down bugs in the VCD plugin. Mask values are:\n" */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_INPUT | PLUGIN_MUST_PRELOAD, 17, (char *) SHORT_PLUGIN_NAME, XINE_VERSION_CODE, NULL, vcd_init }, { PLUGIN_NONE, 0, (char *) "", 0, NULL, NULL } }; -/* +/* * Local variables: * c-file-style: "gnu" * tab-width: 8 diff --git a/src/input/videodev2.h b/src/input/videodev2.h index ce32ec9eb..7863e454b 100644 --- a/src/input/videodev2.h +++ b/src/input/videodev2.h @@ -113,14 +113,14 @@ enum v4l2_field { transmitted first */ }; #define V4L2_FIELD_HAS_TOP(field) \ - ((field) == V4L2_FIELD_TOP ||\ + ((field) == V4L2_FIELD_TOP ||\ (field) == V4L2_FIELD_INTERLACED ||\ (field) == V4L2_FIELD_INTERLACED_TB ||\ (field) == V4L2_FIELD_INTERLACED_BT ||\ (field) == V4L2_FIELD_SEQ_TB ||\ (field) == V4L2_FIELD_SEQ_BT) #define V4L2_FIELD_HAS_BOTTOM(field) \ - ((field) == V4L2_FIELD_BOTTOM ||\ + ((field) == V4L2_FIELD_BOTTOM ||\ (field) == V4L2_FIELD_INTERLACED ||\ (field) == V4L2_FIELD_INTERLACED_TB ||\ (field) == V4L2_FIELD_INTERLACED_BT ||\ @@ -254,12 +254,12 @@ struct v4l2_capability */ struct v4l2_pix_format { - __u32 width; + __u32 width; __u32 height; __u32 pixelformat; - enum v4l2_field field; - __u32 bytesperline; /* for padding, zero if unused */ - __u32 sizeimage; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; enum v4l2_colorspace colorspace; __u32 priv; /* private data, depends on pixelformat */ }; @@ -542,7 +542,7 @@ struct v4l2_clip struct v4l2_window { struct v4l2_rect w; - enum v4l2_field field; + enum v4l2_field field; __u32 chromakey; struct v4l2_clip *clips; __u32 clipcount; @@ -660,7 +660,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ V4L2_STD_NTSC_M_JP |\ V4L2_STD_NTSC_M_KR) -#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ +#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ V4L2_STD_SECAM_K |\ V4L2_STD_SECAM_K1) #define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ @@ -784,7 +784,7 @@ struct v4l2_ext_controls #define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ #define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ -#define V4L2_CTRL_ID_MASK (0x0fffffff) +#define V4L2_CTRL_ID_MASK (0x0fffffff) #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) @@ -814,21 +814,21 @@ struct v4l2_querymenu /* Control flags */ #define V4L2_CTRL_FLAG_DISABLED 0x0001 #define V4L2_CTRL_FLAG_GRABBED 0x0002 -#define V4L2_CTRL_FLAG_READ_ONLY 0x0004 -#define V4L2_CTRL_FLAG_UPDATE 0x0008 -#define V4L2_CTRL_FLAG_INACTIVE 0x0010 -#define V4L2_CTRL_FLAG_SLIDER 0x0020 +#define V4L2_CTRL_FLAG_READ_ONLY 0x0004 +#define V4L2_CTRL_FLAG_UPDATE 0x0008 +#define V4L2_CTRL_FLAG_INACTIVE 0x0010 +#define V4L2_CTRL_FLAG_SLIDER 0x0020 /* Query flag, to be ORed with the control ID */ #define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 /* User-class control IDs defined by V4L2 */ #define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) -#define V4L2_CID_USER_BASE V4L2_CID_BASE +#define V4L2_CID_USER_BASE V4L2_CID_BASE /* IDs reserved for driver specific controls */ #define V4L2_CID_PRIVATE_BASE 0x08000000 -#define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) +#define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) #define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) #define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) #define V4L2_CID_SATURATION (V4L2_CID_BASE+2) @@ -856,11 +856,11 @@ struct v4l2_querymenu #define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ /* MPEG-class control IDs defined by V4L2 */ -#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) -#define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) +#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) +#define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) /* MPEG streams */ -#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) +#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) enum v4l2_mpeg_stream_type { V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ @@ -869,32 +869,32 @@ enum v4l2_mpeg_stream_type { V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible stream */ V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */ }; -#define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) -#define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) -#define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_MPEG_BASE+3) -#define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) -#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) -#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) -#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) +#define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) +#define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) +#define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_MPEG_BASE+3) +#define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) +#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) +#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) +#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) enum v4l2_mpeg_stream_vbi_fmt { V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, IVTV format */ }; /* MPEG audio */ -#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) +#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) enum v4l2_mpeg_audio_sampling_freq { V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, }; -#define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) +#define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) enum v4l2_mpeg_audio_encoding { V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, }; -#define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) +#define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) enum v4l2_mpeg_audio_l1_bitrate { V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, @@ -911,7 +911,7 @@ enum v4l2_mpeg_audio_l1_bitrate { V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, }; -#define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) +#define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) enum v4l2_mpeg_audio_l2_bitrate { V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, @@ -928,7 +928,7 @@ enum v4l2_mpeg_audio_l2_bitrate { V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, }; -#define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) +#define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) enum v4l2_mpeg_audio_l3_bitrate { V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, @@ -945,70 +945,70 @@ enum v4l2_mpeg_audio_l3_bitrate { V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, }; -#define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) +#define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) enum v4l2_mpeg_audio_mode { V4L2_MPEG_AUDIO_MODE_STEREO = 0, V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, V4L2_MPEG_AUDIO_MODE_DUAL = 2, V4L2_MPEG_AUDIO_MODE_MONO = 3, }; -#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) +#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) enum v4l2_mpeg_audio_mode_extension { V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, }; -#define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) +#define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) enum v4l2_mpeg_audio_emphasis { V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, }; -#define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) +#define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) enum v4l2_mpeg_audio_crc { V4L2_MPEG_AUDIO_CRC_NONE = 0, V4L2_MPEG_AUDIO_CRC_CRC16 = 1, }; -#define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) +#define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) /* MPEG video */ -#define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) +#define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) enum v4l2_mpeg_video_encoding { V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, }; -#define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) +#define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) enum v4l2_mpeg_video_aspect { V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, }; -#define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) -#define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) -#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_MPEG_BASE+204) -#define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) -#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) +#define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) +#define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) +#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_MPEG_BASE+204) +#define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) +#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) enum v4l2_mpeg_video_bitrate_mode { V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, }; -#define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) -#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) +#define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) +#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) #define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209) -#define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_MPEG_BASE+210) -#define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_MPEG_BASE+211) +#define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_MPEG_BASE+210) +#define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_MPEG_BASE+211) /* MPEG-class control IDs specific to the CX2584x driver as defined by V4L2 */ -#define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) -#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) +#define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, }; -#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) -#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, @@ -1016,18 +1016,18 @@ enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, }; -#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, }; -#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, }; -#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) -#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) +#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) enum v4l2_mpeg_cx2341x_video_median_filter_type { V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, @@ -1035,11 +1035,11 @@ enum v4l2_mpeg_cx2341x_video_median_filter_type { V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, }; -#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) -#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) #define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9) -#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) -#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) +#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) /* * T U N I N G @@ -1362,8 +1362,8 @@ struct v4l2_chip_ident { #define VIDIOC_S_CROP _IOW ('V', 60, struct v4l2_crop) #define VIDIOC_G_JPEGCOMP _IOR ('V', 61, struct v4l2_jpegcompression) #define VIDIOC_S_JPEGCOMP _IOW ('V', 62, struct v4l2_jpegcompression) -#define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id) -#define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format) +#define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id) +#define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format) #define VIDIOC_ENUMAUDIO _IOWR ('V', 65, struct v4l2_audio) #define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout) #define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority) @@ -1381,20 +1381,20 @@ struct v4l2_chip_ident { #define VIDIOC_TRY_ENCODER_CMD _IOWR ('V', 78, struct v4l2_encoder_cmd) /* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ -#define VIDIOC_DBG_S_REGISTER _IOW ('V', 79, struct v4l2_register) -#define VIDIOC_DBG_G_REGISTER _IOWR ('V', 80, struct v4l2_register) +#define VIDIOC_DBG_S_REGISTER _IOW ('V', 79, struct v4l2_register) +#define VIDIOC_DBG_G_REGISTER _IOWR ('V', 80, struct v4l2_register) #define VIDIOC_G_CHIP_IDENT _IOWR ('V', 81, struct v4l2_chip_ident) #endif #ifdef __OLD_VIDIOC_ /* for compatibility, will go away some day */ -#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) -#define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm) -#define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control) -#define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio) -#define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout) -#define VIDIOC_CROPCAP_OLD _IOR ('V', 58, struct v4l2_cropcap) +#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) +#define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm) +#define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control) +#define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio) +#define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout) +#define VIDIOC_CROPCAP_OLD _IOR ('V', 58, struct v4l2_cropcap) #endif #define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ diff --git a/src/liba52/Makefile.am b/src/liba52/Makefile.am index 508ea9c1b..b13170076 100644 --- a/src/liba52/Makefile.am +++ b/src/liba52/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common if A52 diff --git a/src/liba52/bit_allocate.c b/src/liba52/bit_allocate.c index 0567b2285..9da1661dc 100644 --- a/src/liba52/bit_allocate.c +++ b/src/liba52/bit_allocate.c @@ -100,7 +100,7 @@ static int8_t latab[256] = { 0, 0, 0, 0 }; -#define UPDATE_LEAK() \ +#define UPDATE_LEAK() \ do { \ fastleak += fdecay; \ if (fastleak > psd + fgain) \ diff --git a/src/liba52/bitstream.c b/src/liba52/bitstream.c index 04e8ca6d0..b645cb79f 100644 --- a/src/liba52/bitstream.c +++ b/src/liba52/bitstream.c @@ -88,7 +88,7 @@ int32_t a52_bitstream_get_bh_2 (a52_state_t * state, uint32_t num_bits) if (num_bits != 0) result = (result << num_bits) | (state->current_word >> (32 - num_bits)); - + state->bits_left = 32 - num_bits; return result; diff --git a/src/liba52/bitstream.h b/src/liba52/bitstream.h index f242c37c4..59f91cc0e 100644 --- a/src/liba52/bitstream.h +++ b/src/liba52/bitstream.h @@ -57,7 +57,7 @@ int32_t a52_bitstream_get_bh_2 (a52_state_t * state, uint32_t num_bits); static inline uint32_t bitstream_get (a52_state_t * state, uint32_t num_bits) { uint32_t result; - + if (num_bits < state->bits_left) { result = (state->current_word << (32 - state->bits_left)) >> (32 - num_bits); state->bits_left -= num_bits; @@ -70,7 +70,7 @@ static inline uint32_t bitstream_get (a52_state_t * state, uint32_t num_bits) static inline int32_t bitstream_get_2 (a52_state_t * state, uint32_t num_bits) { int32_t result; - + if (num_bits < state->bits_left) { result = (((int32_t)state->current_word) << (32 - state->bits_left)) >> (32 - num_bits); state->bits_left -= num_bits; diff --git a/src/liba52/crc.c b/src/liba52/crc.c index 38254c9ef..ac7666a90 100644 --- a/src/liba52/crc.c +++ b/src/liba52/crc.c @@ -1,23 +1,23 @@ -/* +/* * crc.c * * Copyright (C) Aaron Holtzman - May 1999 * * This file is part of ac3dec, a free Dolby AC-3 stream decoder. - * + * * ac3dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. - * + * * ac3dec is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ @@ -25,7 +25,7 @@ #include <stdio.h> #include <inttypes.h> -static const uint16_t crc_lut[256] = +static const uint16_t crc_lut[256] = { 0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011, 0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022, diff --git a/src/liba52/imdct.c b/src/liba52/imdct.c index 5835e70a1..672b54c2e 100644 --- a/src/liba52/imdct.c +++ b/src/liba52/imdct.c @@ -247,7 +247,7 @@ void a52_imdct_512 (sample_t * data, sample_t * delay, sample_t bias) sample_t t_r, t_i, a_r, a_i, b_r, b_i, w_1, w_2; const sample_t * window = a52_imdct_window; complex_t buf[128]; - + for (i = 0; i < 128; i++) { k = fftorder[i]; t_r = pre1[i].real; @@ -311,7 +311,7 @@ void a52_imdct_256(sample_t * data, sample_t * delay, sample_t bias) /* Post IFFT complex multiply */ /* Window and convert to real valued signal */ for (i = 0; i < 32; i++) { - /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */ + /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */ t_r = post2[i].real; t_i = post2[i].imag; diff --git a/src/liba52/parse.c b/src/liba52/parse.c index 0bfd02fce..c7531ec61 100644 --- a/src/liba52/parse.c +++ b/src/liba52/parse.c @@ -49,7 +49,7 @@ a52_state_t * a52_init (uint32_t mm_accel) a52_state_t * state; int i; - state = xine_xmalloc (sizeof (a52_state_t)); + state = calloc(1, sizeof (a52_state_t)); if (state == NULL) return NULL; @@ -253,7 +253,7 @@ static int parse_exponents (a52_state_t * state, int expstr, int ngrps, case EXP_D15: *(dest++) = exponent; } - } + } return 0; } @@ -301,7 +301,7 @@ static inline int16_t dither_gen (a52_state_t * state) int16_t nstate; nstate = dither_lut[state->lfsr_state >> 8] ^ (state->lfsr_state << 8); - + state->lfsr_state = (uint16_t) nstate; return nstate; @@ -631,7 +631,7 @@ int a52_block (a52_state_t * state) cplexpstr = bitstream_get (state, 2); for (i = 0; i < nfchans; i++) chexpstr[i] = bitstream_get (state, 2); - if (state->lfeon) + if (state->lfeon) lfeexpstr = bitstream_get (state, 1); for (i = 0; i < nfchans; i++) @@ -849,7 +849,7 @@ int a52_block (a52_state_t * state) if (blksw[i]) a52_imdct_256 (samples + 256 * i, samples + 1536 + 256 * i, bias); - else + else a52_imdct_512 (samples + 256 * i, samples + 1536 + 256 * i, bias); } else { @@ -878,7 +878,7 @@ int a52_block (a52_state_t * state) for (i = 0; i < nfchans; i++) a52_imdct_256 (samples + 256 * i, samples + 1536 + 256 * i, state->bias); - else + else for (i = 0; i < nfchans; i++) a52_imdct_512 (samples + 256 * i, samples + 1536 + 256 * i, state->bias); diff --git a/src/liba52/xine_a52_decoder.c b/src/liba52/xine_a52_decoder.c index b8b500ecd..9e590f77d 100644 --- a/src/liba52/xine_a52_decoder.c +++ b/src/liba52/xine_a52_decoder.c @@ -27,7 +27,7 @@ /* avoid compiler warnings */ #define _BSD_SOURCE 1 -#include <config.h> +#include "config.h" #include <stdlib.h> #include <unistd.h> @@ -72,11 +72,11 @@ int a52file; typedef struct { audio_decoder_class_t decoder_class; config_values_t *config; - + float a52_level; int disable_dynrng_compress; int enable_surround_downmix; - + } a52dec_class_t; typedef struct a52dec_decoder_s { @@ -221,7 +221,7 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, int64_t pts, int previe */ #ifdef LOG_PTS printf("a52dec:decode_frame:pts=%lld\n",pts); -#endif +#endif if (!this->bypass_mode) { int a52_output_flags, i; @@ -273,7 +273,7 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, int64_t pts, int previe this->stream->audio_out->close (this->stream->audio_out, this->stream); - this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, + this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, 16, this->a52_sample_rate, output_mode) ; @@ -297,13 +297,13 @@ static void a52dec_decode_frame (a52dec_decoder_t *this, int64_t pts, int previe for (i = 0; i < 6; i++) { if (a52_block (this->a52_state)) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "liba52: a52_block error on audio channel %d\n", i); -#if 0 +#if 0 for(n=0;n<2000;n++) { printf("%02x ",this->frame_buffer[n]); if ((n % 32) == 0) printf("\n"); } printf("\n"); -#endif +#endif buf->num_frames = 0; break; } @@ -457,7 +457,7 @@ static void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { * We call the start of an A52 frame a frame header. * So, if a A52 pack has 2 "Number of frame headers" is means that the A52 pack contains 2 A52 frame headers. * The "First access unit" then tells us which A52 frame the PTS value applies to. - * + * * Take the following example: - * PACK1: PTS = 10. Contains the entire A52 frame1, followed by the beginning of the frame2. PTS applies to frame1. * PACK2: PTS = 1000, Contains the rest of frame2, and the whole of frame3. and the start of frame4. PTS applies to frame4. @@ -579,14 +579,14 @@ static void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } } break; - + case 2: /* Filling frame_buffer with sync_info bytes */ *this->frame_ptr++ = *current++; this->frame_todo--; if (this->frame_todo < 1) { this->sync_state = 3; } else break; - + case 3: /* Ready for decode */ crc16 = (uint16_t) ((this->frame_buffer[2] << 8) | this->frame_buffer[3]) ; crc16_result = crc16_block(&this->frame_buffer[2], this->frame_length - 2) ; /* frame_length */ @@ -620,7 +620,7 @@ static void a52dec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->syncword = 0; this->sync_state = 0; break; - default: /* No come here */ + default: /* No come here */ break; } } @@ -654,7 +654,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre lprintf ("open_plugin called\n"); - this = (a52dec_decoder_t *) xine_xmalloc (sizeof (a52dec_decoder_t)); + this = calloc(1, sizeof (a52dec_decoder_t)); this->audio_decoder.decode_data = a52dec_decode_data; this->audio_decoder.reset = a52dec_reset; @@ -674,14 +674,14 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre this->pts_list_position = 0; if( !this->a52_state ) { - this->a52_state = + this->a52_state = #ifdef HAVE_A52DEC_A52_H /* External liba52 */ /* When using external liba52, enable _all_ capabilities, even if that might break stuff if they add some new capability that depends on CPU's caps. At the moment the only capability is DJBFFT, which is tested only if djbfft is being used at compile time. - + The actual question would be: why don't they check for capabilities themselves? */ @@ -806,7 +806,7 @@ static void *init_plugin (xine_t *xine, void *data) { a52dec_class_t *this; config_values_t *cfg; - this = (a52dec_class_t *) xine_xmalloc (sizeof (a52dec_class_t)); + this = calloc(1, sizeof (a52dec_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; diff --git a/src/libdts/Makefile.am b/src/libdts/Makefile.am index 1329dd49c..e5fafd80b 100644 --- a/src/libdts/Makefile.am +++ b/src/libdts/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common if DTS @@ -11,7 +12,7 @@ fnsa = internal_sources = else fnsa = -fno-strict-aliasing -internal_sources = bitstream.c downmix.c parse.c +internal_sources = bitstream.c downmix.c parse.c endif xineplug_decode_dts_la_SOURCES = xine_dts_decoder.c $(internal_sources) diff --git a/src/libdts/parse.c b/src/libdts/parse.c index 67067addb..d8f8267e7 100644 --- a/src/libdts/parse.c +++ b/src/libdts/parse.c @@ -769,7 +769,7 @@ static int dts_subsubframe (dts_state_t * state) */ /* Select quantization step size table */ - if (state->bit_rate == 0x1f) + if (state->bit_rate == 0x1f) quant_step_table = lossless_quant_d; else quant_step_table = lossy_quant_d; @@ -787,11 +787,11 @@ static int dts_subsubframe (dts_state_t * state) double rscale; /* - * Determine quantization index code book and its type + * Determine quantization index code book and its type */ /* Select quantization index code book */ - int sel = state->quant_index_huffman[k][abits]; + int sel = state->quant_index_huffman[k][abits]; /* Determine its type */ int q_type = 1; /* (Assume Huffman type by default) */ @@ -805,7 +805,7 @@ static int dts_subsubframe (dts_state_t * state) if (abits == 0) q_type = 0; /* No bits allocated */ /* - * Extract bits from the bit stream + * Extract bits from the bit stream */ switch (q_type) { @@ -942,7 +942,7 @@ static int dts_subsubframe (dts_state_t * state) for (m=0; m<8; m++) { - subband_samples[k][l][m] = + subband_samples[k][l][m] = high_freq_vq[state->high_freq_vq[k][l]][subsubframe*8+m] * (double)state->scale_factor[k][l][0] / 16.0; } @@ -1101,7 +1101,7 @@ int dts_block (dts_state_t * state) /* Very compact version of the block code decoder that does not use table * look-up but is slightly slower */ int decode_blockcode( int code, int levels, int *values ) -{ +{ int i; int offset = (levels - 1) >> 1; diff --git a/src/libdts/tables_huffman.h b/src/libdts/tables_huffman.h index 6690d356c..ec7aa3c9a 100644 --- a/src/libdts/tables_huffman.h +++ b/src/libdts/tables_huffman.h @@ -29,41 +29,41 @@ typedef struct huff_entry_s huff_entry_t bitalloc_a_12[] = { - { 1, 0, 1}, { 2, 2, 2}, { 3, 6, 3}, { 4, 14, 4}, - { 5, 30, 5}, { 6, 62, 6}, { 8, 255, 7}, { 8, 254, 8}, - { 9, 507, 9}, { 9, 506, 10}, { 9, 505, 11}, { 9, 504, 12}, + { 1, 0, 1}, { 2, 2, 2}, { 3, 6, 3}, { 4, 14, 4}, + { 5, 30, 5}, { 6, 62, 6}, { 8, 255, 7}, { 8, 254, 8}, + { 9, 507, 9}, { 9, 506, 10}, { 9, 505, 11}, { 9, 504, 12}, { 0, 0, 0} }; huff_entry_t bitalloc_b_12[] = { - { 1, 1, 1}, { 2, 0, 2}, { 3, 2, 3}, { 5, 15, 4}, - { 5, 12, 5}, { 6, 29, 6}, { 7, 57, 7}, { 7, 56, 8}, - { 7, 55, 9}, { 7, 54, 10}, { 7, 53, 11}, { 7, 52, 12}, - { 0, 0, 0} + { 1, 1, 1}, { 2, 0, 2}, { 3, 2, 3}, { 5, 15, 4}, + { 5, 12, 5}, { 6, 29, 6}, { 7, 57, 7}, { 7, 56, 8}, + { 7, 55, 9}, { 7, 54, 10}, { 7, 53, 11}, { 7, 52, 12}, + { 0, 0, 0} }; huff_entry_t bitalloc_c_12[] = { - { 2, 0, 1}, { 3, 7, 2}, { 3, 5, 3}, { 3, 4, 4}, - { 3, 2, 5}, { 4, 13, 6}, { 4, 12, 7}, { 4, 6, 8}, - { 5, 15, 9}, { 6, 29, 10}, { 7, 57, 11}, { 7, 56, 12}, + { 2, 0, 1}, { 3, 7, 2}, { 3, 5, 3}, { 3, 4, 4}, + { 3, 2, 5}, { 4, 13, 6}, { 4, 12, 7}, { 4, 6, 8}, + { 5, 15, 9}, { 6, 29, 10}, { 7, 57, 11}, { 7, 56, 12}, { 0, 0, 0} }; huff_entry_t bitalloc_d_12[] = { - { 2, 3, 1}, { 2, 2, 2}, { 2, 0, 3}, { 3, 2, 4}, - { 4, 6, 5}, { 5, 14, 6}, { 6, 30, 7}, { 7, 62, 8}, - { 8, 126, 9}, { 9, 254, 10}, {10, 511, 11}, {10, 510, 12}, + { 2, 3, 1}, { 2, 2, 2}, { 2, 0, 3}, { 3, 2, 4}, + { 4, 6, 5}, { 5, 14, 6}, { 6, 30, 7}, { 7, 62, 8}, + { 8, 126, 9}, { 9, 254, 10}, {10, 511, 11}, {10, 510, 12}, { 0, 0, 0} }; huff_entry_t bitalloc_e_12[] = { - { 1, 1, 1}, { 2, 0, 2}, { 3, 2, 3}, { 4, 6, 4}, - { 5, 14, 5}, { 7, 63, 6}, { 7, 61, 7}, { 8, 124, 8}, - { 8, 121, 9}, { 8, 120, 10}, { 9, 251, 11}, { 9, 250, 12}, + { 1, 1, 1}, { 2, 0, 2}, { 3, 2, 3}, { 4, 6, 4}, + { 5, 14, 5}, { 7, 63, 6}, { 7, 61, 7}, { 8, 124, 8}, + { 8, 121, 9}, { 8, 120, 10}, { 9, 251, 11}, { 9, 250, 12}, { 0, 0, 0} }; @@ -78,186 +78,186 @@ huff_entry_t *bitalloc_12[] = huff_entry_t scales_a_129[] = { - { 2, 1, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 0, 2}, - { 4, 15, -2}, { 4, 8, 3}, { 4, 3, -3}, { 5, 28, 4}, - { 5, 19, -4}, { 5, 4, 5}, { 6, 59, -5}, { 6, 36, 6}, - { 6, 11, -6}, { 7, 75, 7}, { 7, 74, -7}, { 8, 233, 8}, - { 8, 232, -8}, { 8, 41, 9}, { 8, 40, -9}, { 9, 87, 10}, - { 9, 86,-10}, {10, 937, 11}, {10, 936,-11}, {11, 1877, 12}, - {11, 1876,-12}, {11, 341, 13}, {11, 340,-13}, {12, 686, 14}, - {12, 685,-14}, {13, 1375, 15}, {13, 1374,-15}, {13, 1369, 16}, - {13, 1368,-16}, {13, 1359, 17}, {13, 1358,-17}, {13, 1357, 18}, - {13, 1356,-18}, {13, 1355, 19}, {13, 1354,-19}, {13, 1353, 20}, - {13, 1352,-20}, {13, 1351, 21}, {13, 1350,-21}, {13, 1349, 22}, - {13, 1348,-22}, {13, 1347, 23}, {13, 1346,-23}, {13, 1345, 24}, - {13, 1344,-24}, {14, 15103, 25}, {14, 15102,-25}, {14, 15101, 26}, - {14, 15100,-26}, {14, 15099, 27}, {14, 15098,-27}, {14, 15097, 28}, - {14, 15096,-28}, {14, 15095, 29}, {14, 15094,-29}, {14, 15093, 30}, - {14, 15092,-30}, {14, 15091, 31}, {14, 15090,-31}, {14, 15089, 32}, - {14, 15088,-32}, {14, 15087, 33}, {14, 15086,-33}, {14, 15085, 34}, - {14, 15084,-34}, {14, 15083, 35}, {14, 15082,-35}, {14, 15081, 36}, - {14, 15080,-36}, {14, 15079, 37}, {14, 15078,-37}, {14, 15077, 38}, - {14, 15076,-38}, {14, 15075, 39}, {14, 15074,-39}, {14, 15073, 40}, - {14, 15072,-40}, {14, 15071, 41}, {14, 15070,-41}, {14, 15069, 42}, - {14, 15068,-42}, {14, 15067, 43}, {14, 15066,-43}, {14, 15065, 44}, - {14, 15064,-44}, {14, 15063, 45}, {14, 15062,-45}, {14, 15061, 46}, - {14, 15060,-46}, {14, 15059, 47}, {14, 15058,-47}, {14, 15057, 48}, - {14, 15056,-48}, {14, 15055, 49}, {14, 15054,-49}, {14, 15053, 50}, - {14, 15052,-50}, {14, 15051, 51}, {14, 15050,-51}, {14, 15049, 52}, - {14, 15048,-52}, {14, 15047, 53}, {14, 15046,-53}, {14, 15045, 54}, - {14, 15044,-54}, {14, 15043, 55}, {14, 15042,-55}, {14, 15041, 56}, - {14, 15040,-56}, {14, 15039, 57}, {14, 15038,-57}, {14, 15037, 58}, - {14, 15036,-58}, {14, 15035, 59}, {14, 15034,-59}, {14, 15033, 60}, - {14, 15032,-60}, {14, 15031, 61}, {14, 15030,-61}, {14, 15029, 62}, - {14, 15028,-62}, {14, 15027, 63}, {14, 15026,-63}, {14, 15025, 64}, + { 2, 1, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 0, 2}, + { 4, 15, -2}, { 4, 8, 3}, { 4, 3, -3}, { 5, 28, 4}, + { 5, 19, -4}, { 5, 4, 5}, { 6, 59, -5}, { 6, 36, 6}, + { 6, 11, -6}, { 7, 75, 7}, { 7, 74, -7}, { 8, 233, 8}, + { 8, 232, -8}, { 8, 41, 9}, { 8, 40, -9}, { 9, 87, 10}, + { 9, 86,-10}, {10, 937, 11}, {10, 936,-11}, {11, 1877, 12}, + {11, 1876,-12}, {11, 341, 13}, {11, 340,-13}, {12, 686, 14}, + {12, 685,-14}, {13, 1375, 15}, {13, 1374,-15}, {13, 1369, 16}, + {13, 1368,-16}, {13, 1359, 17}, {13, 1358,-17}, {13, 1357, 18}, + {13, 1356,-18}, {13, 1355, 19}, {13, 1354,-19}, {13, 1353, 20}, + {13, 1352,-20}, {13, 1351, 21}, {13, 1350,-21}, {13, 1349, 22}, + {13, 1348,-22}, {13, 1347, 23}, {13, 1346,-23}, {13, 1345, 24}, + {13, 1344,-24}, {14, 15103, 25}, {14, 15102,-25}, {14, 15101, 26}, + {14, 15100,-26}, {14, 15099, 27}, {14, 15098,-27}, {14, 15097, 28}, + {14, 15096,-28}, {14, 15095, 29}, {14, 15094,-29}, {14, 15093, 30}, + {14, 15092,-30}, {14, 15091, 31}, {14, 15090,-31}, {14, 15089, 32}, + {14, 15088,-32}, {14, 15087, 33}, {14, 15086,-33}, {14, 15085, 34}, + {14, 15084,-34}, {14, 15083, 35}, {14, 15082,-35}, {14, 15081, 36}, + {14, 15080,-36}, {14, 15079, 37}, {14, 15078,-37}, {14, 15077, 38}, + {14, 15076,-38}, {14, 15075, 39}, {14, 15074,-39}, {14, 15073, 40}, + {14, 15072,-40}, {14, 15071, 41}, {14, 15070,-41}, {14, 15069, 42}, + {14, 15068,-42}, {14, 15067, 43}, {14, 15066,-43}, {14, 15065, 44}, + {14, 15064,-44}, {14, 15063, 45}, {14, 15062,-45}, {14, 15061, 46}, + {14, 15060,-46}, {14, 15059, 47}, {14, 15058,-47}, {14, 15057, 48}, + {14, 15056,-48}, {14, 15055, 49}, {14, 15054,-49}, {14, 15053, 50}, + {14, 15052,-50}, {14, 15051, 51}, {14, 15050,-51}, {14, 15049, 52}, + {14, 15048,-52}, {14, 15047, 53}, {14, 15046,-53}, {14, 15045, 54}, + {14, 15044,-54}, {14, 15043, 55}, {14, 15042,-55}, {14, 15041, 56}, + {14, 15040,-56}, {14, 15039, 57}, {14, 15038,-57}, {14, 15037, 58}, + {14, 15036,-58}, {14, 15035, 59}, {14, 15034,-59}, {14, 15033, 60}, + {14, 15032,-60}, {14, 15031, 61}, {14, 15030,-61}, {14, 15029, 62}, + {14, 15028,-62}, {14, 15027, 63}, {14, 15026,-63}, {14, 15025, 64}, {14, 15024,-64}, { 0, 0, 0} }; huff_entry_t scales_b_129[] = { - { 3, 3, 0}, { 3, 2, 1}, { 3, 1, -1}, { 4, 15, 2}, - { 4, 14, -2}, { 4, 12, 3}, { 4, 11, -3}, { 4, 10, 4}, - { 4, 9, -4}, { 4, 0, 5}, { 5, 27, -5}, { 5, 17, 6}, - { 5, 16, -6}, { 6, 53, 7}, { 6, 52, -7}, { 6, 5, 8}, - { 6, 4, -8}, { 7, 13, 9}, { 7, 12, -9}, { 8, 29, 10}, - { 8, 28,-10}, { 9, 60, 11}, {10, 127,-11}, {11, 253, 12}, - {11, 252,-12}, {12, 491, 13}, {12, 490,-13}, {13, 979, 14}, - {13, 978,-14}, {14, 1955, 15}, {14, 1954,-15}, {14, 1953, 16}, - {14, 1952,-16}, {15, 4031, 17}, {15, 4030,-17}, {15, 4029, 18}, - {15, 4028,-18}, {15, 4027, 19}, {15, 4026,-19}, {15, 4025, 20}, - {15, 4024,-20}, {15, 4023, 21}, {15, 4022,-21}, {15, 4021, 22}, - {15, 4020,-22}, {15, 4019, 23}, {15, 4018,-23}, {15, 4017, 24}, - {15, 4016,-24}, {15, 4015, 25}, {15, 4014,-25}, {15, 4013, 26}, - {15, 4012,-26}, {15, 4011, 27}, {15, 4010,-27}, {15, 4009, 28}, - {15, 4008,-28}, {15, 4007, 29}, {15, 4006,-29}, {15, 4005, 30}, - {15, 4004,-30}, {15, 4003, 31}, {15, 4002,-31}, {15, 4001, 32}, - {15, 4000,-32}, {15, 3999, 33}, {15, 3998,-33}, {15, 3997, 34}, - {15, 3996,-34}, {15, 3995, 35}, {15, 3994,-35}, {15, 3993, 36}, - {15, 3992,-36}, {15, 3991, 37}, {15, 3990,-37}, {15, 3989, 38}, - {15, 3988,-38}, {15, 3987, 39}, {15, 3986,-39}, {15, 3985, 40}, - {15, 3984,-40}, {15, 3983, 41}, {15, 3982,-41}, {15, 3981, 42}, - {15, 3980,-42}, {15, 3979, 43}, {15, 3978,-43}, {15, 3977, 44}, - {15, 3976,-44}, {15, 3975, 45}, {15, 3974,-45}, {15, 3973, 46}, - {15, 3972,-46}, {15, 3971, 47}, {15, 3970,-47}, {15, 3969, 48}, - {15, 3968,-48}, {15, 3967, 49}, {15, 3966,-49}, {15, 3965, 50}, - {15, 3964,-50}, {15, 3963, 51}, {15, 3962,-51}, {15, 3961, 52}, - {15, 3960,-52}, {15, 3959, 53}, {15, 3958,-53}, {15, 3957, 54}, - {15, 3956,-54}, {15, 3955, 55}, {15, 3954,-55}, {15, 3953, 56}, - {15, 3952,-56}, {15, 3951, 57}, {15, 3950,-57}, {15, 3949, 58}, - {15, 3948,-58}, {15, 3947, 59}, {15, 3946,-59}, {15, 3945, 60}, - {15, 3944,-60}, {15, 3943, 61}, {15, 3942,-61}, {15, 3941, 62}, - {15, 3940,-62}, {15, 3939, 63}, {15, 3938,-63}, {15, 3937, 64}, + { 3, 3, 0}, { 3, 2, 1}, { 3, 1, -1}, { 4, 15, 2}, + { 4, 14, -2}, { 4, 12, 3}, { 4, 11, -3}, { 4, 10, 4}, + { 4, 9, -4}, { 4, 0, 5}, { 5, 27, -5}, { 5, 17, 6}, + { 5, 16, -6}, { 6, 53, 7}, { 6, 52, -7}, { 6, 5, 8}, + { 6, 4, -8}, { 7, 13, 9}, { 7, 12, -9}, { 8, 29, 10}, + { 8, 28,-10}, { 9, 60, 11}, {10, 127,-11}, {11, 253, 12}, + {11, 252,-12}, {12, 491, 13}, {12, 490,-13}, {13, 979, 14}, + {13, 978,-14}, {14, 1955, 15}, {14, 1954,-15}, {14, 1953, 16}, + {14, 1952,-16}, {15, 4031, 17}, {15, 4030,-17}, {15, 4029, 18}, + {15, 4028,-18}, {15, 4027, 19}, {15, 4026,-19}, {15, 4025, 20}, + {15, 4024,-20}, {15, 4023, 21}, {15, 4022,-21}, {15, 4021, 22}, + {15, 4020,-22}, {15, 4019, 23}, {15, 4018,-23}, {15, 4017, 24}, + {15, 4016,-24}, {15, 4015, 25}, {15, 4014,-25}, {15, 4013, 26}, + {15, 4012,-26}, {15, 4011, 27}, {15, 4010,-27}, {15, 4009, 28}, + {15, 4008,-28}, {15, 4007, 29}, {15, 4006,-29}, {15, 4005, 30}, + {15, 4004,-30}, {15, 4003, 31}, {15, 4002,-31}, {15, 4001, 32}, + {15, 4000,-32}, {15, 3999, 33}, {15, 3998,-33}, {15, 3997, 34}, + {15, 3996,-34}, {15, 3995, 35}, {15, 3994,-35}, {15, 3993, 36}, + {15, 3992,-36}, {15, 3991, 37}, {15, 3990,-37}, {15, 3989, 38}, + {15, 3988,-38}, {15, 3987, 39}, {15, 3986,-39}, {15, 3985, 40}, + {15, 3984,-40}, {15, 3983, 41}, {15, 3982,-41}, {15, 3981, 42}, + {15, 3980,-42}, {15, 3979, 43}, {15, 3978,-43}, {15, 3977, 44}, + {15, 3976,-44}, {15, 3975, 45}, {15, 3974,-45}, {15, 3973, 46}, + {15, 3972,-46}, {15, 3971, 47}, {15, 3970,-47}, {15, 3969, 48}, + {15, 3968,-48}, {15, 3967, 49}, {15, 3966,-49}, {15, 3965, 50}, + {15, 3964,-50}, {15, 3963, 51}, {15, 3962,-51}, {15, 3961, 52}, + {15, 3960,-52}, {15, 3959, 53}, {15, 3958,-53}, {15, 3957, 54}, + {15, 3956,-54}, {15, 3955, 55}, {15, 3954,-55}, {15, 3953, 56}, + {15, 3952,-56}, {15, 3951, 57}, {15, 3950,-57}, {15, 3949, 58}, + {15, 3948,-58}, {15, 3947, 59}, {15, 3946,-59}, {15, 3945, 60}, + {15, 3944,-60}, {15, 3943, 61}, {15, 3942,-61}, {15, 3941, 62}, + {15, 3940,-62}, {15, 3939, 63}, {15, 3938,-63}, {15, 3937, 64}, {15, 3936,-64}, { 0, 0, 0} }; huff_entry_t scales_c_129[] = { - { 3, 4, 0}, { 3, 1, 1}, { 3, 0, -1}, { 4, 13, 2}, - { 4, 12, -2}, { 4, 7, 3}, { 4, 6, -3}, { 5, 31, 4}, - { 5, 30, -4}, { 5, 23, 5}, { 5, 22, -5}, { 5, 11, 6}, - { 5, 10, -6}, { 6, 59, 7}, { 6, 58, -7}, { 6, 43, 8}, - { 6, 42, -8}, { 6, 19, 9}, { 6, 18, -9}, { 7, 115, 10}, - { 7, 114,-10}, { 7, 83, 11}, { 7, 82,-11}, { 7, 35, 12}, - { 7, 34,-12}, { 8, 227, 13}, { 8, 226,-13}, { 8, 162, 14}, - { 8, 161,-14}, { 8, 66, 15}, { 8, 65,-15}, { 9, 450, 16}, - { 9, 449,-16}, { 9, 321, 17}, { 9, 320,-17}, { 9, 129, 18}, - { 9, 128,-18}, {10, 897, 19}, {10, 896,-19}, {10, 652, 20}, - {10, 271,-20}, {10, 268, 21}, {11, 1807,-21}, {11, 1308, 22}, - {11, 1307,-22}, {11, 540, 23}, {11, 539,-23}, {12, 3612, 24}, - {12, 3611,-24}, {12, 2613, 25}, {12, 2612,-25}, {12, 1077, 26}, - {12, 1076,-26}, {13, 7226, 27}, {13, 7221,-27}, {13, 2167, 28}, - {13, 2166,-28}, {13, 2164, 29}, {14, 14455,-29}, {14, 14441, 30}, - {14, 14440,-30}, {14, 4331, 31}, {14, 4330,-31}, {15, 28909, 32}, - {15, 28908,-32}, {15, 28879, 33}, {15, 28878,-33}, {15, 28877, 34}, - {15, 28876,-34}, {15, 28875, 35}, {15, 28874,-35}, {15, 28873, 36}, - {15, 28872,-36}, {15, 28871, 37}, {15, 28870,-37}, {15, 28869, 38}, - {15, 28868,-38}, {15, 28867, 39}, {15, 28866,-39}, {15, 28865, 40}, - {15, 28864,-40}, {15, 20991, 41}, {15, 20990,-41}, {15, 20989, 42}, - {15, 20988,-42}, {15, 20987, 43}, {15, 20986,-43}, {15, 20985, 44}, - {15, 20984,-44}, {15, 20983, 45}, {15, 20982,-45}, {15, 20981, 46}, - {15, 20980,-46}, {15, 20979, 47}, {15, 20978,-47}, {15, 20977, 48}, - {15, 20976,-48}, {15, 20975, 49}, {15, 20974,-49}, {15, 20973, 50}, - {15, 20972,-50}, {15, 20971, 51}, {15, 20970,-51}, {15, 20969, 52}, - {15, 20968,-52}, {15, 20967, 53}, {15, 20966,-53}, {15, 20965, 54}, - {15, 20964,-54}, {15, 20963, 55}, {15, 20962,-55}, {15, 20961, 56}, - {15, 20960,-56}, {15, 20959, 57}, {15, 20958,-57}, {15, 20957, 58}, - {15, 20956,-58}, {15, 20955, 59}, {15, 20954,-59}, {15, 20953, 60}, - {15, 20952,-60}, {15, 20951, 61}, {15, 20950,-61}, {15, 20949, 62}, - {15, 20948,-62}, {15, 20947, 63}, {15, 20946,-63}, {15, 20945, 64}, + { 3, 4, 0}, { 3, 1, 1}, { 3, 0, -1}, { 4, 13, 2}, + { 4, 12, -2}, { 4, 7, 3}, { 4, 6, -3}, { 5, 31, 4}, + { 5, 30, -4}, { 5, 23, 5}, { 5, 22, -5}, { 5, 11, 6}, + { 5, 10, -6}, { 6, 59, 7}, { 6, 58, -7}, { 6, 43, 8}, + { 6, 42, -8}, { 6, 19, 9}, { 6, 18, -9}, { 7, 115, 10}, + { 7, 114,-10}, { 7, 83, 11}, { 7, 82,-11}, { 7, 35, 12}, + { 7, 34,-12}, { 8, 227, 13}, { 8, 226,-13}, { 8, 162, 14}, + { 8, 161,-14}, { 8, 66, 15}, { 8, 65,-15}, { 9, 450, 16}, + { 9, 449,-16}, { 9, 321, 17}, { 9, 320,-17}, { 9, 129, 18}, + { 9, 128,-18}, {10, 897, 19}, {10, 896,-19}, {10, 652, 20}, + {10, 271,-20}, {10, 268, 21}, {11, 1807,-21}, {11, 1308, 22}, + {11, 1307,-22}, {11, 540, 23}, {11, 539,-23}, {12, 3612, 24}, + {12, 3611,-24}, {12, 2613, 25}, {12, 2612,-25}, {12, 1077, 26}, + {12, 1076,-26}, {13, 7226, 27}, {13, 7221,-27}, {13, 2167, 28}, + {13, 2166,-28}, {13, 2164, 29}, {14, 14455,-29}, {14, 14441, 30}, + {14, 14440,-30}, {14, 4331, 31}, {14, 4330,-31}, {15, 28909, 32}, + {15, 28908,-32}, {15, 28879, 33}, {15, 28878,-33}, {15, 28877, 34}, + {15, 28876,-34}, {15, 28875, 35}, {15, 28874,-35}, {15, 28873, 36}, + {15, 28872,-36}, {15, 28871, 37}, {15, 28870,-37}, {15, 28869, 38}, + {15, 28868,-38}, {15, 28867, 39}, {15, 28866,-39}, {15, 28865, 40}, + {15, 28864,-40}, {15, 20991, 41}, {15, 20990,-41}, {15, 20989, 42}, + {15, 20988,-42}, {15, 20987, 43}, {15, 20986,-43}, {15, 20985, 44}, + {15, 20984,-44}, {15, 20983, 45}, {15, 20982,-45}, {15, 20981, 46}, + {15, 20980,-46}, {15, 20979, 47}, {15, 20978,-47}, {15, 20977, 48}, + {15, 20976,-48}, {15, 20975, 49}, {15, 20974,-49}, {15, 20973, 50}, + {15, 20972,-50}, {15, 20971, 51}, {15, 20970,-51}, {15, 20969, 52}, + {15, 20968,-52}, {15, 20967, 53}, {15, 20966,-53}, {15, 20965, 54}, + {15, 20964,-54}, {15, 20963, 55}, {15, 20962,-55}, {15, 20961, 56}, + {15, 20960,-56}, {15, 20959, 57}, {15, 20958,-57}, {15, 20957, 58}, + {15, 20956,-58}, {15, 20955, 59}, {15, 20954,-59}, {15, 20953, 60}, + {15, 20952,-60}, {15, 20951, 61}, {15, 20950,-61}, {15, 20949, 62}, + {15, 20948,-62}, {15, 20947, 63}, {15, 20946,-63}, {15, 20945, 64}, {15, 20944,-64}, { 0, 0, 0} }; huff_entry_t scales_d_129[] = { - { 2, 0, 0}, { 3, 5, 1}, { 3, 4, -1}, { 4, 15, 2}, - { 4, 14, -2}, { 4, 7, 3}, { 4, 6, -3}, { 5, 26, 4}, - { 5, 25, -4}, { 5, 10, 5}, { 5, 9, -5}, { 6, 54, 6}, - { 6, 49, -6}, { 6, 22, 7}, { 6, 17, -7}, { 7, 110, 8}, - { 7, 97, -8}, { 7, 46, 9}, { 7, 33, -9}, { 8, 193, 10}, - { 8, 192,-10}, { 8, 65, 11}, { 8, 64,-11}, { 9, 444, 12}, - { 9, 191,-12}, { 9, 188, 13}, {10, 895,-13}, {10, 890, 14}, - {10, 381,-14}, {10, 378, 15}, {11, 1789,-15}, {11, 761, 16}, - {11, 760,-16}, {12, 3577, 17}, {12, 3576,-17}, {12, 1519, 18}, - {12, 1518,-18}, {12, 1516, 19}, {13, 7151,-19}, {13, 7128, 20}, - {13, 3035,-20}, {14, 14301, 21}, {14, 14300,-21}, {14, 6069, 22}, - {14, 6068,-22}, {15, 28599, 23}, {15, 28598,-23}, {15, 28597, 24}, - {15, 28596,-24}, {15, 28595, 25}, {15, 28594,-25}, {15, 28593, 26}, - {15, 28592,-26}, {15, 28591, 27}, {15, 28590,-27}, {15, 28589, 28}, - {15, 28588,-28}, {15, 28587, 29}, {15, 28586,-29}, {15, 28585, 30}, - {15, 28584,-30}, {15, 28583, 31}, {15, 28582,-31}, {15, 28581, 32}, - {15, 28580,-32}, {15, 28579, 33}, {15, 28578,-33}, {15, 28577, 34}, - {15, 28576,-34}, {15, 28575, 35}, {15, 28574,-35}, {15, 28573, 36}, - {15, 28572,-36}, {15, 28571, 37}, {15, 28570,-37}, {15, 28569, 38}, - {15, 28568,-38}, {15, 28567, 39}, {15, 28566,-39}, {15, 28565, 40}, - {15, 28564,-40}, {15, 28563, 41}, {15, 28562,-41}, {15, 28561, 42}, - {15, 28560,-42}, {15, 28559, 43}, {15, 28558,-43}, {15, 28557, 44}, - {15, 28556,-44}, {15, 28555, 45}, {15, 28554,-45}, {15, 28553, 46}, - {15, 28552,-46}, {15, 28551, 47}, {15, 28550,-47}, {15, 28549, 48}, - {15, 28548,-48}, {15, 28547, 49}, {15, 28546,-49}, {15, 28545, 50}, - {15, 28544,-50}, {15, 28543, 51}, {15, 28542,-51}, {15, 28541, 52}, - {15, 28540,-52}, {15, 28539, 53}, {15, 28538,-53}, {15, 28537, 54}, - {15, 28536,-54}, {15, 28535, 55}, {15, 28534,-55}, {15, 28533, 56}, - {15, 28532,-56}, {15, 28531, 57}, {15, 28530,-57}, {15, 28529, 58}, - {15, 28528,-58}, {15, 28527, 59}, {15, 28526,-59}, {15, 28525, 60}, - {15, 28524,-60}, {15, 28523, 61}, {15, 28522,-61}, {15, 28521, 62}, - {15, 28520,-62}, {15, 28519, 63}, {15, 28518,-63}, {15, 28517, 64}, + { 2, 0, 0}, { 3, 5, 1}, { 3, 4, -1}, { 4, 15, 2}, + { 4, 14, -2}, { 4, 7, 3}, { 4, 6, -3}, { 5, 26, 4}, + { 5, 25, -4}, { 5, 10, 5}, { 5, 9, -5}, { 6, 54, 6}, + { 6, 49, -6}, { 6, 22, 7}, { 6, 17, -7}, { 7, 110, 8}, + { 7, 97, -8}, { 7, 46, 9}, { 7, 33, -9}, { 8, 193, 10}, + { 8, 192,-10}, { 8, 65, 11}, { 8, 64,-11}, { 9, 444, 12}, + { 9, 191,-12}, { 9, 188, 13}, {10, 895,-13}, {10, 890, 14}, + {10, 381,-14}, {10, 378, 15}, {11, 1789,-15}, {11, 761, 16}, + {11, 760,-16}, {12, 3577, 17}, {12, 3576,-17}, {12, 1519, 18}, + {12, 1518,-18}, {12, 1516, 19}, {13, 7151,-19}, {13, 7128, 20}, + {13, 3035,-20}, {14, 14301, 21}, {14, 14300,-21}, {14, 6069, 22}, + {14, 6068,-22}, {15, 28599, 23}, {15, 28598,-23}, {15, 28597, 24}, + {15, 28596,-24}, {15, 28595, 25}, {15, 28594,-25}, {15, 28593, 26}, + {15, 28592,-26}, {15, 28591, 27}, {15, 28590,-27}, {15, 28589, 28}, + {15, 28588,-28}, {15, 28587, 29}, {15, 28586,-29}, {15, 28585, 30}, + {15, 28584,-30}, {15, 28583, 31}, {15, 28582,-31}, {15, 28581, 32}, + {15, 28580,-32}, {15, 28579, 33}, {15, 28578,-33}, {15, 28577, 34}, + {15, 28576,-34}, {15, 28575, 35}, {15, 28574,-35}, {15, 28573, 36}, + {15, 28572,-36}, {15, 28571, 37}, {15, 28570,-37}, {15, 28569, 38}, + {15, 28568,-38}, {15, 28567, 39}, {15, 28566,-39}, {15, 28565, 40}, + {15, 28564,-40}, {15, 28563, 41}, {15, 28562,-41}, {15, 28561, 42}, + {15, 28560,-42}, {15, 28559, 43}, {15, 28558,-43}, {15, 28557, 44}, + {15, 28556,-44}, {15, 28555, 45}, {15, 28554,-45}, {15, 28553, 46}, + {15, 28552,-46}, {15, 28551, 47}, {15, 28550,-47}, {15, 28549, 48}, + {15, 28548,-48}, {15, 28547, 49}, {15, 28546,-49}, {15, 28545, 50}, + {15, 28544,-50}, {15, 28543, 51}, {15, 28542,-51}, {15, 28541, 52}, + {15, 28540,-52}, {15, 28539, 53}, {15, 28538,-53}, {15, 28537, 54}, + {15, 28536,-54}, {15, 28535, 55}, {15, 28534,-55}, {15, 28533, 56}, + {15, 28532,-56}, {15, 28531, 57}, {15, 28530,-57}, {15, 28529, 58}, + {15, 28528,-58}, {15, 28527, 59}, {15, 28526,-59}, {15, 28525, 60}, + {15, 28524,-60}, {15, 28523, 61}, {15, 28522,-61}, {15, 28521, 62}, + {15, 28520,-62}, {15, 28519, 63}, {15, 28518,-63}, {15, 28517, 64}, {15, 28516,-64}, { 0, 0, 0} }; huff_entry_t scales_e_129[] = { - { 4, 14, 0}, { 4, 11, 1}, { 4, 10, -1}, { 4, 7, 2}, - { 4, 6, -2}, { 4, 3, 3}, { 4, 2, -3}, { 5, 31, 4}, - { 5, 30, -4}, { 5, 25, 5}, { 5, 24, -5}, { 5, 17, 6}, - { 5, 16, -6}, { 5, 9, 7}, { 5, 8, -7}, { 5, 1, 8}, - { 5, 0, -8}, { 6, 53, 9}, { 6, 52, -9}, { 6, 37, 10}, - { 6, 36,-10}, { 6, 21, 11}, { 6, 20,-11}, { 6, 5, 12}, - { 6, 4,-12}, { 7, 109, 13}, { 7, 108,-13}, { 7, 77, 14}, - { 7, 76,-14}, { 7, 45, 15}, { 7, 44,-15}, { 7, 13, 16}, - { 7, 12,-16}, { 8, 221, 17}, { 8, 220,-17}, { 8, 157, 18}, - { 8, 156,-18}, { 8, 93, 19}, { 8, 92,-19}, { 8, 29, 20}, - { 8, 28,-20}, { 9, 445, 21}, { 9, 444,-21}, { 9, 317, 22}, - { 9, 316,-22}, { 9, 189, 23}, { 9, 188,-23}, { 9, 61, 24}, - { 9, 60,-24}, {10, 892, 25}, {10, 639,-25}, {10, 637, 26}, - {10, 636,-26}, {10, 381, 27}, {10, 380,-27}, {10, 125, 28}, - {10, 124,-28}, {11, 1788, 29}, {11, 1787,-29}, {11, 1276, 30}, - {11, 767,-30}, {11, 764, 31}, {11, 255,-31}, {11, 252, 32}, - {12, 3583,-32}, {12, 3579, 33}, {12, 3578,-33}, {12, 2555, 34}, - {12, 2554,-34}, {12, 1531, 35}, {12, 1530,-35}, {12, 507, 36}, - {12, 506,-36}, {13, 7160, 37}, {13, 7147,-37}, {13, 7144, 38}, - {13, 3067,-38}, {13, 3065, 39}, {13, 3064,-39}, {13, 1017, 40}, - {13, 1016,-40}, {14, 14330, 41}, {14, 14329,-41}, {14, 14291, 42}, - {14, 14290,-42}, {14, 6132, 43}, {14, 2039,-43}, {14, 2038, 44}, - {14, 2037,-44}, {15, 28663, 45}, {15, 28662,-45}, {15, 28585, 46}, - {15, 28584,-46}, {15, 12267, 47}, {15, 12266,-47}, {15, 4073, 48}, - {15, 4072,-48}, {16, 57315, 49}, {16, 57314,-49}, {16, 57313, 50}, - {16, 57312,-50}, {16, 57311, 51}, {16, 57310,-51}, {16, 57309, 52}, - {16, 57308,-52}, {16, 57307, 53}, {16, 57306,-53}, {16, 57305, 54}, - {16, 57304,-54}, {16, 57303, 55}, {16, 57302,-55}, {16, 57301, 56}, - {16, 57300,-56}, {16, 57299, 57}, {16, 57298,-57}, {16, 57297, 58}, - {16, 57296,-58}, {16, 57295, 59}, {16, 57294,-59}, {16, 57293, 60}, - {16, 57292,-60}, {16, 57291, 61}, {16, 57290,-61}, {16, 57289, 62}, - {16, 57288,-62}, {16, 57175, 63}, {16, 57174,-63}, {16, 57173, 64}, + { 4, 14, 0}, { 4, 11, 1}, { 4, 10, -1}, { 4, 7, 2}, + { 4, 6, -2}, { 4, 3, 3}, { 4, 2, -3}, { 5, 31, 4}, + { 5, 30, -4}, { 5, 25, 5}, { 5, 24, -5}, { 5, 17, 6}, + { 5, 16, -6}, { 5, 9, 7}, { 5, 8, -7}, { 5, 1, 8}, + { 5, 0, -8}, { 6, 53, 9}, { 6, 52, -9}, { 6, 37, 10}, + { 6, 36,-10}, { 6, 21, 11}, { 6, 20,-11}, { 6, 5, 12}, + { 6, 4,-12}, { 7, 109, 13}, { 7, 108,-13}, { 7, 77, 14}, + { 7, 76,-14}, { 7, 45, 15}, { 7, 44,-15}, { 7, 13, 16}, + { 7, 12,-16}, { 8, 221, 17}, { 8, 220,-17}, { 8, 157, 18}, + { 8, 156,-18}, { 8, 93, 19}, { 8, 92,-19}, { 8, 29, 20}, + { 8, 28,-20}, { 9, 445, 21}, { 9, 444,-21}, { 9, 317, 22}, + { 9, 316,-22}, { 9, 189, 23}, { 9, 188,-23}, { 9, 61, 24}, + { 9, 60,-24}, {10, 892, 25}, {10, 639,-25}, {10, 637, 26}, + {10, 636,-26}, {10, 381, 27}, {10, 380,-27}, {10, 125, 28}, + {10, 124,-28}, {11, 1788, 29}, {11, 1787,-29}, {11, 1276, 30}, + {11, 767,-30}, {11, 764, 31}, {11, 255,-31}, {11, 252, 32}, + {12, 3583,-32}, {12, 3579, 33}, {12, 3578,-33}, {12, 2555, 34}, + {12, 2554,-34}, {12, 1531, 35}, {12, 1530,-35}, {12, 507, 36}, + {12, 506,-36}, {13, 7160, 37}, {13, 7147,-37}, {13, 7144, 38}, + {13, 3067,-38}, {13, 3065, 39}, {13, 3064,-39}, {13, 1017, 40}, + {13, 1016,-40}, {14, 14330, 41}, {14, 14329,-41}, {14, 14291, 42}, + {14, 14290,-42}, {14, 6132, 43}, {14, 2039,-43}, {14, 2038, 44}, + {14, 2037,-44}, {15, 28663, 45}, {15, 28662,-45}, {15, 28585, 46}, + {15, 28584,-46}, {15, 12267, 47}, {15, 12266,-47}, {15, 4073, 48}, + {15, 4072,-48}, {16, 57315, 49}, {16, 57314,-49}, {16, 57313, 50}, + {16, 57312,-50}, {16, 57311, 51}, {16, 57310,-51}, {16, 57309, 52}, + {16, 57308,-52}, {16, 57307, 53}, {16, 57306,-53}, {16, 57305, 54}, + {16, 57304,-54}, {16, 57303, 55}, {16, 57302,-55}, {16, 57301, 56}, + {16, 57300,-56}, {16, 57299, 57}, {16, 57298,-57}, {16, 57297, 58}, + {16, 57296,-58}, {16, 57295, 59}, {16, 57294,-59}, {16, 57293, 60}, + {16, 57292,-60}, {16, 57291, 61}, {16, 57290,-61}, {16, 57289, 62}, + {16, 57288,-62}, {16, 57175, 63}, {16, 57174,-63}, {16, 57173, 64}, {16, 57172,-64}, { 0, 0, 0} }; @@ -277,25 +277,25 @@ huff_entry_t bitalloc_a_3[] = huff_entry_t bitalloc_a_4[] = { - { 1, 0, 0}, { 2, 2, 1}, { 3, 6, 2}, { 3, 7, 3}, + { 1, 0, 0}, { 2, 2, 1}, { 3, 6, 2}, { 3, 7, 3}, { 0, 0, 0} }; huff_entry_t bitalloc_b_4[] = { - { 2, 2, 0}, { 3, 6, 1}, { 3, 7, 2}, { 1, 0, 3}, + { 2, 2, 0}, { 3, 6, 1}, { 3, 7, 2}, { 1, 0, 3}, { 0, 0, 0} }; huff_entry_t bitalloc_c_4[] = { - { 3, 6, 0}, { 3, 7, 1}, { 1, 0, 2}, { 2, 2, 3}, + { 3, 6, 0}, { 3, 7, 1}, { 1, 0, 2}, { 2, 2, 3}, { 0, 0, 0} }; huff_entry_t bitalloc_d_4[] = { - { 2, 0, 0}, { 2, 1, 1}, { 2, 2, 2}, { 2, 3, 3}, + { 2, 0, 0}, { 2, 1, 1}, { 2, 2, 2}, { 2, 3, 3}, { 0, 0, 0} }; @@ -309,719 +309,719 @@ huff_entry_t *tmode[] = huff_entry_t bitalloc_a_5[] = { - { 1, 0, 0}, { 2, 2, 1}, { 3, 6, -1}, { 4, 14, 2}, + { 1, 0, 0}, { 2, 2, 1}, { 3, 6, -1}, { 4, 14, 2}, { 4, 15, -2}, { 0, 0, 0} }; huff_entry_t bitalloc_b_5[] = { - { 2, 2, 0}, { 2, 0, 1}, { 2, 1, -1}, { 3, 6, 2}, + { 2, 2, 0}, { 2, 0, 1}, { 2, 1, -1}, { 3, 6, 2}, { 3, 7, -2}, { 0, 0, 0} }; huff_entry_t bitalloc_c_5[] = { - { 1, 0, 0}, { 3, 4, 1}, { 3, 5, -1}, { 3, 6, 2}, + { 1, 0, 0}, { 3, 4, 1}, { 3, 5, -1}, { 3, 6, 2}, { 3, 7, -2}, { 0, 0, 0} }; huff_entry_t bitalloc_a_7[] = { - { 1, 0, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 4, 2}, + { 1, 0, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 4, 2}, { 4, 14, -2}, { 5, 31, 3}, { 5, 30, -3}, { 0, 0, 0} }; huff_entry_t bitalloc_b_7[] = { - { 2, 3, 0}, { 2, 1, 1}, { 2, 0, -1}, { 3, 4, 2}, + { 2, 3, 0}, { 2, 1, 1}, { 2, 0, -1}, { 3, 4, 2}, { 4, 11, -2}, { 5, 21, 3}, { 5, 20, -3}, { 0, 0, 0} }; huff_entry_t bitalloc_c_7[] = { - { 2, 3, 0}, { 2, 2, 1}, { 2, 1, -1}, { 4, 3, 2}, + { 2, 3, 0}, { 2, 2, 1}, { 2, 1, -1}, { 4, 3, 2}, { 4, 2, -2}, { 4, 1, 3}, { 4, 0, -3}, { 0, 0, 0} }; huff_entry_t bitalloc_a_9[] = { - { 1, 0, 0}, { 3, 7, 1}, { 3, 5, -1}, { 4, 13, 2}, - { 4, 9, -2}, { 4, 8, 3}, { 5, 25, -3}, { 6, 49, 4}, + { 1, 0, 0}, { 3, 7, 1}, { 3, 5, -1}, { 4, 13, 2}, + { 4, 9, -2}, { 4, 8, 3}, { 5, 25, -3}, { 6, 49, 4}, { 6, 48, -4}, { 0, 0, 0} }; huff_entry_t bitalloc_b_9[] = { - { 2, 2, 0}, { 2, 0, 1}, { 3, 7, -1}, { 3, 3, 2}, - { 3, 2, -2}, { 5, 27, 3}, { 5, 26, -3}, { 5, 25, 4}, + { 2, 2, 0}, { 2, 0, 1}, { 3, 7, -1}, { 3, 3, 2}, + { 3, 2, -2}, { 5, 27, 3}, { 5, 26, -3}, { 5, 25, 4}, { 5, 24, -4}, { 0, 0, 0} }; huff_entry_t bitalloc_c_9[] = { - { 2, 2, 0}, { 2, 0, 1}, { 3, 7, -1}, { 3, 6, 2}, - { 3, 2, -2}, { 4, 6, 3}, { 5, 15, -3}, { 6, 29, 4}, + { 2, 2, 0}, { 2, 0, 1}, { 3, 7, -1}, { 3, 6, 2}, + { 3, 2, -2}, { 4, 6, 3}, { 5, 15, -3}, { 6, 29, 4}, { 6, 28, -4}, { 0, 0, 0} }; huff_entry_t bitalloc_a_13[] = { - { 1, 0, 0}, { 3, 4, 1}, { 4, 15, -1}, { 4, 13, 2}, - { 4, 12, -2}, { 4, 10, 3}, { 5, 29, -3}, { 5, 22, 4}, - { 6, 57, -4}, { 6, 47, 5}, { 6, 46, -5}, { 7, 113, 6}, + { 1, 0, 0}, { 3, 4, 1}, { 4, 15, -1}, { 4, 13, 2}, + { 4, 12, -2}, { 4, 10, 3}, { 5, 29, -3}, { 5, 22, 4}, + { 6, 57, -4}, { 6, 47, 5}, { 6, 46, -5}, { 7, 113, 6}, { 7, 112, -6}, { 0, 0, 0} }; huff_entry_t bitalloc_b_13[] = { - { 2, 0, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 2, 2}, - { 4, 15, -2}, { 4, 9, 3}, { 4, 7, -3}, { 4, 6, 4}, - { 5, 29, -4}, { 5, 17, 5}, { 5, 16, -5}, { 6, 57, 6}, + { 2, 0, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 2, 2}, + { 4, 15, -2}, { 4, 9, 3}, { 4, 7, -3}, { 4, 6, 4}, + { 5, 29, -4}, { 5, 17, 5}, { 5, 16, -5}, { 6, 57, 6}, { 6, 56, -6}, { 0, 0, 0} }; huff_entry_t bitalloc_c_13[] = { - { 3, 5, 0}, { 3, 4, 1}, { 3, 3, -1}, { 3, 2, 2}, - { 3, 0, -2}, { 4, 15, 3}, { 4, 14, -3}, { 4, 12, 4}, - { 4, 3, -4}, { 5, 27, 5}, { 5, 26, -5}, { 5, 5, 6}, + { 3, 5, 0}, { 3, 4, 1}, { 3, 3, -1}, { 3, 2, 2}, + { 3, 0, -2}, { 4, 15, 3}, { 4, 14, -3}, { 4, 12, 4}, + { 4, 3, -4}, { 5, 27, 5}, { 5, 26, -5}, { 5, 5, 6}, { 5, 4, -6}, { 0, 0, 0} }; huff_entry_t bitalloc_a_17[] = { - { 2, 1, 0}, { 3, 7, 1}, { 3, 6, -1}, { 3, 4, 2}, - { 3, 1, -2}, { 4, 11, 3}, { 4, 10, -3}, { 4, 0, 4}, - { 5, 3, -4}, { 6, 4, 5}, { 7, 11, -5}, { 8, 20, 6}, - { 9, 43, -6}, {10, 84, 7}, {11, 171, -7}, {12, 341, 8}, + { 2, 1, 0}, { 3, 7, 1}, { 3, 6, -1}, { 3, 4, 2}, + { 3, 1, -2}, { 4, 11, 3}, { 4, 10, -3}, { 4, 0, 4}, + { 5, 3, -4}, { 6, 4, 5}, { 7, 11, -5}, { 8, 20, 6}, + { 9, 43, -6}, {10, 84, 7}, {11, 171, -7}, {12, 341, 8}, {12, 340, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_b_17[] = { - { 2, 0, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 2, 2}, - { 4, 15, -2}, { 4, 9, 3}, { 4, 8, -3}, { 5, 29, 4}, - { 5, 28, -4}, { 5, 14, 5}, { 5, 13, -5}, { 6, 30, 6}, - { 6, 25, -6}, { 6, 24, 7}, { 7, 63, -7}, { 8, 125, 8}, + { 2, 0, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 2, 2}, + { 4, 15, -2}, { 4, 9, 3}, { 4, 8, -3}, { 5, 29, 4}, + { 5, 28, -4}, { 5, 14, 5}, { 5, 13, -5}, { 6, 30, 6}, + { 6, 25, -6}, { 6, 24, 7}, { 7, 63, -7}, { 8, 125, 8}, { 8, 124, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_c_17[] = { - { 3, 6, 0}, { 3, 4, 1}, { 3, 3, -1}, { 3, 0, 2}, - { 4, 15, -2}, { 4, 11, 3}, { 4, 10, -3}, { 4, 4, 4}, - { 4, 3, -4}, { 5, 29, 5}, { 5, 28, -5}, { 5, 10, 6}, - { 5, 5, -6}, { 5, 4, 7}, { 6, 23, -7}, { 7, 45, 8}, + { 3, 6, 0}, { 3, 4, 1}, { 3, 3, -1}, { 3, 0, 2}, + { 4, 15, -2}, { 4, 11, 3}, { 4, 10, -3}, { 4, 4, 4}, + { 4, 3, -4}, { 5, 29, 5}, { 5, 28, -5}, { 5, 10, 6}, + { 5, 5, -6}, { 5, 4, 7}, { 6, 23, -7}, { 7, 45, 8}, { 7, 44, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_d_17[] = { - { 1, 0, 0}, { 3, 7, 1}, { 3, 6, -1}, { 4, 11, 2}, - { 4, 10, -2}, { 5, 19, 3}, { 5, 18, -3}, { 6, 35, 4}, - { 6, 34, -4}, { 7, 67, 5}, { 7, 66, -5}, { 8, 131, 6}, - { 8, 130, -6}, { 9, 259, 7}, { 9, 258, -7}, { 9, 257, 8}, + { 1, 0, 0}, { 3, 7, 1}, { 3, 6, -1}, { 4, 11, 2}, + { 4, 10, -2}, { 5, 19, 3}, { 5, 18, -3}, { 6, 35, 4}, + { 6, 34, -4}, { 7, 67, 5}, { 7, 66, -5}, { 8, 131, 6}, + { 8, 130, -6}, { 9, 259, 7}, { 9, 258, -7}, { 9, 257, 8}, { 9, 256, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_e_17[] = { - { 1, 0, 0}, { 3, 5, 1}, { 3, 4, -1}, { 4, 12, 2}, - { 5, 31, -2}, { 5, 28, 3}, { 5, 27, -3}, { 6, 60, 4}, - { 6, 59, -4}, { 6, 53, 5}, { 6, 52, -5}, { 7, 122, 6}, - { 7, 117, -6}, { 8, 247, 7}, { 8, 246, -7}, { 8, 233, 8}, + { 1, 0, 0}, { 3, 5, 1}, { 3, 4, -1}, { 4, 12, 2}, + { 5, 31, -2}, { 5, 28, 3}, { 5, 27, -3}, { 6, 60, 4}, + { 6, 59, -4}, { 6, 53, 5}, { 6, 52, -5}, { 7, 122, 6}, + { 7, 117, -6}, { 8, 247, 7}, { 8, 246, -7}, { 8, 233, 8}, { 8, 232, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_f_17[] = { - { 3, 6, 0}, { 3, 5, 1}, { 3, 4, -1}, { 3, 2, 2}, - { 3, 1, -2}, { 4, 15, 3}, { 4, 14, -3}, { 4, 6, 4}, - { 4, 1, -4}, { 5, 14, 5}, { 5, 1, -5}, { 6, 31, 6}, - { 6, 30, -6}, { 6, 0, 7}, { 7, 3, -7}, { 8, 5, 8}, + { 3, 6, 0}, { 3, 5, 1}, { 3, 4, -1}, { 3, 2, 2}, + { 3, 1, -2}, { 4, 15, 3}, { 4, 14, -3}, { 4, 6, 4}, + { 4, 1, -4}, { 5, 14, 5}, { 5, 1, -5}, { 6, 31, 6}, + { 6, 30, -6}, { 6, 0, 7}, { 7, 3, -7}, { 8, 5, 8}, { 8, 4, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_g_17[] = { - { 2, 2, 0}, { 3, 7, 1}, { 3, 6, -1}, { 3, 1, 2}, - { 3, 0, -2}, { 4, 5, 3}, { 4, 4, -3}, { 5, 14, 4}, - { 5, 13, -4}, { 6, 30, 5}, { 6, 25, -5}, { 7, 62, 6}, - { 7, 49, -6}, { 8, 127, 7}, { 8, 126, -7}, { 8, 97, 8}, + { 2, 2, 0}, { 3, 7, 1}, { 3, 6, -1}, { 3, 1, 2}, + { 3, 0, -2}, { 4, 5, 3}, { 4, 4, -3}, { 5, 14, 4}, + { 5, 13, -4}, { 6, 30, 5}, { 6, 25, -5}, { 7, 62, 6}, + { 7, 49, -6}, { 8, 127, 7}, { 8, 126, -7}, { 8, 97, 8}, { 8, 96, -8}, { 0, 0, 0} }; huff_entry_t bitalloc_a_25[] = { - { 3, 6, 0}, { 3, 4, 1}, { 3, 3, -1}, { 3, 1, 2}, - { 3, 0, -2}, { 4, 15, 3}, { 4, 14, -3}, { 4, 5, 4}, - { 4, 4, -4}, { 5, 22, 5}, { 5, 21, -5}, { 6, 47, 6}, - { 6, 46, -6}, { 7, 83, 7}, { 7, 82, -7}, { 8, 163, 8}, - { 8, 162, -8}, { 8, 160, 9}, { 9, 323, -9}, {10, 644, 10}, - {11, 1291,-10}, {12, 2580, 11}, {13, 5163,-11}, {14, 10325, 12}, + { 3, 6, 0}, { 3, 4, 1}, { 3, 3, -1}, { 3, 1, 2}, + { 3, 0, -2}, { 4, 15, 3}, { 4, 14, -3}, { 4, 5, 4}, + { 4, 4, -4}, { 5, 22, 5}, { 5, 21, -5}, { 6, 47, 6}, + { 6, 46, -6}, { 7, 83, 7}, { 7, 82, -7}, { 8, 163, 8}, + { 8, 162, -8}, { 8, 160, 9}, { 9, 323, -9}, {10, 644, 10}, + {11, 1291,-10}, {12, 2580, 11}, {13, 5163,-11}, {14, 10325, 12}, {14, 10324,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_b_25[] = { - { 3, 5, 0}, { 3, 2, 1}, { 3, 1, -1}, { 4, 15, 2}, - { 4, 14, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 6, 4}, - { 4, 1, -4}, { 5, 26, 5}, { 5, 25, -5}, { 5, 15, 6}, - { 5, 14, -6}, { 6, 55, 7}, { 6, 54, -7}, { 6, 49, 8}, - { 6, 48, -8}, { 6, 1, 9}, { 6, 0, -9}, { 7, 6, 10}, - { 7, 5,-10}, { 7, 4, 11}, { 8, 15,-11}, { 9, 29, 12}, + { 3, 5, 0}, { 3, 2, 1}, { 3, 1, -1}, { 4, 15, 2}, + { 4, 14, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 6, 4}, + { 4, 1, -4}, { 5, 26, 5}, { 5, 25, -5}, { 5, 15, 6}, + { 5, 14, -6}, { 6, 55, 7}, { 6, 54, -7}, { 6, 49, 8}, + { 6, 48, -8}, { 6, 1, 9}, { 6, 0, -9}, { 7, 6, 10}, + { 7, 5,-10}, { 7, 4, 11}, { 8, 15,-11}, { 9, 29, 12}, { 9, 28,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_c_25[] = { - { 3, 1, 0}, { 4, 15, 1}, { 4, 14, -1}, { 4, 12, 2}, - { 4, 11, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 6, 4}, - { 4, 5, -4}, { 4, 1, 5}, { 4, 0, -5}, { 5, 26, 6}, - { 5, 21, -6}, { 5, 15, 7}, { 5, 14, -7}, { 5, 8, 8}, - { 6, 55, -8}, { 6, 41, 9}, { 6, 40, -9}, { 6, 18, 10}, - { 7, 109,-10}, { 7, 108, 11}, { 7, 39,-11}, { 8, 77, 12}, + { 3, 1, 0}, { 4, 15, 1}, { 4, 14, -1}, { 4, 12, 2}, + { 4, 11, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 6, 4}, + { 4, 5, -4}, { 4, 1, 5}, { 4, 0, -5}, { 5, 26, 6}, + { 5, 21, -6}, { 5, 15, 7}, { 5, 14, -7}, { 5, 8, 8}, + { 6, 55, -8}, { 6, 41, 9}, { 6, 40, -9}, { 6, 18, 10}, + { 7, 109,-10}, { 7, 108, 11}, { 7, 39,-11}, { 8, 77, 12}, { 8, 76,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_d_25[] = { - { 2, 2, 0}, { 3, 7, 1}, { 3, 6, -1}, { 3, 1, 2}, - { 3, 0, -2}, { 4, 5, 3}, { 4, 4, -3}, { 5, 13, 4}, - { 5, 12, -4}, { 6, 29, 5}, { 6, 28, -5}, { 7, 62, 6}, - { 7, 61, -6}, { 8, 126, 7}, { 8, 121, -7}, { 9, 255, 8}, - { 9, 254, -8}, {10, 483, 9}, {10, 482, -9}, {11, 963, 10}, - {11, 962,-10}, {12, 1923, 11}, {12, 1922,-11}, {12, 1921, 12}, + { 2, 2, 0}, { 3, 7, 1}, { 3, 6, -1}, { 3, 1, 2}, + { 3, 0, -2}, { 4, 5, 3}, { 4, 4, -3}, { 5, 13, 4}, + { 5, 12, -4}, { 6, 29, 5}, { 6, 28, -5}, { 7, 62, 6}, + { 7, 61, -6}, { 8, 126, 7}, { 8, 121, -7}, { 9, 255, 8}, + { 9, 254, -8}, {10, 483, 9}, {10, 482, -9}, {11, 963, 10}, + {11, 962,-10}, {12, 1923, 11}, {12, 1922,-11}, {12, 1921, 12}, {12, 1920,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_e_25[] = { - { 2, 3, 0}, { 3, 3, 1}, { 3, 2, -1}, { 4, 11, 2}, - { 4, 10, -2}, { 4, 1, 3}, { 4, 0, -3}, { 5, 17, 4}, - { 5, 16, -4}, { 5, 5, 5}, { 5, 4, -5}, { 6, 38, 6}, - { 6, 37, -6}, { 6, 14, 7}, { 6, 13, -7}, { 7, 79, 8}, - { 7, 78, -8}, { 7, 72, 9}, { 7, 31, -9}, { 7, 25, 10}, - { 7, 24,-10}, { 8, 147, 11}, { 8, 146,-11}, { 8, 61, 12}, + { 2, 3, 0}, { 3, 3, 1}, { 3, 2, -1}, { 4, 11, 2}, + { 4, 10, -2}, { 4, 1, 3}, { 4, 0, -3}, { 5, 17, 4}, + { 5, 16, -4}, { 5, 5, 5}, { 5, 4, -5}, { 6, 38, 6}, + { 6, 37, -6}, { 6, 14, 7}, { 6, 13, -7}, { 7, 79, 8}, + { 7, 78, -8}, { 7, 72, 9}, { 7, 31, -9}, { 7, 25, 10}, + { 7, 24,-10}, { 8, 147, 11}, { 8, 146,-11}, { 8, 61, 12}, { 8, 60,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_f_25[] = { - { 3, 1, 0}, { 3, 0, 1}, { 4, 15, -1}, { 4, 14, 2}, - { 4, 13, -2}, { 4, 11, 3}, { 4, 10, -3}, { 4, 8, 4}, - { 4, 7, -4}, { 4, 5, 5}, { 4, 4, -5}, { 5, 24, 6}, - { 5, 19, -6}, { 5, 13, 7}, { 5, 12, -7}, { 6, 37, 8}, - { 6, 36, -8}, { 7, 102, 9}, { 7, 101, -9}, { 8, 207, 10}, - { 8, 206,-10}, { 8, 200, 11}, { 9, 403,-11}, {10, 805, 12}, + { 3, 1, 0}, { 3, 0, 1}, { 4, 15, -1}, { 4, 14, 2}, + { 4, 13, -2}, { 4, 11, 3}, { 4, 10, -3}, { 4, 8, 4}, + { 4, 7, -4}, { 4, 5, 5}, { 4, 4, -5}, { 5, 24, 6}, + { 5, 19, -6}, { 5, 13, 7}, { 5, 12, -7}, { 6, 37, 8}, + { 6, 36, -8}, { 7, 102, 9}, { 7, 101, -9}, { 8, 207, 10}, + { 8, 206,-10}, { 8, 200, 11}, { 9, 403,-11}, {10, 805, 12}, {10, 804,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_g_25[] = { - { 2, 1, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 0, 2}, - { 4, 15, -2}, { 4, 8, 3}, { 4, 3, -3}, { 5, 28, 4}, - { 5, 19, -4}, { 5, 4, 5}, { 6, 59, -5}, { 6, 36, 6}, - { 6, 11, -6}, { 7, 116, 7}, { 7, 75, -7}, { 7, 21, 8}, - { 7, 20, -8}, { 8, 149, 9}, { 8, 148, -9}, { 9, 470, 10}, - { 9, 469,-10}, {10, 943, 11}, {10, 942,-11}, {10, 937, 12}, + { 2, 1, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 0, 2}, + { 4, 15, -2}, { 4, 8, 3}, { 4, 3, -3}, { 5, 28, 4}, + { 5, 19, -4}, { 5, 4, 5}, { 6, 59, -5}, { 6, 36, 6}, + { 6, 11, -6}, { 7, 116, 7}, { 7, 75, -7}, { 7, 21, 8}, + { 7, 20, -8}, { 8, 149, 9}, { 8, 148, -9}, { 9, 470, 10}, + { 9, 469,-10}, {10, 943, 11}, {10, 942,-11}, {10, 937, 12}, {10, 936,-12}, { 0, 0, 0} }; huff_entry_t bitalloc_a_33[] = { - { 3, 2, 0}, { 3, 1, 1}, { 3, 0, -1}, { 4, 14, 2}, - { 4, 13, -2}, { 4, 12, 3}, { 4, 11, -3}, { 4, 9, 4}, - { 4, 8, -4}, { 4, 6, 5}, { 5, 31, -5}, { 5, 20, 6}, - { 5, 15, -6}, { 6, 61, 7}, { 6, 60, -7}, { 6, 29, 8}, - { 6, 28, -8}, { 7, 85, 9}, { 7, 84, -9}, { 8, 174, 10}, - { 8, 173,-10}, { 9, 351, 11}, { 9, 350,-11}, {10, 691, 12}, - {10, 690,-12}, {11, 1379, 13}, {11, 1378,-13}, {12, 2755, 14}, - {12, 2754,-14}, {13, 5507, 15}, {13, 5506,-15}, {13, 5505, 16}, + { 3, 2, 0}, { 3, 1, 1}, { 3, 0, -1}, { 4, 14, 2}, + { 4, 13, -2}, { 4, 12, 3}, { 4, 11, -3}, { 4, 9, 4}, + { 4, 8, -4}, { 4, 6, 5}, { 5, 31, -5}, { 5, 20, 6}, + { 5, 15, -6}, { 6, 61, 7}, { 6, 60, -7}, { 6, 29, 8}, + { 6, 28, -8}, { 7, 85, 9}, { 7, 84, -9}, { 8, 174, 10}, + { 8, 173,-10}, { 9, 351, 11}, { 9, 350,-11}, {10, 691, 12}, + {10, 690,-12}, {11, 1379, 13}, {11, 1378,-13}, {12, 2755, 14}, + {12, 2754,-14}, {13, 5507, 15}, {13, 5506,-15}, {13, 5505, 16}, {13, 5504,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_b_33[] = { - { 3, 1, 0}, { 4, 15, 1}, { 4, 14, -1}, { 4, 11, 2}, - { 4, 10, -2}, { 4, 8, 3}, { 4, 7, -3}, { 4, 4, 4}, - { 4, 1, -4}, { 5, 27, 5}, { 5, 26, -5}, { 5, 19, 6}, - { 5, 18, -6}, { 5, 12, 7}, { 5, 11, -7}, { 5, 1, 8}, - { 5, 0, -8}, { 6, 50, 9}, { 6, 49, -9}, { 6, 26, 10}, - { 6, 21,-10}, { 7, 103, 11}, { 7, 102,-11}, { 7, 96, 12}, - { 7, 55,-12}, { 7, 41, 13}, { 7, 40,-13}, { 8, 194, 14}, - { 8, 109,-14}, { 8, 108, 15}, { 9, 391,-15}, {10, 781, 16}, + { 3, 1, 0}, { 4, 15, 1}, { 4, 14, -1}, { 4, 11, 2}, + { 4, 10, -2}, { 4, 8, 3}, { 4, 7, -3}, { 4, 4, 4}, + { 4, 1, -4}, { 5, 27, 5}, { 5, 26, -5}, { 5, 19, 6}, + { 5, 18, -6}, { 5, 12, 7}, { 5, 11, -7}, { 5, 1, 8}, + { 5, 0, -8}, { 6, 50, 9}, { 6, 49, -9}, { 6, 26, 10}, + { 6, 21,-10}, { 7, 103, 11}, { 7, 102,-11}, { 7, 96, 12}, + { 7, 55,-12}, { 7, 41, 13}, { 7, 40,-13}, { 8, 194, 14}, + { 8, 109,-14}, { 8, 108, 15}, { 9, 391,-15}, {10, 781, 16}, {10, 780,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_c_33[] = { - { 4, 13, 0}, { 4, 11, 1}, { 4, 10, -1}, { 4, 8, 2}, - { 4, 7, -2}, { 4, 4, 3}, { 4, 3, -3}, { 4, 2, 4}, - { 4, 1, -4}, { 5, 30, 5}, { 5, 29, -5}, { 5, 25, 6}, - { 5, 24, -6}, { 5, 19, 7}, { 5, 18, -7}, { 5, 11, 8}, - { 5, 10, -8}, { 5, 0, 9}, { 6, 63, -9}, { 6, 62, 10}, - { 6, 57,-10}, { 6, 27, 11}, { 6, 26,-11}, { 6, 24, 12}, - { 6, 3,-12}, { 7, 113, 13}, { 7, 112,-13}, { 7, 50, 14}, - { 7, 5,-14}, { 7, 4, 15}, { 8, 103,-15}, { 9, 205, 16}, + { 4, 13, 0}, { 4, 11, 1}, { 4, 10, -1}, { 4, 8, 2}, + { 4, 7, -2}, { 4, 4, 3}, { 4, 3, -3}, { 4, 2, 4}, + { 4, 1, -4}, { 5, 30, 5}, { 5, 29, -5}, { 5, 25, 6}, + { 5, 24, -6}, { 5, 19, 7}, { 5, 18, -7}, { 5, 11, 8}, + { 5, 10, -8}, { 5, 0, 9}, { 6, 63, -9}, { 6, 62, 10}, + { 6, 57,-10}, { 6, 27, 11}, { 6, 26,-11}, { 6, 24, 12}, + { 6, 3,-12}, { 7, 113, 13}, { 7, 112,-13}, { 7, 50, 14}, + { 7, 5,-14}, { 7, 4, 15}, { 8, 103,-15}, { 9, 205, 16}, { 9, 204,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_d_33[] = { - { 2, 1, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 0, 2}, - { 4, 15, -2}, { 4, 8, 3}, { 4, 3, -3}, { 5, 28, 4}, - { 5, 19, -4}, { 5, 4, 5}, { 6, 59, -5}, { 6, 36, 6}, - { 6, 11, -6}, { 7, 116, 7}, { 7, 75, -7}, { 7, 21, 8}, - { 7, 20, -8}, { 8, 149, 9}, { 8, 148, -9}, { 9, 469, 10}, - { 9, 468,-10}, {10, 941, 11}, {10, 940,-11}, {11, 1885, 12}, - {11, 1884,-12}, {12, 3773, 13}, {12, 3772,-13}, {13, 7551, 14}, - {13, 7550,-14}, {14, 15099, 15}, {14, 15098,-15}, {14, 15097, 16}, + { 2, 1, 0}, { 3, 6, 1}, { 3, 5, -1}, { 3, 0, 2}, + { 4, 15, -2}, { 4, 8, 3}, { 4, 3, -3}, { 5, 28, 4}, + { 5, 19, -4}, { 5, 4, 5}, { 6, 59, -5}, { 6, 36, 6}, + { 6, 11, -6}, { 7, 116, 7}, { 7, 75, -7}, { 7, 21, 8}, + { 7, 20, -8}, { 8, 149, 9}, { 8, 148, -9}, { 9, 469, 10}, + { 9, 468,-10}, {10, 941, 11}, {10, 940,-11}, {11, 1885, 12}, + {11, 1884,-12}, {12, 3773, 13}, {12, 3772,-13}, {13, 7551, 14}, + {13, 7550,-14}, {14, 15099, 15}, {14, 15098,-15}, {14, 15097, 16}, {14, 15096,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_e_33[] = { - { 2, 2, 0}, { 3, 2, 1}, { 3, 1, -1}, { 4, 12, 2}, - { 4, 7, -2}, { 4, 0, 3}, { 5, 31, -3}, { 5, 27, 4}, - { 5, 26, -4}, { 5, 3, 5}, { 5, 2, -5}, { 6, 59, 6}, - { 6, 58, -6}, { 6, 27, 7}, { 6, 26, -7}, { 7, 123, 8}, - { 7, 122, -8}, { 7, 120, 9}, { 7, 115, -9}, { 7, 112, 10}, - { 7, 51,-10}, { 7, 49, 11}, { 7, 48,-11}, { 8, 242, 12}, - { 8, 229,-12}, { 8, 227, 13}, { 8, 226,-13}, { 8, 101, 14}, - { 8, 100,-14}, { 9, 487, 15}, { 9, 486,-15}, { 9, 457, 16}, + { 2, 2, 0}, { 3, 2, 1}, { 3, 1, -1}, { 4, 12, 2}, + { 4, 7, -2}, { 4, 0, 3}, { 5, 31, -3}, { 5, 27, 4}, + { 5, 26, -4}, { 5, 3, 5}, { 5, 2, -5}, { 6, 59, 6}, + { 6, 58, -6}, { 6, 27, 7}, { 6, 26, -7}, { 7, 123, 8}, + { 7, 122, -8}, { 7, 120, 9}, { 7, 115, -9}, { 7, 112, 10}, + { 7, 51,-10}, { 7, 49, 11}, { 7, 48,-11}, { 8, 242, 12}, + { 8, 229,-12}, { 8, 227, 13}, { 8, 226,-13}, { 8, 101, 14}, + { 8, 100,-14}, { 9, 487, 15}, { 9, 486,-15}, { 9, 457, 16}, { 9, 456,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_f_33[] = { - { 4, 13, 0}, { 4, 12, 1}, { 4, 11, -1}, { 4, 9, 2}, - { 4, 8, -2}, { 4, 7, 3}, { 4, 6, -3}, { 4, 4, 4}, - { 4, 3, -4}, { 4, 1, 5}, { 4, 0, -5}, { 5, 30, 6}, - { 5, 29, -6}, { 5, 21, 7}, { 5, 20, -7}, { 5, 10, 8}, - { 5, 5, -8}, { 6, 63, 9}, { 6, 62, -9}, { 6, 56, 10}, - { 6, 23,-10}, { 6, 9, 11}, { 6, 8,-11}, { 7, 45, 12}, - { 7, 44,-12}, { 8, 230, 13}, { 8, 229,-13}, { 9, 463, 14}, - { 9, 462,-14}, { 9, 456, 15}, {10, 915,-15}, {11, 1829, 16}, + { 4, 13, 0}, { 4, 12, 1}, { 4, 11, -1}, { 4, 9, 2}, + { 4, 8, -2}, { 4, 7, 3}, { 4, 6, -3}, { 4, 4, 4}, + { 4, 3, -4}, { 4, 1, 5}, { 4, 0, -5}, { 5, 30, 6}, + { 5, 29, -6}, { 5, 21, 7}, { 5, 20, -7}, { 5, 10, 8}, + { 5, 5, -8}, { 6, 63, 9}, { 6, 62, -9}, { 6, 56, 10}, + { 6, 23,-10}, { 6, 9, 11}, { 6, 8,-11}, { 7, 45, 12}, + { 7, 44,-12}, { 8, 230, 13}, { 8, 229,-13}, { 9, 463, 14}, + { 9, 462,-14}, { 9, 456, 15}, {10, 915,-15}, {11, 1829, 16}, {11, 1828,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_g_33[] = { - { 3, 6, 0}, { 3, 3, 1}, { 3, 2, -1}, { 4, 15, 2}, - { 4, 14, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 1, 4}, - { 4, 0, -4}, { 5, 22, 5}, { 5, 21, -5}, { 5, 6, 6}, - { 5, 5, -6}, { 6, 46, 7}, { 6, 41, -7}, { 6, 14, 8}, - { 6, 9, -8}, { 7, 94, 9}, { 7, 81, -9}, { 7, 30, 10}, - { 7, 17,-10}, { 8, 191, 11}, { 8, 190,-11}, { 8, 63, 12}, - { 8, 62,-12}, { 8, 32, 13}, { 9, 323,-13}, { 9, 321, 14}, - { 9, 320,-14}, { 9, 67, 15}, { 9, 66,-15}, {10, 645, 16}, + { 3, 6, 0}, { 3, 3, 1}, { 3, 2, -1}, { 4, 15, 2}, + { 4, 14, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 1, 4}, + { 4, 0, -4}, { 5, 22, 5}, { 5, 21, -5}, { 5, 6, 6}, + { 5, 5, -6}, { 6, 46, 7}, { 6, 41, -7}, { 6, 14, 8}, + { 6, 9, -8}, { 7, 94, 9}, { 7, 81, -9}, { 7, 30, 10}, + { 7, 17,-10}, { 8, 191, 11}, { 8, 190,-11}, { 8, 63, 12}, + { 8, 62,-12}, { 8, 32, 13}, { 9, 323,-13}, { 9, 321, 14}, + { 9, 320,-14}, { 9, 67, 15}, { 9, 66,-15}, {10, 645, 16}, {10, 644,-16}, { 0, 0, 0} }; huff_entry_t bitalloc_a_65[] = { - { 4, 6, 0}, { 4, 5, 1}, { 4, 4, -1}, { 4, 2, 2}, - { 4, 1, -2}, { 4, 0, 3}, { 5, 31, -3}, { 5, 29, 4}, - { 5, 28, -4}, { 5, 27, 5}, { 5, 26, -5}, { 5, 24, 6}, - { 5, 23, -6}, { 5, 21, 7}, { 5, 20, -7}, { 5, 18, 8}, - { 5, 17, -8}, { 5, 14, 9}, { 5, 7, -9}, { 5, 6, 10}, - { 6, 61,-10}, { 6, 50, 11}, { 6, 45,-11}, { 6, 38, 12}, - { 6, 33,-12}, { 6, 31, 13}, { 6, 30,-13}, { 7, 120, 14}, - { 7, 103,-14}, { 7, 89, 15}, { 7, 88,-15}, { 7, 65, 16}, - { 7, 64,-16}, { 8, 205, 17}, { 8, 204,-17}, { 8, 157, 18}, - { 8, 156,-18}, { 9, 486, 19}, { 9, 485,-19}, { 9, 318, 20}, - { 9, 317,-20}, {10, 975, 21}, {10, 974,-21}, {10, 639, 22}, - {10, 638,-22}, {11, 1939, 23}, {11, 1938,-23}, {11, 1936, 24}, - {11, 1267,-24}, {11, 1264, 25}, {12, 3875,-25}, {12, 2532, 26}, - {12, 2531,-26}, {13, 7749, 27}, {13, 7748,-27}, {13, 5061, 28}, - {13, 5060,-28}, {14, 10133, 29}, {14, 10132,-29}, {15, 20269, 30}, - {15, 20268,-30}, {16, 40543, 31}, {16, 40542,-31}, {16, 40541, 32}, + { 4, 6, 0}, { 4, 5, 1}, { 4, 4, -1}, { 4, 2, 2}, + { 4, 1, -2}, { 4, 0, 3}, { 5, 31, -3}, { 5, 29, 4}, + { 5, 28, -4}, { 5, 27, 5}, { 5, 26, -5}, { 5, 24, 6}, + { 5, 23, -6}, { 5, 21, 7}, { 5, 20, -7}, { 5, 18, 8}, + { 5, 17, -8}, { 5, 14, 9}, { 5, 7, -9}, { 5, 6, 10}, + { 6, 61,-10}, { 6, 50, 11}, { 6, 45,-11}, { 6, 38, 12}, + { 6, 33,-12}, { 6, 31, 13}, { 6, 30,-13}, { 7, 120, 14}, + { 7, 103,-14}, { 7, 89, 15}, { 7, 88,-15}, { 7, 65, 16}, + { 7, 64,-16}, { 8, 205, 17}, { 8, 204,-17}, { 8, 157, 18}, + { 8, 156,-18}, { 9, 486, 19}, { 9, 485,-19}, { 9, 318, 20}, + { 9, 317,-20}, {10, 975, 21}, {10, 974,-21}, {10, 639, 22}, + {10, 638,-22}, {11, 1939, 23}, {11, 1938,-23}, {11, 1936, 24}, + {11, 1267,-24}, {11, 1264, 25}, {12, 3875,-25}, {12, 2532, 26}, + {12, 2531,-26}, {13, 7749, 27}, {13, 7748,-27}, {13, 5061, 28}, + {13, 5060,-28}, {14, 10133, 29}, {14, 10132,-29}, {15, 20269, 30}, + {15, 20268,-30}, {16, 40543, 31}, {16, 40542,-31}, {16, 40541, 32}, {16, 40540,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_b_65[] = { - { 4, 4, 0}, { 4, 2, 1}, { 4, 1, -1}, { 5, 30, 2}, - { 5, 29, -2}, { 5, 26, 3}, { 5, 25, -3}, { 5, 23, 4}, - { 5, 22, -4}, { 5, 19, 5}, { 5, 18, -5}, { 5, 16, 6}, - { 5, 15, -6}, { 5, 12, 7}, { 5, 11, -7}, { 5, 7, 8}, - { 5, 6, -8}, { 6, 63, 9}, { 6, 62, -9}, { 6, 56, 10}, - { 6, 55,-10}, { 6, 49, 11}, { 6, 48,-11}, { 6, 41, 12}, - { 6, 40,-12}, { 6, 34, 13}, { 6, 29,-13}, { 6, 26, 14}, - { 6, 21,-14}, { 6, 20, 15}, { 6, 3,-15}, { 6, 0, 16}, - { 7, 115,-16}, { 7, 109, 17}, { 7, 108,-17}, { 7, 86, 18}, - { 7, 85,-18}, { 7, 70, 19}, { 7, 57,-19}, { 7, 56, 20}, - { 7, 55,-20}, { 7, 4, 21}, { 7, 3,-21}, { 8, 229, 22}, - { 8, 228,-22}, { 8, 175, 23}, { 8, 174,-23}, { 8, 143, 24}, - { 8, 142,-24}, { 8, 108, 25}, { 8, 11,-25}, { 8, 10, 26}, - { 8, 5,-26}, { 9, 339, 27}, { 9, 338,-27}, { 9, 336, 28}, - { 9, 219,-28}, { 9, 9, 29}, { 9, 8,-29}, {10, 674, 30}, - {10, 437,-30}, {10, 436, 31}, {11, 1351,-31}, {12, 2701, 32}, + { 4, 4, 0}, { 4, 2, 1}, { 4, 1, -1}, { 5, 30, 2}, + { 5, 29, -2}, { 5, 26, 3}, { 5, 25, -3}, { 5, 23, 4}, + { 5, 22, -4}, { 5, 19, 5}, { 5, 18, -5}, { 5, 16, 6}, + { 5, 15, -6}, { 5, 12, 7}, { 5, 11, -7}, { 5, 7, 8}, + { 5, 6, -8}, { 6, 63, 9}, { 6, 62, -9}, { 6, 56, 10}, + { 6, 55,-10}, { 6, 49, 11}, { 6, 48,-11}, { 6, 41, 12}, + { 6, 40,-12}, { 6, 34, 13}, { 6, 29,-13}, { 6, 26, 14}, + { 6, 21,-14}, { 6, 20, 15}, { 6, 3,-15}, { 6, 0, 16}, + { 7, 115,-16}, { 7, 109, 17}, { 7, 108,-17}, { 7, 86, 18}, + { 7, 85,-18}, { 7, 70, 19}, { 7, 57,-19}, { 7, 56, 20}, + { 7, 55,-20}, { 7, 4, 21}, { 7, 3,-21}, { 8, 229, 22}, + { 8, 228,-22}, { 8, 175, 23}, { 8, 174,-23}, { 8, 143, 24}, + { 8, 142,-24}, { 8, 108, 25}, { 8, 11,-25}, { 8, 10, 26}, + { 8, 5,-26}, { 9, 339, 27}, { 9, 338,-27}, { 9, 336, 28}, + { 9, 219,-28}, { 9, 9, 29}, { 9, 8,-29}, {10, 674, 30}, + {10, 437,-30}, {10, 436, 31}, {11, 1351,-31}, {12, 2701, 32}, {12, 2700,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_c_65[] = { - { 5, 28, 0}, { 5, 25, 1}, { 5, 24, -1}, { 5, 23, 2}, - { 5, 22, -2}, { 5, 19, 3}, { 5, 18, -3}, { 5, 16, 4}, - { 5, 15, -4}, { 5, 13, 5}, { 5, 12, -5}, { 5, 10, 6}, - { 5, 9, -6}, { 5, 7, 7}, { 5, 6, -7}, { 5, 4, 8}, - { 5, 3, -8}, { 5, 1, 9}, { 5, 0, -9}, { 6, 62, 10}, - { 6, 61,-10}, { 6, 59, 11}, { 6, 58,-11}, { 6, 54, 12}, - { 6, 53,-12}, { 6, 43, 13}, { 6, 42,-13}, { 6, 40, 14}, - { 6, 35,-14}, { 6, 29, 15}, { 6, 28,-15}, { 6, 17, 16}, - { 6, 16,-16}, { 6, 11, 17}, { 6, 10,-17}, { 6, 4, 18}, - { 7, 127,-18}, { 7, 121, 19}, { 7, 120,-19}, { 7, 110, 20}, - { 7, 105,-20}, { 7, 83, 21}, { 7, 82,-21}, { 7, 68, 22}, - { 7, 47,-22}, { 7, 46, 23}, { 7, 45,-23}, { 7, 11, 24}, - { 7, 10,-24}, { 8, 252, 25}, { 8, 223,-25}, { 8, 209, 26}, - { 8, 208,-26}, { 8, 138, 27}, { 8, 89,-27}, { 8, 88, 28}, - { 9, 507,-28}, { 9, 445, 29}, { 9, 444,-29}, { 9, 278, 30}, - {10, 1013,-30}, {10, 1012, 31}, {10, 559,-31}, {11, 1117, 32}, + { 5, 28, 0}, { 5, 25, 1}, { 5, 24, -1}, { 5, 23, 2}, + { 5, 22, -2}, { 5, 19, 3}, { 5, 18, -3}, { 5, 16, 4}, + { 5, 15, -4}, { 5, 13, 5}, { 5, 12, -5}, { 5, 10, 6}, + { 5, 9, -6}, { 5, 7, 7}, { 5, 6, -7}, { 5, 4, 8}, + { 5, 3, -8}, { 5, 1, 9}, { 5, 0, -9}, { 6, 62, 10}, + { 6, 61,-10}, { 6, 59, 11}, { 6, 58,-11}, { 6, 54, 12}, + { 6, 53,-12}, { 6, 43, 13}, { 6, 42,-13}, { 6, 40, 14}, + { 6, 35,-14}, { 6, 29, 15}, { 6, 28,-15}, { 6, 17, 16}, + { 6, 16,-16}, { 6, 11, 17}, { 6, 10,-17}, { 6, 4, 18}, + { 7, 127,-18}, { 7, 121, 19}, { 7, 120,-19}, { 7, 110, 20}, + { 7, 105,-20}, { 7, 83, 21}, { 7, 82,-21}, { 7, 68, 22}, + { 7, 47,-22}, { 7, 46, 23}, { 7, 45,-23}, { 7, 11, 24}, + { 7, 10,-24}, { 8, 252, 25}, { 8, 223,-25}, { 8, 209, 26}, + { 8, 208,-26}, { 8, 138, 27}, { 8, 89,-27}, { 8, 88, 28}, + { 9, 507,-28}, { 9, 445, 29}, { 9, 444,-29}, { 9, 278, 30}, + {10, 1013,-30}, {10, 1012, 31}, {10, 559,-31}, {11, 1117, 32}, {11, 1116,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_d_65[] = { - { 3, 4, 0}, { 3, 1, 1}, { 3, 0, -1}, { 4, 13, 2}, - { 4, 12, -2}, { 4, 7, 3}, { 4, 6, -3}, { 5, 31, 4}, - { 5, 30, -4}, { 5, 23, 5}, { 5, 22, -5}, { 5, 11, 6}, - { 5, 10, -6}, { 6, 59, 7}, { 6, 58, -7}, { 6, 43, 8}, - { 6, 42, -8}, { 6, 19, 9}, { 6, 18, -9}, { 7, 115, 10}, - { 7, 114,-10}, { 7, 83, 11}, { 7, 82,-11}, { 7, 35, 12}, - { 7, 34,-12}, { 8, 227, 13}, { 8, 226,-13}, { 8, 163, 14}, - { 8, 162,-14}, { 8, 160, 15}, { 8, 67,-15}, { 8, 64, 16}, - { 9, 451,-16}, { 9, 448, 17}, { 9, 323,-17}, { 9, 132, 18}, - { 9, 131,-18}, {10, 900, 19}, {10, 899,-19}, {10, 644, 20}, - {10, 267,-20}, {10, 261, 21}, {10, 260,-21}, {11, 1797, 22}, - {11, 1796,-22}, {11, 533, 23}, {11, 532,-23}, {12, 3605, 24}, - {12, 3604,-24}, {12, 2582, 25}, {12, 2581,-25}, {13, 7215, 26}, - {13, 7214,-26}, {13, 5167, 27}, {13, 5166,-27}, {13, 5160, 28}, - {14, 14427,-28}, {14, 10323, 29}, {14, 10322,-29}, {15, 28853, 30}, - {15, 28852,-30}, {15, 28851, 31}, {15, 28850,-31}, {15, 28849, 32}, + { 3, 4, 0}, { 3, 1, 1}, { 3, 0, -1}, { 4, 13, 2}, + { 4, 12, -2}, { 4, 7, 3}, { 4, 6, -3}, { 5, 31, 4}, + { 5, 30, -4}, { 5, 23, 5}, { 5, 22, -5}, { 5, 11, 6}, + { 5, 10, -6}, { 6, 59, 7}, { 6, 58, -7}, { 6, 43, 8}, + { 6, 42, -8}, { 6, 19, 9}, { 6, 18, -9}, { 7, 115, 10}, + { 7, 114,-10}, { 7, 83, 11}, { 7, 82,-11}, { 7, 35, 12}, + { 7, 34,-12}, { 8, 227, 13}, { 8, 226,-13}, { 8, 163, 14}, + { 8, 162,-14}, { 8, 160, 15}, { 8, 67,-15}, { 8, 64, 16}, + { 9, 451,-16}, { 9, 448, 17}, { 9, 323,-17}, { 9, 132, 18}, + { 9, 131,-18}, {10, 900, 19}, {10, 899,-19}, {10, 644, 20}, + {10, 267,-20}, {10, 261, 21}, {10, 260,-21}, {11, 1797, 22}, + {11, 1796,-22}, {11, 533, 23}, {11, 532,-23}, {12, 3605, 24}, + {12, 3604,-24}, {12, 2582, 25}, {12, 2581,-25}, {13, 7215, 26}, + {13, 7214,-26}, {13, 5167, 27}, {13, 5166,-27}, {13, 5160, 28}, + {14, 14427,-28}, {14, 10323, 29}, {14, 10322,-29}, {15, 28853, 30}, + {15, 28852,-30}, {15, 28851, 31}, {15, 28850,-31}, {15, 28849, 32}, {15, 28848,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_e_65[] = { - { 3, 4, 0}, { 3, 0, 1}, { 4, 15, -1}, { 4, 7, 2}, - { 4, 6, -2}, { 5, 29, 3}, { 5, 28, -3}, { 5, 23, 4}, - { 5, 22, -4}, { 5, 10, 5}, { 5, 9, -5}, { 5, 6, 6}, - { 5, 5, -6}, { 6, 54, 7}, { 6, 53, -7}, { 6, 48, 8}, - { 6, 43, -8}, { 6, 40, 9}, { 6, 23, -9}, { 6, 16, 10}, - { 6, 15,-10}, { 6, 9, 11}, { 6, 8,-11}, { 7, 105, 12}, - { 7, 104,-12}, { 7, 100, 13}, { 7, 99,-13}, { 7, 84, 14}, - { 7, 83,-14}, { 7, 45, 15}, { 7, 44,-15}, { 7, 29, 16}, - { 7, 28,-16}, { 8, 221, 17}, { 8, 220,-17}, { 8, 206, 18}, - { 8, 205,-18}, { 8, 202, 19}, { 8, 197,-19}, { 8, 171, 20}, - { 8, 170,-20}, { 8, 164, 21}, { 8, 71,-21}, { 8, 69, 22}, - { 8, 68,-22}, { 9, 446, 23}, { 9, 445,-23}, { 9, 415, 24}, - { 9, 414,-24}, { 9, 408, 25}, { 9, 407,-25}, { 9, 393, 26}, - { 9, 392,-26}, { 9, 331, 27}, { 9, 330,-27}, { 9, 141, 28}, - { 9, 140,-28}, {10, 895, 29}, {10, 894,-29}, {10, 889, 30}, - {10, 888,-30}, {10, 819, 31}, {10, 818,-31}, {10, 813, 32}, + { 3, 4, 0}, { 3, 0, 1}, { 4, 15, -1}, { 4, 7, 2}, + { 4, 6, -2}, { 5, 29, 3}, { 5, 28, -3}, { 5, 23, 4}, + { 5, 22, -4}, { 5, 10, 5}, { 5, 9, -5}, { 5, 6, 6}, + { 5, 5, -6}, { 6, 54, 7}, { 6, 53, -7}, { 6, 48, 8}, + { 6, 43, -8}, { 6, 40, 9}, { 6, 23, -9}, { 6, 16, 10}, + { 6, 15,-10}, { 6, 9, 11}, { 6, 8,-11}, { 7, 105, 12}, + { 7, 104,-12}, { 7, 100, 13}, { 7, 99,-13}, { 7, 84, 14}, + { 7, 83,-14}, { 7, 45, 15}, { 7, 44,-15}, { 7, 29, 16}, + { 7, 28,-16}, { 8, 221, 17}, { 8, 220,-17}, { 8, 206, 18}, + { 8, 205,-18}, { 8, 202, 19}, { 8, 197,-19}, { 8, 171, 20}, + { 8, 170,-20}, { 8, 164, 21}, { 8, 71,-21}, { 8, 69, 22}, + { 8, 68,-22}, { 9, 446, 23}, { 9, 445,-23}, { 9, 415, 24}, + { 9, 414,-24}, { 9, 408, 25}, { 9, 407,-25}, { 9, 393, 26}, + { 9, 392,-26}, { 9, 331, 27}, { 9, 330,-27}, { 9, 141, 28}, + { 9, 140,-28}, {10, 895, 29}, {10, 894,-29}, {10, 889, 30}, + {10, 888,-30}, {10, 819, 31}, {10, 818,-31}, {10, 813, 32}, {10, 812,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_f_65[] = { - { 3, 6, 0}, { 3, 3, 1}, { 3, 2, -1}, { 4, 15, 2}, - { 4, 14, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 1, 4}, - { 4, 0, -4}, { 5, 21, 5}, { 5, 20, -5}, { 5, 5, 6}, - { 5, 4, -6}, { 6, 45, 7}, { 6, 44, -7}, { 6, 13, 8}, - { 6, 12, -8}, { 7, 93, 9}, { 7, 92, -9}, { 7, 29, 10}, - { 7, 28,-10}, { 8, 189, 11}, { 8, 188,-11}, { 8, 61, 12}, - { 8, 60,-12}, { 9, 381, 13}, { 9, 380,-13}, { 9, 125, 14}, - { 9, 124,-14}, {10, 765, 15}, {10, 764,-15}, {10, 252, 16}, - {11, 1535,-16}, {11, 1532, 17}, {11, 511,-17}, {11, 506, 18}, - {12, 3069,-18}, {12, 3067, 19}, {12, 3066,-19}, {12, 1015, 20}, - {12, 1014,-20}, {13, 6136, 21}, {13, 2043,-21}, {13, 2035, 22}, - {13, 2034,-22}, {14, 12275, 23}, {14, 12274,-23}, {14, 4085, 24}, - {14, 4084,-24}, {14, 4083, 25}, {14, 4082,-25}, {14, 4081, 26}, - {14, 4080,-26}, {14, 4079, 27}, {14, 4078,-27}, {14, 4077, 28}, - {14, 4076,-28}, {14, 4075, 29}, {14, 4074,-29}, {14, 4073, 30}, - {14, 4072,-30}, {14, 4067, 31}, {14, 4066,-31}, {14, 4065, 32}, + { 3, 6, 0}, { 3, 3, 1}, { 3, 2, -1}, { 4, 15, 2}, + { 4, 14, -2}, { 4, 9, 3}, { 4, 8, -3}, { 4, 1, 4}, + { 4, 0, -4}, { 5, 21, 5}, { 5, 20, -5}, { 5, 5, 6}, + { 5, 4, -6}, { 6, 45, 7}, { 6, 44, -7}, { 6, 13, 8}, + { 6, 12, -8}, { 7, 93, 9}, { 7, 92, -9}, { 7, 29, 10}, + { 7, 28,-10}, { 8, 189, 11}, { 8, 188,-11}, { 8, 61, 12}, + { 8, 60,-12}, { 9, 381, 13}, { 9, 380,-13}, { 9, 125, 14}, + { 9, 124,-14}, {10, 765, 15}, {10, 764,-15}, {10, 252, 16}, + {11, 1535,-16}, {11, 1532, 17}, {11, 511,-17}, {11, 506, 18}, + {12, 3069,-18}, {12, 3067, 19}, {12, 3066,-19}, {12, 1015, 20}, + {12, 1014,-20}, {13, 6136, 21}, {13, 2043,-21}, {13, 2035, 22}, + {13, 2034,-22}, {14, 12275, 23}, {14, 12274,-23}, {14, 4085, 24}, + {14, 4084,-24}, {14, 4083, 25}, {14, 4082,-25}, {14, 4081, 26}, + {14, 4080,-26}, {14, 4079, 27}, {14, 4078,-27}, {14, 4077, 28}, + {14, 4076,-28}, {14, 4075, 29}, {14, 4074,-29}, {14, 4073, 30}, + {14, 4072,-30}, {14, 4067, 31}, {14, 4066,-31}, {14, 4065, 32}, {14, 4064,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_g_65[] = { - { 4, 14, 0}, { 4, 11, 1}, { 4, 10, -1}, { 4, 8, 2}, - { 4, 6, -2}, { 4, 4, 3}, { 4, 3, -3}, { 4, 0, 4}, - { 5, 31, -4}, { 5, 26, 5}, { 5, 25, -5}, { 5, 18, 6}, - { 5, 15, -6}, { 5, 10, 7}, { 5, 5, -7}, { 5, 2, 8}, - { 6, 61, -8}, { 6, 54, 9}, { 6, 49, -9}, { 6, 38, 10}, - { 6, 29,-10}, { 6, 22, 11}, { 6, 9,-11}, { 6, 6, 12}, - { 7, 121,-12}, { 7, 110, 13}, { 7, 97,-13}, { 7, 78, 14}, - { 7, 57,-14}, { 7, 46, 15}, { 7, 17,-15}, { 7, 14, 16}, - { 8, 241,-16}, { 8, 223, 17}, { 8, 222,-17}, { 8, 159, 18}, - { 8, 158,-18}, { 8, 95, 19}, { 8, 94,-19}, { 8, 31, 20}, - { 8, 30,-20}, { 9, 480, 21}, { 9, 387,-21}, { 9, 384, 22}, - { 9, 227,-22}, { 9, 225, 23}, { 9, 224,-23}, { 9, 65, 24}, - { 9, 64,-24}, {10, 962, 25}, {10, 773,-25}, {10, 771, 26}, - {10, 770,-26}, {10, 452, 27}, {10, 135,-27}, {10, 133, 28}, - {10, 132,-28}, {11, 1927, 29}, {11, 1926,-29}, {11, 1545, 30}, - {11, 1544,-30}, {11, 907, 31}, {11, 906,-31}, {11, 269, 32}, + { 4, 14, 0}, { 4, 11, 1}, { 4, 10, -1}, { 4, 8, 2}, + { 4, 6, -2}, { 4, 4, 3}, { 4, 3, -3}, { 4, 0, 4}, + { 5, 31, -4}, { 5, 26, 5}, { 5, 25, -5}, { 5, 18, 6}, + { 5, 15, -6}, { 5, 10, 7}, { 5, 5, -7}, { 5, 2, 8}, + { 6, 61, -8}, { 6, 54, 9}, { 6, 49, -9}, { 6, 38, 10}, + { 6, 29,-10}, { 6, 22, 11}, { 6, 9,-11}, { 6, 6, 12}, + { 7, 121,-12}, { 7, 110, 13}, { 7, 97,-13}, { 7, 78, 14}, + { 7, 57,-14}, { 7, 46, 15}, { 7, 17,-15}, { 7, 14, 16}, + { 8, 241,-16}, { 8, 223, 17}, { 8, 222,-17}, { 8, 159, 18}, + { 8, 158,-18}, { 8, 95, 19}, { 8, 94,-19}, { 8, 31, 20}, + { 8, 30,-20}, { 9, 480, 21}, { 9, 387,-21}, { 9, 384, 22}, + { 9, 227,-22}, { 9, 225, 23}, { 9, 224,-23}, { 9, 65, 24}, + { 9, 64,-24}, {10, 962, 25}, {10, 773,-25}, {10, 771, 26}, + {10, 770,-26}, {10, 452, 27}, {10, 135,-27}, {10, 133, 28}, + {10, 132,-28}, {11, 1927, 29}, {11, 1926,-29}, {11, 1545, 30}, + {11, 1544,-30}, {11, 907, 31}, {11, 906,-31}, {11, 269, 32}, {11, 268,-32}, { 0, 0, 0} }; huff_entry_t bitalloc_a_129[] = { - { 4, 8, 0}, { 4, 10, 1}, { 4, 9, -1}, { 4, 0, 2}, - { 5, 31, -2}, { 5, 24, 3}, { 5, 23, -3}, { 5, 12, 4}, - { 5, 11, -4}, { 5, 5, 5}, { 5, 4, -5}, { 6, 60, 6}, - { 6, 58, -6}, { 6, 54, 7}, { 6, 53, -7}, { 6, 45, 8}, - { 6, 44, -8}, { 6, 28, 9}, { 6, 27, -9}, { 6, 19, 10}, - { 6, 18,-10}, { 6, 14, 11}, { 6, 13,-11}, { 6, 6, 12}, - { 6, 5,-12}, { 7, 122, 13}, { 7, 119,-13}, { 7, 113, 14}, - { 7, 112,-14}, { 7, 104, 15}, { 7, 103,-15}, { 7, 100, 16}, - { 7, 63,-16}, { 7, 60, 17}, { 7, 59,-17}, { 7, 52, 18}, - { 7, 43,-18}, { 7, 40, 19}, { 7, 35,-19}, { 7, 32, 20}, - { 7, 31,-20}, { 7, 15, 21}, { 7, 14,-21}, { 8, 247, 22}, - { 8, 246,-22}, { 8, 231, 23}, { 8, 230,-23}, { 8, 223, 24}, - { 8, 222,-24}, { 8, 211, 25}, { 8, 210,-25}, { 8, 203, 26}, - { 8, 202,-26}, { 8, 123, 27}, { 8, 122,-27}, { 8, 116, 28}, - { 8, 107,-28}, { 8, 84, 29}, { 8, 83,-29}, { 8, 68, 30}, - { 8, 67,-30}, { 8, 60, 31}, { 8, 51,-31}, { 8, 49, 32}, - { 8, 48,-32}, { 8, 17, 33}, { 8, 16,-33}, { 9, 474, 34}, - { 9, 473,-34}, { 9, 458, 35}, { 9, 457,-35}, { 9, 442, 36}, - { 9, 441,-36}, { 9, 411, 37}, { 9, 410,-37}, { 9, 251, 38}, - { 9, 250,-38}, { 9, 248, 39}, { 9, 235,-39}, { 9, 213, 40}, - { 9, 212,-40}, { 9, 170, 41}, { 9, 165,-41}, { 9, 139, 42}, - { 9, 138,-42}, { 9, 132, 43}, { 9, 123,-43}, { 9, 101, 44}, - { 9, 100,-44}, { 9, 37, 45}, { 9, 36,-45}, {10, 950, 46}, - {10, 945,-46}, {10, 919, 47}, {10, 918,-47}, {10, 912, 48}, - {10, 887,-48}, {10, 881, 49}, {10, 880,-49}, {10, 818, 50}, - {10, 817,-50}, {10, 499, 51}, {10, 498,-51}, {10, 469, 52}, - {10, 468,-52}, {10, 343, 53}, {10, 342,-53}, {10, 329, 54}, - {10, 328,-54}, {10, 267, 55}, {10, 266,-55}, {10, 245, 56}, - {10, 244,-56}, {10, 79, 57}, {10, 78,-57}, {10, 77, 58}, - {10, 76,-58}, {11, 1903, 59}, {11, 1902,-59}, {11, 1889, 60}, - {11, 1888,-60}, {11, 1827, 61}, {11, 1826,-61}, {11, 1773, 62}, - {11, 1772,-62}, {11, 1639, 63}, {11, 1638,-63}, {11, 1633, 64}, + { 4, 8, 0}, { 4, 10, 1}, { 4, 9, -1}, { 4, 0, 2}, + { 5, 31, -2}, { 5, 24, 3}, { 5, 23, -3}, { 5, 12, 4}, + { 5, 11, -4}, { 5, 5, 5}, { 5, 4, -5}, { 6, 60, 6}, + { 6, 58, -6}, { 6, 54, 7}, { 6, 53, -7}, { 6, 45, 8}, + { 6, 44, -8}, { 6, 28, 9}, { 6, 27, -9}, { 6, 19, 10}, + { 6, 18,-10}, { 6, 14, 11}, { 6, 13,-11}, { 6, 6, 12}, + { 6, 5,-12}, { 7, 122, 13}, { 7, 119,-13}, { 7, 113, 14}, + { 7, 112,-14}, { 7, 104, 15}, { 7, 103,-15}, { 7, 100, 16}, + { 7, 63,-16}, { 7, 60, 17}, { 7, 59,-17}, { 7, 52, 18}, + { 7, 43,-18}, { 7, 40, 19}, { 7, 35,-19}, { 7, 32, 20}, + { 7, 31,-20}, { 7, 15, 21}, { 7, 14,-21}, { 8, 247, 22}, + { 8, 246,-22}, { 8, 231, 23}, { 8, 230,-23}, { 8, 223, 24}, + { 8, 222,-24}, { 8, 211, 25}, { 8, 210,-25}, { 8, 203, 26}, + { 8, 202,-26}, { 8, 123, 27}, { 8, 122,-27}, { 8, 116, 28}, + { 8, 107,-28}, { 8, 84, 29}, { 8, 83,-29}, { 8, 68, 30}, + { 8, 67,-30}, { 8, 60, 31}, { 8, 51,-31}, { 8, 49, 32}, + { 8, 48,-32}, { 8, 17, 33}, { 8, 16,-33}, { 9, 474, 34}, + { 9, 473,-34}, { 9, 458, 35}, { 9, 457,-35}, { 9, 442, 36}, + { 9, 441,-36}, { 9, 411, 37}, { 9, 410,-37}, { 9, 251, 38}, + { 9, 250,-38}, { 9, 248, 39}, { 9, 235,-39}, { 9, 213, 40}, + { 9, 212,-40}, { 9, 170, 41}, { 9, 165,-41}, { 9, 139, 42}, + { 9, 138,-42}, { 9, 132, 43}, { 9, 123,-43}, { 9, 101, 44}, + { 9, 100,-44}, { 9, 37, 45}, { 9, 36,-45}, {10, 950, 46}, + {10, 945,-46}, {10, 919, 47}, {10, 918,-47}, {10, 912, 48}, + {10, 887,-48}, {10, 881, 49}, {10, 880,-49}, {10, 818, 50}, + {10, 817,-50}, {10, 499, 51}, {10, 498,-51}, {10, 469, 52}, + {10, 468,-52}, {10, 343, 53}, {10, 342,-53}, {10, 329, 54}, + {10, 328,-54}, {10, 267, 55}, {10, 266,-55}, {10, 245, 56}, + {10, 244,-56}, {10, 79, 57}, {10, 78,-57}, {10, 77, 58}, + {10, 76,-58}, {11, 1903, 59}, {11, 1902,-59}, {11, 1889, 60}, + {11, 1888,-60}, {11, 1827, 61}, {11, 1826,-61}, {11, 1773, 62}, + {11, 1772,-62}, {11, 1639, 63}, {11, 1638,-63}, {11, 1633, 64}, {11, 1632,-64}, { 0, 0, 0} }; huff_entry_t bitalloc_b_129[] = { - { 5, 10, 0}, { 5, 7, 1}, { 5, 6, -1}, { 5, 4, 2}, - { 5, 3, -2}, { 5, 0, 3}, { 6, 63, -3}, { 6, 60, 4}, - { 6, 59, -4}, { 6, 57, 5}, { 6, 56, -5}, { 6, 53, 6}, - { 6, 52, -6}, { 6, 50, 7}, { 6, 49, -7}, { 6, 46, 8}, - { 6, 45, -8}, { 6, 43, 9}, { 6, 42, -9}, { 6, 39, 10}, - { 6, 38,-10}, { 6, 35, 11}, { 6, 34,-11}, { 6, 32, 12}, - { 6, 31,-12}, { 6, 28, 13}, { 6, 27,-13}, { 6, 25, 14}, - { 6, 24,-14}, { 6, 22, 15}, { 6, 19,-15}, { 6, 16, 16}, - { 6, 11,-16}, { 6, 5, 17}, { 6, 4,-17}, { 7, 125, 18}, - { 7, 124,-18}, { 7, 122, 19}, { 7, 117,-19}, { 7, 110, 20}, - { 7, 109,-20}, { 7, 103, 21}, { 7, 102,-21}, { 7, 96, 22}, - { 7, 95,-22}, { 7, 89, 23}, { 7, 88,-23}, { 7, 81, 24}, - { 7, 80,-24}, { 7, 74, 25}, { 7, 73,-25}, { 7, 66, 26}, - { 7, 61,-26}, { 7, 59, 27}, { 7, 58,-27}, { 7, 52, 28}, - { 7, 47,-28}, { 7, 37, 29}, { 7, 36,-29}, { 7, 21, 30}, - { 7, 20,-30}, { 7, 6, 31}, { 7, 5,-31}, { 8, 247, 32}, - { 8, 246,-32}, { 8, 223, 33}, { 8, 222,-33}, { 8, 217, 34}, - { 8, 216,-34}, { 8, 189, 35}, { 8, 188,-35}, { 8, 166, 36}, - { 8, 165,-36}, { 8, 151, 37}, { 8, 150,-37}, { 8, 144, 38}, - { 8, 135,-38}, { 8, 121, 39}, { 8, 120,-39}, { 8, 106, 40}, - { 8, 93,-40}, { 8, 71, 41}, { 8, 70,-41}, { 8, 68, 42}, - { 8, 15,-42}, { 8, 9, 43}, { 8, 8,-43}, { 9, 466, 44}, - { 9, 465,-44}, { 9, 391, 45}, { 9, 390,-45}, { 9, 388, 46}, - { 9, 335,-46}, { 9, 329, 47}, { 9, 328,-47}, { 9, 269, 48}, - { 9, 268,-48}, { 9, 215, 49}, { 9, 214,-49}, { 9, 184, 50}, - { 9, 139,-50}, { 9, 29, 51}, { 9, 28,-51}, {10, 934, 52}, - {10, 929,-52}, {10, 779, 53}, {10, 778,-53}, {10, 668, 54}, - {10, 583,-54}, {10, 582, 55}, {10, 581,-55}, {10, 371, 56}, - {10, 370,-56}, {10, 276, 57}, {11, 1871,-57}, {11, 1857, 58}, - {11, 1856,-58}, {11, 1338, 59}, {11, 1161,-59}, {11, 1160, 60}, - {11, 555,-60}, {12, 3741, 61}, {12, 3740,-61}, {12, 2678, 62}, - {12, 1109,-62}, {12, 1108, 63}, {13, 5359,-63}, {14, 10717, 64}, + { 5, 10, 0}, { 5, 7, 1}, { 5, 6, -1}, { 5, 4, 2}, + { 5, 3, -2}, { 5, 0, 3}, { 6, 63, -3}, { 6, 60, 4}, + { 6, 59, -4}, { 6, 57, 5}, { 6, 56, -5}, { 6, 53, 6}, + { 6, 52, -6}, { 6, 50, 7}, { 6, 49, -7}, { 6, 46, 8}, + { 6, 45, -8}, { 6, 43, 9}, { 6, 42, -9}, { 6, 39, 10}, + { 6, 38,-10}, { 6, 35, 11}, { 6, 34,-11}, { 6, 32, 12}, + { 6, 31,-12}, { 6, 28, 13}, { 6, 27,-13}, { 6, 25, 14}, + { 6, 24,-14}, { 6, 22, 15}, { 6, 19,-15}, { 6, 16, 16}, + { 6, 11,-16}, { 6, 5, 17}, { 6, 4,-17}, { 7, 125, 18}, + { 7, 124,-18}, { 7, 122, 19}, { 7, 117,-19}, { 7, 110, 20}, + { 7, 109,-20}, { 7, 103, 21}, { 7, 102,-21}, { 7, 96, 22}, + { 7, 95,-22}, { 7, 89, 23}, { 7, 88,-23}, { 7, 81, 24}, + { 7, 80,-24}, { 7, 74, 25}, { 7, 73,-25}, { 7, 66, 26}, + { 7, 61,-26}, { 7, 59, 27}, { 7, 58,-27}, { 7, 52, 28}, + { 7, 47,-28}, { 7, 37, 29}, { 7, 36,-29}, { 7, 21, 30}, + { 7, 20,-30}, { 7, 6, 31}, { 7, 5,-31}, { 8, 247, 32}, + { 8, 246,-32}, { 8, 223, 33}, { 8, 222,-33}, { 8, 217, 34}, + { 8, 216,-34}, { 8, 189, 35}, { 8, 188,-35}, { 8, 166, 36}, + { 8, 165,-36}, { 8, 151, 37}, { 8, 150,-37}, { 8, 144, 38}, + { 8, 135,-38}, { 8, 121, 39}, { 8, 120,-39}, { 8, 106, 40}, + { 8, 93,-40}, { 8, 71, 41}, { 8, 70,-41}, { 8, 68, 42}, + { 8, 15,-42}, { 8, 9, 43}, { 8, 8,-43}, { 9, 466, 44}, + { 9, 465,-44}, { 9, 391, 45}, { 9, 390,-45}, { 9, 388, 46}, + { 9, 335,-46}, { 9, 329, 47}, { 9, 328,-47}, { 9, 269, 48}, + { 9, 268,-48}, { 9, 215, 49}, { 9, 214,-49}, { 9, 184, 50}, + { 9, 139,-50}, { 9, 29, 51}, { 9, 28,-51}, {10, 934, 52}, + {10, 929,-52}, {10, 779, 53}, {10, 778,-53}, {10, 668, 54}, + {10, 583,-54}, {10, 582, 55}, {10, 581,-55}, {10, 371, 56}, + {10, 370,-56}, {10, 276, 57}, {11, 1871,-57}, {11, 1857, 58}, + {11, 1856,-58}, {11, 1338, 59}, {11, 1161,-59}, {11, 1160, 60}, + {11, 555,-60}, {12, 3741, 61}, {12, 3740,-61}, {12, 2678, 62}, + {12, 1109,-62}, {12, 1108, 63}, {13, 5359,-63}, {14, 10717, 64}, {14, 10716,-64}, { 0, 0, 0} }; huff_entry_t bitalloc_c_129[] = { - { 6, 58, 0}, { 6, 55, 1}, { 6, 54, -1}, { 6, 52, 2}, - { 6, 51, -2}, { 6, 49, 3}, { 6, 48, -3}, { 6, 46, 4}, - { 6, 45, -4}, { 6, 43, 5}, { 6, 42, -5}, { 6, 40, 6}, - { 6, 39, -6}, { 6, 37, 7}, { 6, 36, -7}, { 6, 34, 8}, - { 6, 33, -8}, { 6, 30, 9}, { 6, 29, -9}, { 6, 27, 10}, - { 6, 26,-10}, { 6, 24, 11}, { 6, 23,-11}, { 6, 21, 12}, - { 6, 20,-12}, { 6, 18, 13}, { 6, 17,-13}, { 6, 14, 14}, - { 6, 13,-14}, { 6, 12, 15}, { 6, 11,-15}, { 6, 8, 16}, - { 6, 7,-16}, { 6, 6, 17}, { 6, 5,-17}, { 6, 3, 18}, - { 6, 2,-18}, { 7, 127, 19}, { 7, 126,-19}, { 7, 124, 20}, - { 7, 123,-20}, { 7, 121, 21}, { 7, 120,-21}, { 7, 118, 22}, - { 7, 115,-22}, { 7, 113, 23}, { 7, 112,-23}, { 7, 106, 24}, - { 7, 101,-24}, { 7, 95, 25}, { 7, 94,-25}, { 7, 88, 26}, - { 7, 83,-26}, { 7, 77, 27}, { 7, 76,-27}, { 7, 70, 28}, - { 7, 65,-28}, { 7, 64, 29}, { 7, 63,-29}, { 7, 56, 30}, - { 7, 51,-30}, { 7, 45, 31}, { 7, 44,-31}, { 7, 39, 32}, - { 7, 38,-32}, { 7, 31, 33}, { 7, 30,-33}, { 7, 20, 34}, - { 7, 19,-34}, { 7, 18, 35}, { 7, 9,-35}, { 7, 3, 36}, - { 7, 2,-36}, { 7, 0, 37}, { 8, 251,-37}, { 8, 245, 38}, - { 8, 244,-38}, { 8, 238, 39}, { 8, 229,-39}, { 8, 215, 40}, - { 8, 214,-40}, { 8, 200, 41}, { 8, 179,-41}, { 8, 165, 42}, - { 8, 164,-42}, { 8, 143, 43}, { 8, 142,-43}, { 8, 124, 44}, - { 8, 115,-44}, { 8, 101, 45}, { 8, 100,-45}, { 8, 66, 46}, - { 8, 65,-46}, { 8, 43, 47}, { 8, 42,-47}, { 8, 17, 48}, - { 8, 16,-48}, { 8, 2, 49}, { 9, 501,-49}, { 9, 479, 50}, - { 9, 478,-50}, { 9, 456, 51}, { 9, 403,-51}, { 9, 357, 52}, - { 9, 356,-52}, { 9, 251, 53}, { 9, 250,-53}, { 9, 228, 54}, - { 9, 135,-54}, { 9, 129, 55}, { 9, 128,-55}, { 9, 6, 56}, - {10, 1001,-56}, {10, 1000, 57}, {10, 915,-57}, {10, 805, 58}, - {10, 804,-58}, {10, 458, 59}, {10, 269,-59}, {10, 268, 60}, - {10, 15,-60}, {11, 1829, 61}, {11, 1828,-61}, {11, 918, 62}, - {11, 29,-62}, {11, 28, 63}, {12, 1839,-63}, {13, 3677, 64}, + { 6, 58, 0}, { 6, 55, 1}, { 6, 54, -1}, { 6, 52, 2}, + { 6, 51, -2}, { 6, 49, 3}, { 6, 48, -3}, { 6, 46, 4}, + { 6, 45, -4}, { 6, 43, 5}, { 6, 42, -5}, { 6, 40, 6}, + { 6, 39, -6}, { 6, 37, 7}, { 6, 36, -7}, { 6, 34, 8}, + { 6, 33, -8}, { 6, 30, 9}, { 6, 29, -9}, { 6, 27, 10}, + { 6, 26,-10}, { 6, 24, 11}, { 6, 23,-11}, { 6, 21, 12}, + { 6, 20,-12}, { 6, 18, 13}, { 6, 17,-13}, { 6, 14, 14}, + { 6, 13,-14}, { 6, 12, 15}, { 6, 11,-15}, { 6, 8, 16}, + { 6, 7,-16}, { 6, 6, 17}, { 6, 5,-17}, { 6, 3, 18}, + { 6, 2,-18}, { 7, 127, 19}, { 7, 126,-19}, { 7, 124, 20}, + { 7, 123,-20}, { 7, 121, 21}, { 7, 120,-21}, { 7, 118, 22}, + { 7, 115,-22}, { 7, 113, 23}, { 7, 112,-23}, { 7, 106, 24}, + { 7, 101,-24}, { 7, 95, 25}, { 7, 94,-25}, { 7, 88, 26}, + { 7, 83,-26}, { 7, 77, 27}, { 7, 76,-27}, { 7, 70, 28}, + { 7, 65,-28}, { 7, 64, 29}, { 7, 63,-29}, { 7, 56, 30}, + { 7, 51,-30}, { 7, 45, 31}, { 7, 44,-31}, { 7, 39, 32}, + { 7, 38,-32}, { 7, 31, 33}, { 7, 30,-33}, { 7, 20, 34}, + { 7, 19,-34}, { 7, 18, 35}, { 7, 9,-35}, { 7, 3, 36}, + { 7, 2,-36}, { 7, 0, 37}, { 8, 251,-37}, { 8, 245, 38}, + { 8, 244,-38}, { 8, 238, 39}, { 8, 229,-39}, { 8, 215, 40}, + { 8, 214,-40}, { 8, 200, 41}, { 8, 179,-41}, { 8, 165, 42}, + { 8, 164,-42}, { 8, 143, 43}, { 8, 142,-43}, { 8, 124, 44}, + { 8, 115,-44}, { 8, 101, 45}, { 8, 100,-45}, { 8, 66, 46}, + { 8, 65,-46}, { 8, 43, 47}, { 8, 42,-47}, { 8, 17, 48}, + { 8, 16,-48}, { 8, 2, 49}, { 9, 501,-49}, { 9, 479, 50}, + { 9, 478,-50}, { 9, 456, 51}, { 9, 403,-51}, { 9, 357, 52}, + { 9, 356,-52}, { 9, 251, 53}, { 9, 250,-53}, { 9, 228, 54}, + { 9, 135,-54}, { 9, 129, 55}, { 9, 128,-55}, { 9, 6, 56}, + {10, 1001,-56}, {10, 1000, 57}, {10, 915,-57}, {10, 805, 58}, + {10, 804,-58}, {10, 458, 59}, {10, 269,-59}, {10, 268, 60}, + {10, 15,-60}, {11, 1829, 61}, {11, 1828,-61}, {11, 918, 62}, + {11, 29,-62}, {11, 28, 63}, {12, 1839,-63}, {13, 3677, 64}, {13, 3676,-64}, { 0, 0, 0} }; huff_entry_t bitalloc_d_129[] = { - { 4, 9, 0}, { 4, 6, 1}, { 4, 5, -1}, { 4, 2, 2}, - { 4, 1, -2}, { 5, 30, 3}, { 5, 29, -3}, { 5, 26, 4}, - { 5, 25, -4}, { 5, 22, 5}, { 5, 21, -5}, { 5, 16, 6}, - { 5, 15, -6}, { 5, 8, 7}, { 5, 7, -7}, { 5, 0, 8}, - { 6, 63, -8}, { 6, 56, 9}, { 6, 55, -9}, { 6, 48, 10}, - { 6, 47,-10}, { 6, 40, 11}, { 6, 35,-11}, { 6, 28, 12}, - { 6, 19,-12}, { 6, 12, 13}, { 6, 3,-13}, { 7, 124, 14}, - { 7, 115,-14}, { 7, 108, 15}, { 7, 99,-15}, { 7, 92, 16}, - { 7, 83,-16}, { 7, 68, 17}, { 7, 59,-17}, { 7, 36, 18}, - { 7, 27,-18}, { 7, 4, 19}, { 8, 251,-19}, { 8, 228, 20}, - { 8, 219,-20}, { 8, 196, 21}, { 8, 187,-21}, { 8, 164, 22}, - { 8, 139,-22}, { 8, 116, 23}, { 8, 75,-23}, { 8, 52, 24}, - { 8, 11,-24}, { 9, 501, 25}, { 9, 500,-25}, { 9, 437, 26}, - { 9, 436,-26}, { 9, 373, 27}, { 9, 372,-27}, { 9, 277, 28}, - { 9, 276,-28}, { 9, 149, 29}, { 9, 148,-29}, { 9, 21, 30}, - { 9, 20,-30}, {10, 917, 31}, {10, 916,-31}, {10, 789, 32}, - {10, 788,-32}, {10, 661, 33}, {10, 660,-33}, {10, 469, 34}, - {10, 468,-34}, {10, 214, 35}, {10, 213,-35}, {11, 1838, 36}, - {11, 1837,-36}, {11, 1582, 37}, {11, 1581,-37}, {11, 1326, 38}, - {11, 1325,-38}, {11, 942, 39}, {11, 941,-39}, {11, 431, 40}, - {11, 430,-40}, {12, 3679, 41}, {12, 3678,-41}, {12, 3167, 42}, - {12, 3166,-42}, {12, 3160, 43}, {12, 2655,-43}, {12, 2648, 44}, - {12, 1887,-44}, {12, 1880, 45}, {12, 851,-45}, {12, 849, 46}, - {12, 848,-46}, {13, 7346, 47}, {13, 7345,-47}, {13, 6322, 48}, - {13, 5309,-48}, {13, 3773, 49}, {13, 3772,-49}, {13, 3762, 50}, - {13, 1701,-50}, {14, 14695, 51}, {14, 14694,-51}, {14, 14688, 52}, - {14, 12647,-52}, {14, 10617, 53}, {14, 10616,-53}, {14, 10596, 54}, - {14, 7527,-54}, {14, 3401, 55}, {14, 3400,-55}, {15, 29378, 56}, - {15, 25293,-56}, {15, 21195, 57}, {15, 21194,-57}, {15, 15053, 58}, - {15, 15052,-58}, {16, 58759, 59}, {16, 58758,-59}, {16, 50585, 60}, - {16, 50584,-60}, {16, 42399, 61}, {16, 42398,-61}, {16, 42397, 62}, - {16, 42396,-62}, {16, 42395, 63}, {16, 42394,-63}, {16, 42393, 64}, + { 4, 9, 0}, { 4, 6, 1}, { 4, 5, -1}, { 4, 2, 2}, + { 4, 1, -2}, { 5, 30, 3}, { 5, 29, -3}, { 5, 26, 4}, + { 5, 25, -4}, { 5, 22, 5}, { 5, 21, -5}, { 5, 16, 6}, + { 5, 15, -6}, { 5, 8, 7}, { 5, 7, -7}, { 5, 0, 8}, + { 6, 63, -8}, { 6, 56, 9}, { 6, 55, -9}, { 6, 48, 10}, + { 6, 47,-10}, { 6, 40, 11}, { 6, 35,-11}, { 6, 28, 12}, + { 6, 19,-12}, { 6, 12, 13}, { 6, 3,-13}, { 7, 124, 14}, + { 7, 115,-14}, { 7, 108, 15}, { 7, 99,-15}, { 7, 92, 16}, + { 7, 83,-16}, { 7, 68, 17}, { 7, 59,-17}, { 7, 36, 18}, + { 7, 27,-18}, { 7, 4, 19}, { 8, 251,-19}, { 8, 228, 20}, + { 8, 219,-20}, { 8, 196, 21}, { 8, 187,-21}, { 8, 164, 22}, + { 8, 139,-22}, { 8, 116, 23}, { 8, 75,-23}, { 8, 52, 24}, + { 8, 11,-24}, { 9, 501, 25}, { 9, 500,-25}, { 9, 437, 26}, + { 9, 436,-26}, { 9, 373, 27}, { 9, 372,-27}, { 9, 277, 28}, + { 9, 276,-28}, { 9, 149, 29}, { 9, 148,-29}, { 9, 21, 30}, + { 9, 20,-30}, {10, 917, 31}, {10, 916,-31}, {10, 789, 32}, + {10, 788,-32}, {10, 661, 33}, {10, 660,-33}, {10, 469, 34}, + {10, 468,-34}, {10, 214, 35}, {10, 213,-35}, {11, 1838, 36}, + {11, 1837,-36}, {11, 1582, 37}, {11, 1581,-37}, {11, 1326, 38}, + {11, 1325,-38}, {11, 942, 39}, {11, 941,-39}, {11, 431, 40}, + {11, 430,-40}, {12, 3679, 41}, {12, 3678,-41}, {12, 3167, 42}, + {12, 3166,-42}, {12, 3160, 43}, {12, 2655,-43}, {12, 2648, 44}, + {12, 1887,-44}, {12, 1880, 45}, {12, 851,-45}, {12, 849, 46}, + {12, 848,-46}, {13, 7346, 47}, {13, 7345,-47}, {13, 6322, 48}, + {13, 5309,-48}, {13, 3773, 49}, {13, 3772,-49}, {13, 3762, 50}, + {13, 1701,-50}, {14, 14695, 51}, {14, 14694,-51}, {14, 14688, 52}, + {14, 12647,-52}, {14, 10617, 53}, {14, 10616,-53}, {14, 10596, 54}, + {14, 7527,-54}, {14, 3401, 55}, {14, 3400,-55}, {15, 29378, 56}, + {15, 25293,-56}, {15, 21195, 57}, {15, 21194,-57}, {15, 15053, 58}, + {15, 15052,-58}, {16, 58759, 59}, {16, 58758,-59}, {16, 50585, 60}, + {16, 50584,-60}, {16, 42399, 61}, {16, 42398,-61}, {16, 42397, 62}, + {16, 42396,-62}, {16, 42395, 63}, {16, 42394,-63}, {16, 42393, 64}, {16, 42392,-64}, { 0, 0, 0} }; huff_entry_t bitalloc_e_129[] = { - { 5, 12, 0}, { 5, 11, 1}, { 5, 10, -1}, { 5, 9, 2}, - { 5, 8, -2}, { 5, 7, 3}, { 5, 6, -3}, { 5, 4, 4}, - { 5, 3, -4}, { 5, 2, 5}, { 5, 1, -5}, { 5, 0, 6}, - { 6, 63, -6}, { 6, 61, 7}, { 6, 60, -7}, { 6, 59, 8}, - { 6, 58, -8}, { 6, 56, 9}, { 6, 55, -9}, { 6, 53, 10}, - { 6, 52,-10}, { 6, 51, 11}, { 6, 50,-11}, { 6, 47, 12}, - { 6, 46,-12}, { 6, 45, 13}, { 6, 44,-13}, { 6, 42, 14}, - { 6, 41,-14}, { 6, 38, 15}, { 6, 37,-15}, { 6, 36, 16}, - { 6, 35,-16}, { 6, 32, 17}, { 6, 31,-17}, { 6, 29, 18}, - { 6, 28,-18}, { 6, 26, 19}, { 6, 11,-19}, { 7, 125, 20}, - { 7, 124,-20}, { 7, 109, 21}, { 7, 108,-21}, { 7, 98, 22}, - { 7, 97,-22}, { 7, 87, 23}, { 7, 86,-23}, { 7, 79, 24}, - { 7, 78,-24}, { 7, 68, 25}, { 7, 67,-25}, { 7, 60, 26}, - { 7, 55,-26}, { 7, 21, 27}, { 7, 20,-27}, { 8, 230, 28}, - { 8, 229,-28}, { 8, 198, 29}, { 8, 193,-29}, { 8, 163, 30}, - { 8, 162,-30}, { 8, 139, 31}, { 8, 138,-31}, { 8, 123, 32}, - { 8, 122,-32}, { 8, 108, 33}, { 9, 463,-33}, { 9, 457, 34}, - { 9, 456,-34}, { 9, 385, 35}, { 9, 384,-35}, { 9, 321, 36}, - { 9, 320,-36}, { 9, 266, 37}, { 9, 265,-37}, { 9, 218, 38}, - {10, 925,-38}, {10, 798, 39}, {10, 797,-39}, {10, 646, 40}, - {10, 645,-40}, {10, 535, 41}, {10, 534,-41}, {10, 528, 42}, - {10, 439,-42}, {11, 1848, 43}, {11, 1599,-43}, {11, 1592, 44}, - {11, 1295,-44}, {11, 1288, 45}, {11, 1059,-45}, {11, 877, 46}, - {11, 876,-46}, {12, 3197, 47}, {12, 3196,-47}, {12, 2589, 48}, - {12, 2588,-48}, {12, 2117, 49}, {12, 2116,-49}, {13, 7398, 50}, - {13, 7397,-50}, {13, 6374, 51}, {13, 6373,-51}, {13, 5158, 52}, - {13, 5157,-52}, {14, 14799, 53}, {14, 14798,-53}, {14, 12751, 54}, - {14, 12750,-54}, {14, 10318, 55}, {14, 10313,-55}, {15, 29587, 56}, - {15, 29586,-56}, {15, 29584, 57}, {15, 25491,-57}, {15, 20625, 58}, - {15, 20624,-58}, {16, 59171, 59}, {16, 59170,-59}, {16, 50980, 60}, - {16, 41277,-60}, {16, 50981, 61}, {16, 41278,-61}, {16, 50978, 62}, - {16, 41279,-62}, {16, 50979, 63}, {16, 50976,-63}, {16, 50977, 64}, + { 5, 12, 0}, { 5, 11, 1}, { 5, 10, -1}, { 5, 9, 2}, + { 5, 8, -2}, { 5, 7, 3}, { 5, 6, -3}, { 5, 4, 4}, + { 5, 3, -4}, { 5, 2, 5}, { 5, 1, -5}, { 5, 0, 6}, + { 6, 63, -6}, { 6, 61, 7}, { 6, 60, -7}, { 6, 59, 8}, + { 6, 58, -8}, { 6, 56, 9}, { 6, 55, -9}, { 6, 53, 10}, + { 6, 52,-10}, { 6, 51, 11}, { 6, 50,-11}, { 6, 47, 12}, + { 6, 46,-12}, { 6, 45, 13}, { 6, 44,-13}, { 6, 42, 14}, + { 6, 41,-14}, { 6, 38, 15}, { 6, 37,-15}, { 6, 36, 16}, + { 6, 35,-16}, { 6, 32, 17}, { 6, 31,-17}, { 6, 29, 18}, + { 6, 28,-18}, { 6, 26, 19}, { 6, 11,-19}, { 7, 125, 20}, + { 7, 124,-20}, { 7, 109, 21}, { 7, 108,-21}, { 7, 98, 22}, + { 7, 97,-22}, { 7, 87, 23}, { 7, 86,-23}, { 7, 79, 24}, + { 7, 78,-24}, { 7, 68, 25}, { 7, 67,-25}, { 7, 60, 26}, + { 7, 55,-26}, { 7, 21, 27}, { 7, 20,-27}, { 8, 230, 28}, + { 8, 229,-28}, { 8, 198, 29}, { 8, 193,-29}, { 8, 163, 30}, + { 8, 162,-30}, { 8, 139, 31}, { 8, 138,-31}, { 8, 123, 32}, + { 8, 122,-32}, { 8, 108, 33}, { 9, 463,-33}, { 9, 457, 34}, + { 9, 456,-34}, { 9, 385, 35}, { 9, 384,-35}, { 9, 321, 36}, + { 9, 320,-36}, { 9, 266, 37}, { 9, 265,-37}, { 9, 218, 38}, + {10, 925,-38}, {10, 798, 39}, {10, 797,-39}, {10, 646, 40}, + {10, 645,-40}, {10, 535, 41}, {10, 534,-41}, {10, 528, 42}, + {10, 439,-42}, {11, 1848, 43}, {11, 1599,-43}, {11, 1592, 44}, + {11, 1295,-44}, {11, 1288, 45}, {11, 1059,-45}, {11, 877, 46}, + {11, 876,-46}, {12, 3197, 47}, {12, 3196,-47}, {12, 2589, 48}, + {12, 2588,-48}, {12, 2117, 49}, {12, 2116,-49}, {13, 7398, 50}, + {13, 7397,-50}, {13, 6374, 51}, {13, 6373,-51}, {13, 5158, 52}, + {13, 5157,-52}, {14, 14799, 53}, {14, 14798,-53}, {14, 12751, 54}, + {14, 12750,-54}, {14, 10318, 55}, {14, 10313,-55}, {15, 29587, 56}, + {15, 29586,-56}, {15, 29584, 57}, {15, 25491,-57}, {15, 20625, 58}, + {15, 20624,-58}, {16, 59171, 59}, {16, 59170,-59}, {16, 50980, 60}, + {16, 41277,-60}, {16, 50981, 61}, {16, 41278,-61}, {16, 50978, 62}, + {16, 41279,-62}, {16, 50979, 63}, {16, 50976,-63}, {16, 50977, 64}, {16, 41276,-64}, { 0, 0, 0} }; huff_entry_t bitalloc_f_129[] = { - { 6, 56, 0}, { 6, 55, 1}, { 6, 54, -1}, { 6, 52, 2}, - { 6, 51, -2}, { 6, 50, 3}, { 6, 49, -3}, { 6, 48, 4}, - { 6, 47, -4}, { 6, 46, 5}, { 6, 45, -5}, { 6, 44, 6}, - { 6, 43, -6}, { 6, 41, 7}, { 6, 40, -7}, { 6, 39, 8}, - { 6, 38, -8}, { 6, 36, 9}, { 6, 35, -9}, { 6, 34, 10}, - { 6, 33,-10}, { 6, 31, 11}, { 6, 30,-11}, { 6, 29, 12}, - { 6, 28,-12}, { 6, 26, 13}, { 6, 25,-13}, { 6, 23, 14}, - { 6, 22,-14}, { 6, 21, 15}, { 6, 20,-15}, { 6, 18, 16}, - { 6, 17,-16}, { 6, 15, 17}, { 6, 14,-17}, { 6, 12, 18}, - { 6, 11,-18}, { 6, 9, 19}, { 6, 8,-19}, { 6, 7, 20}, - { 6, 6,-20}, { 6, 3, 21}, { 6, 2,-21}, { 6, 1, 22}, - { 6, 0,-22}, { 7, 125, 23}, { 7, 124,-23}, { 7, 123, 24}, - { 7, 122,-24}, { 7, 120, 25}, { 7, 119,-25}, { 7, 116, 26}, - { 7, 115,-26}, { 7, 114, 27}, { 7, 107,-27}, { 7, 84, 28}, - { 7, 75,-28}, { 7, 65, 29}, { 7, 64,-29}, { 7, 54, 30}, - { 7, 49,-30}, { 7, 39, 31}, { 7, 38,-31}, { 7, 27, 32}, - { 7, 26,-32}, { 7, 20, 33}, { 7, 11,-33}, { 7, 10, 34}, - { 7, 9,-34}, { 8, 254, 35}, { 8, 253,-35}, { 8, 243, 36}, - { 8, 242,-36}, { 8, 235, 37}, { 8, 234,-37}, { 8, 213, 38}, - { 8, 212,-38}, { 8, 149, 39}, { 8, 148,-39}, { 8, 110, 40}, - { 8, 97,-40}, { 8, 66, 41}, { 8, 65,-41}, { 8, 43, 42}, - { 8, 42,-42}, { 8, 16, 43}, { 9, 511,-43}, { 9, 505, 44}, - { 9, 504,-44}, { 9, 474, 45}, { 9, 473,-45}, { 9, 343, 46}, - { 9, 342,-46}, { 9, 340, 47}, { 9, 223,-47}, { 9, 192, 48}, - { 9, 135,-48}, { 9, 129, 49}, { 9, 128,-49}, { 9, 34, 50}, - {10, 1021,-50}, {10, 951, 51}, {10, 950,-51}, {10, 944, 52}, - {10, 683,-52}, {10, 445, 53}, {10, 444,-53}, {10, 269, 54}, - {10, 268,-54}, {10, 71, 55}, {10, 70,-55}, {11, 2040, 56}, - {11, 1891,-56}, {11, 1364, 57}, {11, 775,-57}, {11, 774, 58}, - {11, 773,-58}, {12, 4083, 59}, {12, 4082,-59}, {12, 3780, 60}, - {12, 2731,-60}, {12, 1545, 61}, {12, 1544,-61}, {13, 7562, 62}, - {13, 5461,-62}, {13, 5460, 63}, {14, 15127,-63}, {15, 30253, 64}, + { 6, 56, 0}, { 6, 55, 1}, { 6, 54, -1}, { 6, 52, 2}, + { 6, 51, -2}, { 6, 50, 3}, { 6, 49, -3}, { 6, 48, 4}, + { 6, 47, -4}, { 6, 46, 5}, { 6, 45, -5}, { 6, 44, 6}, + { 6, 43, -6}, { 6, 41, 7}, { 6, 40, -7}, { 6, 39, 8}, + { 6, 38, -8}, { 6, 36, 9}, { 6, 35, -9}, { 6, 34, 10}, + { 6, 33,-10}, { 6, 31, 11}, { 6, 30,-11}, { 6, 29, 12}, + { 6, 28,-12}, { 6, 26, 13}, { 6, 25,-13}, { 6, 23, 14}, + { 6, 22,-14}, { 6, 21, 15}, { 6, 20,-15}, { 6, 18, 16}, + { 6, 17,-16}, { 6, 15, 17}, { 6, 14,-17}, { 6, 12, 18}, + { 6, 11,-18}, { 6, 9, 19}, { 6, 8,-19}, { 6, 7, 20}, + { 6, 6,-20}, { 6, 3, 21}, { 6, 2,-21}, { 6, 1, 22}, + { 6, 0,-22}, { 7, 125, 23}, { 7, 124,-23}, { 7, 123, 24}, + { 7, 122,-24}, { 7, 120, 25}, { 7, 119,-25}, { 7, 116, 26}, + { 7, 115,-26}, { 7, 114, 27}, { 7, 107,-27}, { 7, 84, 28}, + { 7, 75,-28}, { 7, 65, 29}, { 7, 64,-29}, { 7, 54, 30}, + { 7, 49,-30}, { 7, 39, 31}, { 7, 38,-31}, { 7, 27, 32}, + { 7, 26,-32}, { 7, 20, 33}, { 7, 11,-33}, { 7, 10, 34}, + { 7, 9,-34}, { 8, 254, 35}, { 8, 253,-35}, { 8, 243, 36}, + { 8, 242,-36}, { 8, 235, 37}, { 8, 234,-37}, { 8, 213, 38}, + { 8, 212,-38}, { 8, 149, 39}, { 8, 148,-39}, { 8, 110, 40}, + { 8, 97,-40}, { 8, 66, 41}, { 8, 65,-41}, { 8, 43, 42}, + { 8, 42,-42}, { 8, 16, 43}, { 9, 511,-43}, { 9, 505, 44}, + { 9, 504,-44}, { 9, 474, 45}, { 9, 473,-45}, { 9, 343, 46}, + { 9, 342,-46}, { 9, 340, 47}, { 9, 223,-47}, { 9, 192, 48}, + { 9, 135,-48}, { 9, 129, 49}, { 9, 128,-49}, { 9, 34, 50}, + {10, 1021,-50}, {10, 951, 51}, {10, 950,-51}, {10, 944, 52}, + {10, 683,-52}, {10, 445, 53}, {10, 444,-53}, {10, 269, 54}, + {10, 268,-54}, {10, 71, 55}, {10, 70,-55}, {11, 2040, 56}, + {11, 1891,-56}, {11, 1364, 57}, {11, 775,-57}, {11, 774, 58}, + {11, 773,-58}, {12, 4083, 59}, {12, 4082,-59}, {12, 3780, 60}, + {12, 2731,-60}, {12, 1545, 61}, {12, 1544,-61}, {13, 7562, 62}, + {13, 5461,-62}, {13, 5460, 63}, {14, 15127,-63}, {15, 30253, 64}, {15, 30252,-64}, { 0, 0, 0} }; huff_entry_t bitalloc_g_129[] = { - { 4, 0, 0}, { 5, 29, 1}, { 5, 28, -1}, { 5, 25, 2}, - { 5, 24, -2}, { 5, 21, 3}, { 5, 20, -3}, { 5, 17, 4}, - { 5, 16, -4}, { 5, 13, 5}, { 5, 12, -5}, { 5, 9, 6}, - { 5, 8, -6}, { 5, 5, 7}, { 5, 4, -7}, { 6, 63, 8}, - { 6, 62, -8}, { 6, 55, 9}, { 6, 54, -9}, { 6, 47, 10}, - { 6, 46,-10}, { 6, 39, 11}, { 6, 38,-11}, { 6, 31, 12}, - { 6, 30,-12}, { 6, 23, 13}, { 6, 22,-13}, { 6, 15, 14}, - { 6, 14,-14}, { 6, 7, 15}, { 6, 6,-15}, { 7, 123, 16}, - { 7, 122,-16}, { 7, 107, 17}, { 7, 106,-17}, { 7, 91, 18}, - { 7, 90,-18}, { 7, 75, 19}, { 7, 74,-19}, { 7, 59, 20}, - { 7, 58,-20}, { 7, 43, 21}, { 7, 42,-21}, { 7, 27, 22}, - { 7, 26,-22}, { 7, 11, 23}, { 7, 10,-23}, { 7, 8, 24}, - { 8, 243,-24}, { 8, 240, 25}, { 8, 211,-25}, { 8, 208, 26}, - { 8, 179,-26}, { 8, 176, 27}, { 8, 147,-27}, { 8, 144, 28}, - { 8, 115,-28}, { 8, 112, 29}, { 8, 83,-29}, { 8, 80, 30}, - { 8, 51,-30}, { 8, 48, 31}, { 8, 19,-31}, { 9, 484, 32}, - { 9, 483,-32}, { 9, 421, 33}, { 9, 420,-33}, { 9, 357, 34}, - { 9, 356,-34}, { 9, 293, 35}, { 9, 292,-35}, { 9, 229, 36}, - { 9, 228,-36}, { 9, 226, 37}, { 9, 165,-37}, { 9, 162, 38}, - { 9, 101,-38}, { 9, 98, 39}, { 9, 37,-39}, {10, 970, 40}, - {10, 965,-40}, {10, 839, 41}, {10, 838,-41}, {10, 711, 42}, - {10, 710,-42}, {10, 708, 43}, {10, 583,-43}, {10, 580, 44}, - {10, 455,-44}, {10, 329, 45}, {10, 328,-45}, {10, 201, 46}, - {10, 200,-46}, {10, 198, 47}, {10, 73,-47}, {11, 1942, 48}, - {11, 1929,-48}, {11, 1675, 49}, {11, 1674,-49}, {11, 1672, 50}, - {11, 1419,-50}, {11, 1165, 51}, {11, 1164,-51}, {11, 1162, 52}, - {11, 909,-52}, {11, 655, 53}, {11, 654,-53}, {11, 652, 54}, - {11, 399,-54}, {11, 145, 55}, {11, 144,-55}, {12, 3886, 56}, - {12, 3857,-56}, {12, 3347, 57}, {12, 3346,-57}, {12, 2837, 58}, - {12, 2836,-58}, {12, 2327, 59}, {12, 2326,-59}, {12, 1817, 60}, - {12, 1816,-60}, {12, 1307, 61}, {12, 1306,-61}, {12, 797, 62}, - {12, 796,-62}, {13, 7775, 63}, {13, 7774,-63}, {13, 7713, 64}, + { 4, 0, 0}, { 5, 29, 1}, { 5, 28, -1}, { 5, 25, 2}, + { 5, 24, -2}, { 5, 21, 3}, { 5, 20, -3}, { 5, 17, 4}, + { 5, 16, -4}, { 5, 13, 5}, { 5, 12, -5}, { 5, 9, 6}, + { 5, 8, -6}, { 5, 5, 7}, { 5, 4, -7}, { 6, 63, 8}, + { 6, 62, -8}, { 6, 55, 9}, { 6, 54, -9}, { 6, 47, 10}, + { 6, 46,-10}, { 6, 39, 11}, { 6, 38,-11}, { 6, 31, 12}, + { 6, 30,-12}, { 6, 23, 13}, { 6, 22,-13}, { 6, 15, 14}, + { 6, 14,-14}, { 6, 7, 15}, { 6, 6,-15}, { 7, 123, 16}, + { 7, 122,-16}, { 7, 107, 17}, { 7, 106,-17}, { 7, 91, 18}, + { 7, 90,-18}, { 7, 75, 19}, { 7, 74,-19}, { 7, 59, 20}, + { 7, 58,-20}, { 7, 43, 21}, { 7, 42,-21}, { 7, 27, 22}, + { 7, 26,-22}, { 7, 11, 23}, { 7, 10,-23}, { 7, 8, 24}, + { 8, 243,-24}, { 8, 240, 25}, { 8, 211,-25}, { 8, 208, 26}, + { 8, 179,-26}, { 8, 176, 27}, { 8, 147,-27}, { 8, 144, 28}, + { 8, 115,-28}, { 8, 112, 29}, { 8, 83,-29}, { 8, 80, 30}, + { 8, 51,-30}, { 8, 48, 31}, { 8, 19,-31}, { 9, 484, 32}, + { 9, 483,-32}, { 9, 421, 33}, { 9, 420,-33}, { 9, 357, 34}, + { 9, 356,-34}, { 9, 293, 35}, { 9, 292,-35}, { 9, 229, 36}, + { 9, 228,-36}, { 9, 226, 37}, { 9, 165,-37}, { 9, 162, 38}, + { 9, 101,-38}, { 9, 98, 39}, { 9, 37,-39}, {10, 970, 40}, + {10, 965,-40}, {10, 839, 41}, {10, 838,-41}, {10, 711, 42}, + {10, 710,-42}, {10, 708, 43}, {10, 583,-43}, {10, 580, 44}, + {10, 455,-44}, {10, 329, 45}, {10, 328,-45}, {10, 201, 46}, + {10, 200,-46}, {10, 198, 47}, {10, 73,-47}, {11, 1942, 48}, + {11, 1929,-48}, {11, 1675, 49}, {11, 1674,-49}, {11, 1672, 50}, + {11, 1419,-50}, {11, 1165, 51}, {11, 1164,-51}, {11, 1162, 52}, + {11, 909,-52}, {11, 655, 53}, {11, 654,-53}, {11, 652, 54}, + {11, 399,-54}, {11, 145, 55}, {11, 144,-55}, {12, 3886, 56}, + {12, 3857,-56}, {12, 3347, 57}, {12, 3346,-57}, {12, 2837, 58}, + {12, 2836,-58}, {12, 2327, 59}, {12, 2326,-59}, {12, 1817, 60}, + {12, 1816,-60}, {12, 1307, 61}, {12, 1306,-61}, {12, 797, 62}, + {12, 796,-62}, {13, 7775, 63}, {13, 7774,-63}, {13, 7713, 64}, {13, 7712,-64}, { 0, 0, 0} }; diff --git a/src/libdts/tables_quantization.h b/src/libdts/tables_quantization.h index 904b1014e..447d6a8d0 100644 --- a/src/libdts/tables_quantization.h +++ b/src/libdts/tables_quantization.h @@ -22,59 +22,59 @@ int scale_factor_quant6[] = { - 1, 2, 2, 3, 3, 4, 6, 7, - 10, 12, 16, 20, 26, 34, 44, 56, - 72, 93, 120, 155, 200, 257, 331, 427, - 550, 708, 912, 1175, 1514, 1950, 2512, 3236, - 4169, 5370, 6918, 8913, 11482, 14791, 19055, 24547, - 31623, 40738, 52481, 67608, 87096, 112202, 144544, 186209, - 239883, 309030, 398107, 512861, 660693, 851138, 1096478, 1412538, + 1, 2, 2, 3, 3, 4, 6, 7, + 10, 12, 16, 20, 26, 34, 44, 56, + 72, 93, 120, 155, 200, 257, 331, 427, + 550, 708, 912, 1175, 1514, 1950, 2512, 3236, + 4169, 5370, 6918, 8913, 11482, 14791, 19055, 24547, + 31623, 40738, 52481, 67608, 87096, 112202, 144544, 186209, + 239883, 309030, 398107, 512861, 660693, 851138, 1096478, 1412538, 1819701, 2344229, 3019952, 3890451, 5011872, 6456542, 8317638, 0 }; int scale_factor_quant7[] = { - 1, 1, 2, 2, 2, 2, 3, 3, - 3, 4, 4, 5, 6, 7, 7, 8, - 10, 11, 12, 14, 16, 18, 20, 23, - 26, 30, 34, 38, 44, 50, 56, 64, - 72, 82, 93, 106, 120, 136, 155, 176, - 200, 226, 257, 292, 331, 376, 427, 484, - 550, 624, 708, 804, 912, 1035, 1175, 1334, - 1514, 1718, 1950, 2213, 2512, 2851, 3236, 3673, - 4169, 4732, 5370, 6095, 6918, 7852, 8913, 10116, - 11482, 13032, 14791, 16788, 19055, 21627, 24547, 27861, - 31623, 35892, 40738, 46238, 52481, 59566, 67608, 76736, - 87096, 98855, 112202, 127350, 144544, 164059, 186209, 211349, - 239883, 272270, 309030, 350752, 398107, 451856, 512861, 582103, - 660693, 749894, 851138, 966051, 1096478, 1244515, 1412538, 1603245, - 1819701, 2065380, 2344229, 2660725, 3019952, 3427678, 3890451, 4415704, + 1, 1, 2, 2, 2, 2, 3, 3, + 3, 4, 4, 5, 6, 7, 7, 8, + 10, 11, 12, 14, 16, 18, 20, 23, + 26, 30, 34, 38, 44, 50, 56, 64, + 72, 82, 93, 106, 120, 136, 155, 176, + 200, 226, 257, 292, 331, 376, 427, 484, + 550, 624, 708, 804, 912, 1035, 1175, 1334, + 1514, 1718, 1950, 2213, 2512, 2851, 3236, 3673, + 4169, 4732, 5370, 6095, 6918, 7852, 8913, 10116, + 11482, 13032, 14791, 16788, 19055, 21627, 24547, 27861, + 31623, 35892, 40738, 46238, 52481, 59566, 67608, 76736, + 87096, 98855, 112202, 127350, 144544, 164059, 186209, 211349, + 239883, 272270, 309030, 350752, 398107, 451856, 512861, 582103, + 660693, 749894, 851138, 966051, 1096478, 1244515, 1412538, 1603245, + 1819701, 2065380, 2344229, 2660725, 3019952, 3427678, 3890451, 4415704, 5011872, 5688529, 6456542, 7328245, 8317638, 0, 0, 0 }; /* 20bits unsigned fractional binary codes */ int lossy_quant[] = { - 0, 6710886, 4194304, 3355443, 2474639, 2097152, 1761608, 1426063, - 796918, 461373, 251658, 146801, 79692, 46137, 27263, 16777, - 10486, 5872, 3355, 1887, 1258, 713, 336, 168, + 0, 6710886, 4194304, 3355443, 2474639, 2097152, 1761608, 1426063, + 796918, 461373, 251658, 146801, 79692, 46137, 27263, 16777, + 10486, 5872, 3355, 1887, 1258, 713, 336, 168, 84, 42, 21, 0, 0, 0, 0, 0 }; double lossy_quant_d[] = { - 0, 1.6, 1.0, 0.8, 0.59, 0.50, 0.42, 0.34, - 0.19, 0.11, 0.06, 0.035, 0.019, 0.011, 0.0065, 0.0040, - 0.0025, 0.0014, 0.0008, 0.00045, 0.00030, 0.00017, 0.00008, 0.00004, + 0, 1.6, 1.0, 0.8, 0.59, 0.50, 0.42, 0.34, + 0.19, 0.11, 0.06, 0.035, 0.019, 0.011, 0.0065, 0.0040, + 0.0025, 0.0014, 0.0008, 0.00045, 0.00030, 0.00017, 0.00008, 0.00004, 0.00002, 0.00001, 0.000005, 0, 0, 0, 0, 0 }; /* 20bits unsigned fractional binary codes */ int lossless_quant[] = { - 0, 4194304, 2097152, 1384120, 1048576, 696254, 524288, 348127, - 262144, 131072, 65431, 33026, 16450, 8208, 4100, 2049, - 1024, 512, 256, 128, 64, 32, 16, 8, + 0, 4194304, 2097152, 1384120, 1048576, 696254, 524288, 348127, + 262144, 131072, 65431, 33026, 16450, 8208, 4100, 2049, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0, 0, 0, 0, 0 }; diff --git a/src/libdts/tables_vq.h b/src/libdts/tables_vq.h index eae1ed94c..9c81505fa 100644 --- a/src/libdts/tables_vq.h +++ b/src/libdts/tables_vq.h @@ -24,2052 +24,2052 @@ static int8_t high_freq_vq[1024][32] = { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { -4, -2, 2, 1, -16, -10, 1, 3, 1, 0, 6, 1, -3, 7, 1, -22, + { -4, -2, 2, 1, -16, -10, 1, 3, 1, 0, 6, 1, -3, 7, 1, -22, 2, -4, -3, 11, 14, 6, -1, 1, -13, 29, -28, 10, 10, -8, 0, -9 }, - { -8, 8, -7, 10, -3, -12, -5, -8, 1, -2, 9, -2, -5, -18, 1, 9, + { -8, 8, -7, 10, -3, -12, -5, -8, 1, -2, 9, -2, -5, -18, 1, 9, -8, -8, 3, 41, 7, -9, -9, 22, -42, -29, 14, -18, -14, -32, 1, -15 }, - { -16, 8, 15, 16, -16, 5, 2, 7, -6, -16, -7, 1, 1, -3, -2, 0, + { -16, 8, 15, 16, -16, 5, 2, 7, -6, -16, -7, 1, 1, -3, -2, 0, 8, 20, -26, -11, 2, -17, 0, -3, -34, -37, 10, 44, -2, 22, 2, -4 }, - { 7, 14, 5, 6, 15, -1, 3, -3, -9, -23, -5, -14, 8, -1, -14, -6, + { 7, 14, 5, 6, 15, -1, 3, -3, -9, -23, -5, -14, 8, -1, -14, -6, -5, -8, 54, 31, -6, 18, 2, -19, -2, -11, -30, -6, -19, 2, -2, -14 }, - { 1, 2, -2, -1, -3, -3, 1, -5, 1, -3, -4, -8, 5, -4, 0, 1, + { 1, 2, -2, -1, -3, -3, 1, -5, 1, -3, -4, -8, 5, -4, 0, 1, 3, 7, -5, -4, -3, -12, 3, -2, -3, 12, -53, -51, 6, -1, 6, 8 }, - { 0, -1, 5, 1, -6, -8, 7, 5, -18, -4, -1, 1, 0, -3, -3, -14, + { 0, -1, 5, 1, -6, -8, 7, 5, -18, -4, -1, 1, 0, -3, -3, -14, -1, -6, 0, -14, -1, -1, 5, -3, -11, 1, -20, 10, 2, 19, -2, -2 }, - { 2, 4, 3, 0, 5, 0, 3, 1, -2, 0, -6, -3, -4, -5, -3, -3, + { 2, 4, 3, 0, 5, 0, 3, 1, -2, 0, -6, -3, -4, -5, -3, -3, -7, 0, -34, 4, -43, 17, 0, -53, -13, -7, 24, 14, 5, -18, 9, -20 }, - { 1, 0, -3, 2, 3, -5, -2, 7, -21, 5, -25, 23, 11, -28, 2, 1, + { 1, 0, -3, 2, 3, -5, -2, 7, -21, 5, -25, 23, 11, -28, 2, 1, -11, 9, 13, -6, -12, 5, 7, 2, 4, -11, -6, -1, 8, 0, 1, -2 }, - { 2, -4, -6, -4, 0, -5, -29, 13, -6, -22, -3, -43, 12, -41, 5, 24, + { 2, -4, -6, -4, 0, -5, -29, 13, -6, -22, -3, -43, 12, -41, 5, 24, 18, -9, -36, -6, 4, -7, -4, 13, 4, -15, -1, -5, 1, 2, -5, 4 }, - { 0, -1, 13, -6, -5, 1, 0, -3, 1, -5, 19, -22, 31, -27, 4, -15, + { 0, -1, 13, -6, -5, 1, 0, -3, 1, -5, 19, -22, 31, -27, 4, -15, -6, 15, 9, -13, 1, -9, 10, -17, 4, -1, -1, 4, 2, 0, -3, -5 }, - { -7, 3, -8, 13, 19, -12, 8, -19, -3, -2, -24, 31, 14, 0, 7, -13, + { -7, 3, -8, 13, 19, -12, 8, -19, -3, -2, -24, 31, 14, 0, 7, -13, -18, 0, 3, 6, 13, -2, 1, -12, -21, 9, -2, 30, 21, -14, 2, -14 }, - { -3, -7, 8, -1, -2, -9, 6, 1, -7, 7, 13, 3, -1, -10, 30, 4, + { -3, -7, 8, -1, -2, -9, 6, 1, -7, 7, 13, 3, -1, -10, 30, 4, -10, 12, 5, 6, -13, -7, -4, -2, -2, 7, -3, -6, 3, 4, 1, 2 }, - { -8, 9, 2, -3, -5, 2, 0, 9, 3, 7, -4, -16, -13, 3, 23, -27, + { -8, 9, 2, -3, -5, 2, 0, 9, 3, 7, -4, -16, -13, 3, 23, -27, 18, 46, -38, 6, 4, 43, -1, 0, 8, -7, -4, -1, 11, -7, 6, -3 }, - { 1, 1, 18, -8, -6, 0, 3, 4, 22, -3, -4, -2, -4, -11, 40, -7, + { 1, 1, 18, -8, -6, 0, 3, 4, 22, -3, -4, -2, -4, -11, 40, -7, -3, -13, -14, -7, -10, 14, 7, 5, -14, 11, -5, 7, 21, -2, 9, -3 }, - { 0, 0, -2, 4, -2, 0, 2, 0, -1, 2, -1, 0, 0, 2, 2, 2, + { 0, 0, -2, 4, -2, 0, 2, 0, -1, 2, -1, 0, 0, 2, 2, 2, -1, 1, -3, -1, -15, -2, -63, -27, -21, -47, -14, 1, -14, 10, 0, 2 }, - { 1, 0, -4, 0, -3, -9, 4, 2, 6, -6, 0, -5, 11, -7, -15, 6, + { 1, 0, -4, 0, -3, -9, 4, 2, 6, -6, 0, -5, 11, -7, -15, 6, -7, -6, 3, 7, -15, -5, 23, -13, -6, 12, -8, 9, 2, -3, 3, 4 }, - { 6, 0, 3, 0, -2, -4, 2, 1, 1, -1, 1, -2, -1, -4, -22, -15, + { 6, 0, 3, 0, -2, -4, 2, 1, 1, -1, 1, -2, -1, -4, -22, -15, -46, -66, 10, 20, 2, -17, 12, -6, 1, -2, -2, 0, 1, -5, 1, 2 }, - { -1, 0, 0, 1, 0, -4, 0, 1, -10, -3, -8, 5, 7, -11, 2, -11, + { -1, 0, 0, 1, 0, -4, 0, 1, -10, -3, -8, 5, 7, -11, 2, -11, 29, -25, 11, 10, 0, -1, 5, -7, -2, -5, -2, 4, 4, -3, 5, -2 }, - { 1, -1, -1, -3, -2, 1, -8, -3, 2, -2, 4, -5, -1, -7, -2, 1, + { 1, -1, -1, -3, -2, 1, -8, -3, 2, -2, 4, -5, -1, -7, -2, 1, -14, -7, 3, -30, -15, -14, 3, -4, -1, 3, -13, -1, -3, 1, 2, 3 }, - { -1, -2, -3, 2, 2, -3, 3, 1, -3, 2, 0, -4, 6, 5, -5, 10, + { -1, -2, -3, 2, 2, -3, 3, 1, -3, 2, 0, -4, 6, 5, -5, 10, -57, 3, 22, -50, 1, -2, -5, -6, -1, 5, 1, 2, 2, 1, -2, 2 }, - { 2, 0, -1, -7, 2, 1, 3, 2, 0, 4, 3, -2, 3, -3, 4, -4, + { 2, 0, -1, -7, 2, 1, 3, 2, 0, 4, 3, -2, 3, -3, 4, -4, 24, -35, -3, 38, -6, -5, 15, 20, 3, 16, -7, -5, 0, -4, -5, 0 }, - { 0, 1, 0, 0, 0, -1, -1, 1, 1, -1, 1, -2, 0, 0, 0, 0, + { 0, 1, 0, 0, 0, -1, -1, 1, 1, -1, 1, -2, 0, 0, 0, 0, 0, -1, -2, -1, -5, -2, -43, -3, 46, -52, -10, 7, -8, 11, -2, -1 }, - { 0, 0, -1, 0, -1, 2, -41, 33, -44, -48, -15, -26, -9, 6, 3, 3, + { 0, 0, -1, 0, -1, 2, -41, 33, -44, -48, -15, -26, -9, 6, 3, 3, -3, 2, 2, 2, 2, -1, -1, -2, 1, 3, 0, 0, 5, 2, 3, 1 }, - { -4, 1, 6, 1, -6, -1, -2, 1, -14, -4, 0, -5, -2, 2, -2, 0, + { -4, 1, 6, 1, -6, -1, -2, 1, -14, -4, 0, -5, -2, 2, -2, 0, -6, 1, 0, 8, -21, 32, -3, -36, -6, -2, -1, -7, 3, 0, 1, -6 }, - { -3, -2, 3, 0, 2, 2, 8, -4, -4, 6, 2, 1, 3, -6, 4, 3, + { -3, -2, 3, 0, 2, 2, 8, -4, -4, 6, 2, 1, 3, -6, 4, 3, 13, 0, -12, -1, 25, -20, -2, -23, -15, 7, -3, -11, -3, 6, -1, 0 }, - { 0, 0, -3, -1, 0, 0, -2, -1, -2, -2, 1, -1, 0, 0, 10, 3, + { 0, 0, -3, -1, 0, 0, -2, -1, -2, -2, 1, -1, 0, 0, 10, 3, -2, 3, 3, -7, -6, -5, 0, -4, -60, -16, -6, 38, 5, 6, -5, 0 }, - { 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 1, 0, 0, 1, + { 0, 1, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 1, 0, 0, 1, 0, 0, -1, 0, -8, 2, -9, 10, 40, 31, -56, -21, 4, 20, -4, 7 }, - { -2, -2, 0, 4, -3, -1, 7, 3, 1, 3, -8, 0, 3, 1, 2, 5, + { -2, -2, 0, 4, -3, -1, 7, 3, 1, 3, -8, 0, 3, 1, 2, 5, 1, -2, 14, 5, 4, 5, 5, 5, -5, 9, -66, 0, -20, -2, -8, 4 }, - { -2, -1, 4, -1, -8, -2, -4, -1, -3, -3, 2, -7, -3, 5, 7, -2, + { -2, -1, 4, -1, -8, -2, -4, -1, -3, -3, 2, -7, -3, 5, 7, -2, 45, 31, -17, -16, -2, -2, -1, -22, 1, -1, -3, 3, 5, -3, 5, -1 }, - { -4, 0, 7, 5, 8, 7, 2, 9, -9, -9, -7, -11, -3, -8, 17, -4, + { -4, 0, 7, 5, 8, 7, 2, 9, -9, -9, -7, -11, -3, -8, 17, -4, 34, 32, 18, 22, 1, 2, 1, -7, -5, 6, -1, 6, 4, 10, -2, -7 }, - { 6, 0, 14, 9, 6, -1, -2, -3, 4, -6, -8, 4, 7, -1, 28, 38, + { 6, 0, 14, 9, 6, -1, -2, -3, 4, -6, -8, 4, 7, -1, 28, 38, 15, -1, 16, -11, 5, 8, 4, -10, 3, -10, -17, 5, 3, 3, 3, 1 }, - { 1, 1, 2, -1, 2, 1, 0, 0, -1, 0, 0, -2, 1, -3, 0, 1, + { 1, 1, 2, -1, 2, 1, 0, 0, -1, 0, 0, -2, 1, -3, 0, 1, 2, -2, -4, -2, 0, -1, 1, -3, 1, 1, 1, -1, 8, 8, 66, 33 }, - { -5, 2, -3, -7, 2, -8, -4, 10, 17, -18, -7, 4, -4, -7, -6, -6, + { -5, 2, -3, -7, 2, -8, -4, 10, 17, -18, -7, 4, -4, -7, -6, -6, -5, 5, -12, 2, 0, 6, 8, -2, 1, 4, -11, 2, 1, 8, 31, 19 }, - { 6, 9, 16, -6, -6, -1, -2, -3, -11, -2, 7, 7, 17, 3, 4, 10, + { 6, 9, 16, -6, -6, -1, -2, -3, -11, -2, 7, 7, 17, 3, 4, 10, 2, 5, -13, 8, 7, 1, 4, 5, 7, 6, 7, -8, 9, -8, 33, 6 }, - { 3, -1, 1, 0, -7, -5, 0, 14, -7, 1, -7, 1, 2, -4, 7, 10, + { 3, -1, 1, 0, -7, -5, 0, 14, -7, 1, -7, 1, 2, -4, 7, 10, -16, 12, 1, -6, 3, 8, -1, 10, -13, -6, -12, -23, 12, -3, 30, 14 }, - { -2, -15, 0, 8, 3, -19, 5, -3, 2, 3, 13, 7, 14, -3, -10, 0, + { -2, -15, 0, 8, 3, -19, 5, -3, 2, 3, 13, 7, 14, -3, -10, 0, 8, 5, -6, -16, -8, -8, 14, 2, -1, 1, -9, -11, 11, -5, 27, 9 }, - { -8, 6, -4, 4, -4, -1, 5, 4, 1, -7, -5, -4, -15, 1, 9, 0, + { -8, 6, -4, 4, -4, -1, 5, 4, 1, -7, -5, -4, -15, 1, 9, 0, 8, 4, 1, -17, 11, -2, -19, -1, -6, -8, 3, -12, 3, -17, 33, -10 }, - { -3, -1, 2, 7, 7, -2, 9, 8, -18, -1, -13, -10, -3, -3, 11, 8, + { -3, -1, 2, 7, 7, -2, 9, 8, -18, -1, -13, -10, -3, -3, 11, 8, -2, -12, -8, 1, 4, 9, 14, 10, -3, 0, 2, 1, -2, 3, 31, 10 }, - { -3, -10, 8, -1, -5, -11, 7, -5, 3, 6, 1, 4, -16, 10, 5, -4, + { -3, -10, 8, -1, -5, -11, 7, -5, 3, 6, 1, 4, -16, 10, 5, -4, -2, -10, -1, 13, 6, -5, -7, 12, 7, -3, -17, 1, 12, -4, 29, 8 }, - { 1, 2, 5, 2, -6, -7, 0, -1, 6, -1, 10, 6, -4, 5, 2, 2, + { 1, 2, 5, 2, -6, -7, 0, -1, 6, -1, 10, 6, -4, 5, 2, 2, -2, -8, -6, -11, 14, -13, 27, 3, -2, -12, 5, -16, 2, -26, 20, 15 }, - { -1, -3, -5, -3, -3, 6, -1, 3, -5, 1, 7, 2, 1, 0, -1, -1, + { -1, -3, -5, -3, -3, 6, -1, 3, -5, 1, 7, 2, 1, 0, -1, -1, 0, -1, 9, 7, -6, -3, 4, -5, -4, 8, -8, -25, -8, -4, 34, 23 }, - { -1, -2, 1, 1, -1, -2, -1, 1, -1, 0, 0, 0, 0, -2, -1, 1, + { -1, -2, 1, 1, -1, -2, -1, 1, -1, 0, 0, 0, 0, -2, -1, 1, 0, 2, 1, -1, 4, 0, 0, 1, -1, 0, 5, 3, 12, -9, 68, -16 }, - { 10, 0, -8, 14, -6, 1, -12, 0, 0, -3, -5, -11, -6, 12, 9, -10, + { 10, 0, -8, 14, -6, 1, -12, 0, 0, -3, -5, -11, -6, 12, 9, -10, -3, 5, 0, 7, 11, 2, 4, -3, -8, -3, 7, 4, 3, -3, 34, 4 }, - { -12, 13, -5, 7, -11, -2, -1, 1, -4, -14, -21, 3, -3, -3, -4, -7, + { -12, 13, -5, 7, -11, -2, -1, 1, -4, -14, -21, 3, -3, -3, -4, -7, -9, -4, 3, -17, -2, -13, 10, -2, 12, -4, 0, -9, 1, -5, 31, 10 }, - { -10, 6, 5, 6, 4, -7, 10, 0, -28, -3, 0, -11, -1, -5, 16, -10, + { -10, 6, 5, 6, 4, -7, 10, 0, -28, -3, 0, -11, -1, -5, 16, -10, -16, 7, 20, 2, -4, 2, -5, 0, 15, 6, 5, -10, 7, -9, 20, 4 }, - { 1, -7, -2, -7, 4, -3, -2, -7, -1, -14, 6, -16, 4, -5, -4, -6, + { 1, -7, -2, -7, 4, -3, -2, -7, -1, -14, 6, -16, 4, -5, -4, -6, -5, 0, -2, 2, -6, 9, -5, 4, -18, 8, -10, 8, 15, 0, 32, 1 }, - { -5, 7, -3, 7, 15, -4, 0, -16, 9, 5, -5, 5, 4, -3, -12, -9, + { -5, 7, -3, 7, 15, -4, 0, -16, 9, 5, -5, 5, 4, -3, -12, -9, -18, 10, 2, 2, -3, 7, 3, -1, 6, -9, -10, 3, 15, -4, 35, -7 }, - { -1, -10, 2, 2, -4, -2, 10, 2, -1, 2, -2, 1, -1, -14, -11, 3, + { -1, -10, 2, 2, -4, -2, 10, 2, -1, 2, -2, 1, -1, -14, -11, 3, -8, 5, -8, -2, 6, -1, -7, 1, 7, 5, 7, 8, 30, -4, 30, 14 }, - { 2, -2, 1, 2, 3, -8, 3, 0, -2, 0, -9, 2, 1, 4, -6, -1, + { 2, -2, 1, 2, 3, -8, 3, 0, -2, 0, -9, 2, 1, 4, -6, -1, -2, 5, 0, 1, -2, 12, 6, -3, 9, -3, 4, -12, 21, -39, 24, -2 }, - { 3, 5, 1, -2, -2, -2, -3, 6, -8, -2, -11, -8, -1, 4, 2, 2, + { 3, 5, 1, -2, -2, -2, -3, 6, -8, -2, -11, -8, -1, 4, 2, 2, -4, -10, 12, -5, -11, 1, -15, -34, -11, -7, -11, -1, 7, -14, 38, -1 }, - { -4, 4, 8, 9, 8, 1, -5, -9, 4, -2, 15, -4, 11, -15, 20, -1, + { -4, 4, 8, 9, 8, 1, -5, -9, 4, -2, 15, -4, 11, -15, 20, -1, -1, -3, 4, -9, -2, -2, -2, 8, 6, 12, -5, 0, 11, -12, 27, -4 }, - { 0, 8, -4, 3, -11, 6, -11, 2, 3, 0, 5, -8, -7, -6, -9, -21, + { 0, 8, -4, 3, -11, 6, -11, 2, 3, 0, 5, -8, -7, -6, -9, -21, 4, -11, -1, -16, -7, 16, -3, 7, -7, 4, -5, 0, 11, -7, 31, 3 }, - { 1, 3, 4, 11, -11, -2, -3, -6, 6, 5, 0, 3, -9, -6, 4, -4, + { 1, 3, 4, 11, -11, -2, -3, -6, 6, 5, 0, 3, -9, -6, 4, -4, 0, 4, -8, 13, -6, -13, -1, -5, -1, 4, 0, 0, 9, -22, 24, 18 }, - { -7, 3, 10, -13, -6, 6, -6, 6, 22, 1, 0, -14, 2, 3, 7, -1, + { -7, 3, 10, -13, -6, 6, -6, 6, 22, 1, 0, -14, 2, 3, 7, -1, 8, 20, -1, 5, -4, 13, 9, -9, -9, 6, 0, -4, 0, -8, 31, -4 }, - { -3, -4, 0, 1, 7, 3, -7, 0, 5, -2, 1, 3, 3, 1, -5, -2, + { -3, -4, 0, 1, 7, 3, -7, 0, 5, -2, 1, 3, 3, 1, -5, -2, 5, 2, -11, 4, 0, -1, 12, 0, -3, -13, 15, 8, -6, -27, 34, 0 }, - { -3, -3, 10, -4, 2, -1, -3, 0, -1, -1, -4, 2, 6, -2, 12, 1, + { -3, -3, 10, -4, 2, -1, -3, 0, -1, -1, -4, 2, 6, -2, 12, 1, 3, -6, -7, -6, -5, 4, -19, -6, -8, -34, -4, -8, 10, -7, 23, 10 }, - { -7, 0, -1, -6, 8, 4, -4, 2, -5, -8, -7, -9, -8, 5, 9, 7, + { -7, 0, -1, -6, 8, 4, -4, 2, -5, -8, -7, -9, -8, 5, 9, 7, -6, 1, -12, -12, -1, -16, 5, 0, 16, 3, -7, -8, 27, -4, 23, 15 }, - { -8, 4, 8, 5, 6, 11, -3, 5, 3, -1, -11, 6, -5, 0, 2, -6, + { -8, 4, 8, 5, 6, 11, -3, 5, 3, -1, -11, 6, -5, 0, 2, -6, -3, -6, 4, -1, 5, -5, -12, -6, 7, -5, 9, 3, 6, -7, 29, 1 }, - { 1, 3, -2, -2, -6, -2, 1, 6, -6, -3, 1, 2, 3, 4, 1, 5, + { 1, 3, -2, -2, -6, -2, 1, 6, -6, -3, 1, 2, 3, 4, 1, 5, -1, 0, 4, 2, 11, 6, 2, -3, 13, -9, -19, 18, -15, -10, 36, 21 }, - { -3, -3, 2, -1, -7, 6, -4, 1, -3, -1, -2, 2, 3, -7, -3, 0, + { -3, -3, 2, -1, -7, 6, -4, 1, -3, -1, -2, 2, 3, -7, -3, 0, -2, 0, -2, 6, -19, 3, -8, 2, -6, 7, -1, 0, 29, -6, 28, -10 }, - { -5, 1, -3, -7, -12, -4, 1, 1, -1, 13, -10, -1, -9, -5, -13, 6, + { -5, 1, -3, -7, -12, -4, 1, 1, -1, 13, -10, -1, -9, -5, -13, 6, 13, 3, -4, 2, 3, 11, 2, 6, -25, -16, -6, 0, 14, -1, 27, 16 }, - { -6, -1, -7, -5, -2, -5, -5, -1, 9, 1, 0, 3, -8, -12, -6, 5, + { -6, -1, -7, -5, -2, -5, -5, -1, 9, 1, 0, 3, -8, -12, -6, 5, -6, 5, 3, -9, 1, 4, -7, -10, -9, -7, -17, -5, -15, -23, 25, 3 }, - { -8, -2, 9, -3, -4, 3, -1, 8, -7, -7, -5, -4, -2, 9, 4, -1, + { -8, -2, 9, -3, -4, 3, -1, 8, -7, -7, -5, -4, -2, 9, 4, -1, -7, -4, -5, -16, 3, -6, 18, -13, -9, 16, -15, 8, 15, -10, 24, 5 }, - { 1, -38, 2, 34, 9, 10, 11, 2, 2, -6, 3, 2, -2, 5, 4, -7, + { 1, -38, 2, 34, 9, 10, 11, 2, 2, -6, 3, 2, -2, 5, 4, -7, -1, 1, 4, 0, 3, 1, -8, -1, -6, 5, 4, 2, -4, 5, 2, -1 }, - { 1, -22, 15, 18, -2, 10, -16, -9, -8, -11, 8, 4, 0, 7, -14, -5, + { 1, -22, 15, 18, -2, 10, -16, -9, -8, -11, 8, 4, 0, 7, -14, -5, -1, -7, 12, 17, 9, 5, -7, -4, -12, -6, 7, 0, 7, 2, -2, 1 }, - { -11, -29, 7, 10, 19, -1, -8, -9, 7, 1, 9, 6, 8, -7, -14, 8, + { -11, -29, 7, 10, 19, -1, -8, -9, 7, 1, 9, 6, 8, -7, -14, 8, -3, -11, -13, 0, -7, -23, -2, -8, 12, 9, 2, 14, 19, 1, -1, 5 }, - { -24, -27, -11, 36, 2, 6, -3, 4, -6, 8, 0, 12, -1, -4, -6, 3, + { -24, -27, -11, 36, 2, 6, -3, 4, -6, 8, 0, 12, -1, -4, -6, 3, 4, -1, 2, -3, -2, 3, 2, -1, -2, -4, 0, -1, -2, 7, 2, 3 }, - { -9, -24, 11, 13, -10, -12, 12, -2, 7, 4, 8, 13, -3, -3, 2, 9, + { -9, -24, 11, 13, -10, -12, 12, -2, 7, 4, 8, 13, -3, -3, 2, 9, -3, -4, 4, 13, 5, 13, -6, -3, 1, 15, 7, -3, 0, 19, -2, -9 }, - { -8, -15, 7, 14, -4, -5, 2, -18, -19, -2, 2, 17, 16, 6, -10, 10, + { -8, -15, 7, 14, -4, -5, 2, -18, -19, -2, 2, 17, 16, 6, -10, 10, -9, 14, -1, -5, -1, -6, -7, 2, 9, 11, 13, 6, -5, -12, 3, 2 }, - { -10, -37, 13, 1, 3, -14, 0, -20, 4, -3, 8, 2, -2, -3, -9, -5, + { -10, -37, 13, 1, 3, -14, 0, -20, 4, -3, 8, 2, -2, -3, -9, -5, -3, -17, -1, 13, -11, 2, -6, 4, 4, 0, 3, 1, -9, -4, -5, -4 }, - { -2, -22, -5, 46, -8, 5, 9, -11, 8, 7, 7, -1, -1, -2, -7, 2, + { -2, -22, -5, 46, -8, 5, 9, -11, 8, 7, 7, -1, -1, -2, -7, 2, -3, 3, -1, -2, 7, 0, 2, -1, 1, -2, -2, -3, 6, 0, -4, -6 }, - { -16, -27, 15, 16, -4, 14, -7, -26, 2, -2, 6, 5, -3, 11, 0, 2, + { -16, -27, 15, 16, -4, 14, -7, -26, 2, -2, 6, 5, -3, 11, 0, 2, 3, 9, -7, -1, 2, -4, -4, -1, 6, 10, 1, 1, -3, -2, 3, 0 }, - { -3, -22, 10, 26, 1, 2, -3, 3, 17, -3, -7, 9, 1, -21, -4, 5, + { -3, -22, 10, 26, 1, 2, -3, 3, 17, -3, -7, 9, 1, -21, -4, 5, 3, 0, -7, -6, 3, 3, -8, -7, -9, 3, 7, 1, -8, 12, 6, -7 }, - { -9, -25, 3, 18, 9, -6, -11, 0, -5, -12, 9, -8, -7, -6, -6, 22, + { -9, -25, 3, 18, 9, -6, -11, 0, -5, -12, 9, -8, -7, -6, -6, 22, 2, -6, -3, 15, 3, 2, -2, 9, 14, -10, -7, 15, 13, 6, -2, 11 }, - { 5, -20, -5, 28, 11, 10, -4, -4, 0, -7, 3, 5, 2, -5, -8, 2, + { 5, -20, -5, 28, 11, 10, -4, -4, 0, -7, 3, 5, 2, -5, -8, 2, 6, 10, 9, -9, -18, 3, 14, 1, 3, -3, -1, -6, 7, 7, 2, -1 }, - { -8, -30, 7, 12, 10, 8, 7, -13, -16, 0, 1, -1, -6, -11, -15, 4, + { -8, -30, 7, 12, 10, 8, 7, -13, -16, 0, 1, -1, -6, -11, -15, 4, 1, -2, 10, -15, 1, 11, -2, 8, 9, -7, -7, 9, -5, 2, 7, -18 }, - { -10, -32, 10, 11, 3, -1, 3, -5, 5, 2, 14, -6, 3, 1, 5, -15, + { -10, -32, 10, 11, 3, -1, 3, -5, 5, 2, 14, -6, 3, 1, 5, -15, -11, 6, 20, 4, 0, -12, -7, 3, 1, -1, 10, 6, -1, -9, -4, -1 }, - { 1, -25, -14, 12, -11, 9, 9, -16, -24, -17, 22, -9, 11, -30, -3, -4, + { 1, -25, -14, 12, -11, 9, 9, -16, -24, -17, 22, -9, 11, -30, -3, -4, 6, -7, 9, 2, -1, -5, -6, 2, -1, -1, 10, 1, -3, 3, 4, 8 }, - { -14, -26, -6, 9, 8, 17, -11, -24, -7, -4, -8, -2, 10, 2, 2, -1, + { -14, -26, -6, 9, 8, 17, -11, -24, -7, -4, -8, -2, 10, 2, 2, -1, 2, 13, 12, -7, 4, -6, -10, 6, 6, -13, -11, -7, -16, 0, -2, 5 }, - { -4, -30, -13, 12, 16, -6, 12, -16, -13, 5, 15, -2, -2, -10, -7, 7, + { -4, -30, -13, 12, 16, -6, 12, -16, -13, 5, 15, -2, -2, -10, -7, 7, 11, -1, -4, -2, -4, 7, 4, -8, 1, 3, 0, 11, 3, -2, -5, 4 }, - { -4, -21, 20, 22, 2, 20, -8, 1, -12, -5, -9, 4, -10, -17, -3, -8, + { -4, -21, 20, 22, 2, 20, -8, 1, -12, -5, -9, 4, -10, -17, -3, -8, -3, 3, -12, 1, -3, 0, 7, 4, 7, 7, -3, 7, 5, 3, 1, -5 }, - { -12, -20, 2, 29, 11, -6, 9, -7, -6, -4, 0, 6, 17, -13, -2, -10, + { -12, -20, 2, 29, 11, -6, 9, -7, -6, -4, 0, 6, 17, -13, -2, -10, -17, -1, -18, 2, 0, 14, -6, 1, 0, 3, 2, -10, 1, -5, -2, 5 }, - { 16, -37, -1, 26, -2, -14, 1, -5, -14, 2, 2, 3, 6, 1, 1, 4, + { 16, -37, -1, 26, -2, -14, 1, -5, -14, 2, 2, 3, 6, 1, 1, 4, 0, -1, 0, -2, -2, 4, 9, -6, 0, -2, 10, -7, -2, 4, 1, 0 }, - { -9, -24, -12, 5, 5, 3, -17, -14, 4, 3, 2, -4, 10, -22, -8, -3, + { -9, -24, -12, 5, 5, 3, -17, -14, 4, 3, 2, -4, 10, -22, -8, -3, 6, 1, 12, -8, 4, 1, 9, -1, 18, -3, 6, 5, 3, -5, 9, -5 }, - { -14, -33, -2, 20, -13, -10, 2, -7, -1, 11, -9, -8, 18, -3, 1, 8, + { -14, -33, -2, 20, -13, -10, 2, -7, -1, 11, -9, -8, 18, -3, 1, 8, 0, -2, 10, 7, -2, -13, 9, -3, -4, 5, -2, -2, -1, -5, 1, -7 }, - { -10, -23, 8, 14, 1, 7, 1, -3, -7, 4, 1, 1, 8, -7, 15, -14, + { -10, -23, 8, 14, 1, 7, 1, -3, -7, 4, 1, 1, 8, -7, 15, -14, 13, 14, 2, 5, -13, -5, -8, -1, 6, 3, 6, 9, 6, 15, 14, 5 }, - { -13, -25, -10, 13, -17, -24, -7, -13, -6, -10, -8, 2, 0, -13, -10, -4, + { -13, -25, -10, 13, -17, -24, -7, -13, -6, -10, -8, 2, 0, -13, -10, -4, -8, 4, -9, 9, -4, 4, -3, -3, 3, 3, -5, -9, 1, -2, 11, 2 }, - { -12, -23, 1, 18, -11, -2, 5, 9, -5, 5, 14, -9, -3, -2, -6, 2, + { -12, -23, 1, 18, -11, -2, 5, 9, -5, 5, 14, -9, -3, -2, -6, 2, -2, 11, -13, 1, -3, 11, -9, -4, -2, -6, 8, 10, 1, 4, 2, 1 }, - { -5, -18, 16, 22, 2, 0, 8, -6, -9, -7, 10, -16, 23, 10, -11, -1, + { -5, -18, 16, 22, 2, 0, 8, -6, -9, -7, 10, -16, 23, 10, -11, -1, 7, 2, 7, 2, 1, -5, 6, 1, 0, -4, 9, 2, -3, 1, 0, -4 }, - { -3, -26, 14, 11, 2, -9, 17, -2, -1, -5, -16, -9, -5, 10, -13, 1, + { -3, -26, 14, 11, 2, -9, 17, -2, -1, -5, -16, -9, -5, 10, -13, 1, 6, 12, 10, 11, 0, 0, -3, -14, 6, -2, 0, 4, -5, -1, -7, -1 }, - { -10, -33, 1, 8, 11, -5, 1, -6, 7, 4, 5, 6, 1, -2, -10, -5, + { -10, -33, 1, 8, 11, -5, 1, -6, 7, 4, 5, 6, 1, -2, -10, -5, -6, 12, -11, 5, -10, 4, 12, -1, -1, -3, 4, -1, 9, 0, 16, -17 }, - { -14, -37, 7, 7, -2, 5, -8, -11, 2, -13, 4, -19, 1, 8, 8, 4, + { -14, -37, 7, 7, -2, 5, -8, -11, 2, -13, 4, -19, 1, 8, 8, 4, -9, 2, -4, 3, 12, 2, 4, -4, -8, 8, 1, 4, 8, -1, 6, -2 }, - { -6, -30, 18, 17, 1, -22, -3, 4, -7, -10, 7, 0, -8, 8, -1, 4, + { -6, -30, 18, 17, 1, -22, -3, 4, -7, -10, 7, 0, -8, 8, -1, 4, 2, 8, 6, -2, 2, 7, 4, 4, 3, -6, 2, 1, -3, 1, -1, -5 }, - { -17, -18, -3, 22, -8, 1, 9, -2, -17, 20, -5, -5, -12, -5, 4, -5, + { -17, -18, -3, 22, -8, 1, 9, -2, -17, 20, -5, -5, -12, -5, 4, -5, -9, 8, -2, 16, -3, 0, 19, -8, 8, 1, 2, -4, 0, 11, 0, -3 }, - { -9, -23, 3, 10, 4, 4, -3, -2, -2, -2, 1, -22, 11, 0, -2, 5, + { -9, -23, 3, 10, 4, 4, -3, -2, -2, -2, 1, -22, 11, 0, -2, 5, -2, 14, -9, -11, -4, 7, 5, 32, 1, -3, -7, 0, 21, -9, 7, -6 }, - { 0, 0, 0, 2, -1, 1, 0, 1, 3, 0, 0, 1, 0, 1, 0, 1, + { 0, 0, 0, 2, -1, 1, 0, 1, 3, 0, 0, 1, 0, 1, 0, 1, -3, 0, -1, -2, 0, -1, -1, -3, -1, 1, -4, 1, -1, -5, -69, -19 }, - { -3, -5, -8, -12, 4, -3, -19, -11, -5, 0, -14, 7, 18, -6, 7, 22, + { -3, -5, -8, -12, 4, -3, -19, -11, -5, 0, -14, 7, 18, -6, 7, 22, 8, 14, 15, 10, 3, -1, -3, 5, -1, 7, -7, 1, -6, 3, -26, -11 }, - { -1, -6, 4, -4, -5, -16, 0, -6, -3, 11, 1, 0, 9, 5, 16, 3, + { -1, -6, 4, -4, -5, -16, 0, -6, -3, 11, 1, 0, 9, 5, 16, 3, -4, -33, -4, 4, -7, 0, 1, 6, -11, -2, -13, -2, -18, 20, -25, -16 }, - { 4, 0, -1, 0, -5, 1, 0, 2, 0, 11, -10, 4, -10, 7, 16, 2, + { 4, 0, -1, 0, -5, 1, 0, 2, 0, 11, -10, 4, -10, 7, 16, 2, 16, 15, 2, -1, 2, 9, 2, 8, -3, -5, -2, 0, -3, 0, -33, -2 }, - { -3, -15, 10, 10, -9, -1, 7, 3, 5, -5, -8, -8, -3, 15, -9, 4, + { -3, -15, 10, 10, -9, -1, 7, 3, 5, -5, -8, -8, -3, 15, -9, 4, 12, 13, -13, -14, 10, -6, 9, 22, -27, 23, -1, 5, -24, 2, -30, 5 }, - { 0, -2, 7, -5, -5, 3, 5, 3, -3, -5, 2, 1, -4, 3, -3, -1, + { 0, -2, 7, -5, -5, 3, 5, 3, -3, -5, 2, 1, -4, 3, -3, -1, 1, -2, 10, 22, -3, -4, -2, -2, -7, 3, 8, 1, 14, 4, -37, 9 }, - { -3, -4, -1, 1, -4, 0, 6, 2, 6, -7, -10, -10, -1, -4, 11, -3, + { -3, -4, -1, 1, -4, 0, 6, 2, 6, -7, -10, -10, -1, -4, 11, -3, 7, -6, 4, -12, -1, 5, 1, -7, 10, -6, 17, -4, 8, 3, -40, 13 }, - { 2, 12, 4, -7, 14, -3, 16, -2, 18, 2, 13, 5, 5, 1, 11, -1, + { 2, 12, 4, -7, 14, -3, 16, -2, 18, 2, 13, 5, 5, 1, 11, -1, 0, 9, 2, -6, -1, 2, -6, 2, -5, 3, 5, 1, -1, 1, -32, -7 }, - { -16, 11, 7, -4, 2, -5, -9, 9, 11, 11, 15, -13, -11, 11, 9, 4, + { -16, 11, 7, -4, 2, -5, -9, 9, 11, 11, 15, -13, -11, 11, 9, 4, 3, -8, -10, 12, 12, 0, 0, -16, -9, 13, 2, 9, 4, -13, -33, 3 }, - { 6, 4, 5, 4, 3, -1, 5, 6, 4, 2, -11, -1, -15, -11, -1, 1, + { 6, 4, 5, 4, 3, -1, 5, 6, 4, 2, -11, -1, -15, -11, -1, 1, 11, -3, -2, 24, -4, -6, -25, -10, -15, -8, 0, 0, -5, 4, -30, 2 }, - { 10, -3, -6, 1, -9, -5, 6, 9, -10, -3, 8, -1, 4, -1, 11, -11, + { 10, -3, -6, 1, -9, -5, 6, 9, -10, -3, 8, -1, 4, -1, 11, -11, 3, 9, 11, -3, 6, -17, 5, -8, -33, 9, -13, 19, -2, 9, -25, 2 }, - { 0, 0, -1, -3, 0, -2, 1, 0, 0, 2, 1, 0, -2, 0, -1, 2, + { 0, 0, -1, -3, 0, -2, 1, 0, 0, 2, 1, 0, -2, 0, -1, 2, 0, -1, 4, -1, 2, -3, 4, -2, 3, 3, 1, 0, -15, 12, -63, 27 }, - { -2, 14, 9, -1, 3, 0, 1, 1, -19, 15, 3, 4, 0, -10, 1, -5, + { -2, 14, 9, -1, 3, 0, 1, 1, -19, 15, 3, 4, 0, -10, 1, -5, 3, 0, -5, -10, 2, -16, -4, 8, -12, -6, 7, -5, -10, -1, -33, -4 }, - { 0, 3, 1, 3, 1, 2, 4, 4, 9, -6, -8, -5, 1, -12, 3, 8, + { 0, 3, 1, 3, 1, 2, 4, 4, 9, -6, -8, -5, 1, -12, 3, 8, -10, 6, -1, 1, 13, -5, -5, 2, -4, 13, -18, -10, -7, -9, -33, 10 }, - { -6, -3, -12, 5, -1, 11, -6, 0, -2, 1, 2, -7, 3, 1, 3, -2, + { -6, -3, -12, 5, -1, 11, -6, 0, -2, 1, 2, -7, 3, 1, 3, -2, 1, 8, -10, 7, -1, -3, 3, 0, 13, 1, 6, 7, -16, -7, -39, 8 }, - { -6, -1, 11, 6, -3, 8, 3, -5, 3, 0, -5, -2, -6, -3, -4, 2, + { -6, -1, 11, 6, -3, 8, 3, -5, 3, 0, -5, -2, -6, -3, -4, 2, -3, 13, -11, 1, 7, 5, 19, -5, -3, -15, -1, 7, -1, 6, -33, 8 }, - { -7, 3, -4, -3, -4, 1, 6, -5, -5, 6, -8, -1, -7, 4, -1, -6, + { -7, 3, -4, -3, -4, 1, 6, -5, -5, 6, -8, -1, -7, 4, -1, -6, -2, 1, 7, 0, 1, 1, -5, 2, -2, 0, -13, -2, -31, -14, -39, -12 }, - { -10, 9, 0, -3, 1, -1, -1, 0, 1, -5, -1, -4, -2, 5, 2, -7, + { -10, 9, 0, -3, 1, -1, -1, 0, 1, -5, -1, -4, -2, 5, 2, -7, 18, -8, -2, -19, -7, -7, -12, -14, -11, -1, -9, -13, -7, -12, -31, -9 }, - { -3, -16, 10, 9, 1, -10, -12, 2, -2, 2, 7, -3, -3, 1, -4, -5, + { -3, -16, 10, 9, 1, -10, -12, 2, -2, 2, 7, -3, -3, 1, -4, -5, -9, 5, 7, 3, -1, 4, -11, -8, 4, 13, -10, 13, 10, -4, -36, 1 }, - { -7, -12, 4, -20, -7, -7, 2, 11, -1, -2, 3, -12, 1, 0, -6, -7, + { -7, -12, 4, -20, -7, -7, 2, 11, -1, -2, 3, -12, 1, 0, -6, -7, 6, 4, 13, 3, -3, 4, 3, -6, -12, 5, -5, -22, -13, -8, -37, -6 }, - { -7, 5, 3, 5, 7, 9, -14, -3, 10, 17, -1, 1, -12, 5, -6, 0, + { -7, 5, 3, 5, 7, 9, -14, -3, 10, 17, -1, 1, -12, 5, -6, 0, -4, -9, 0, -11, -14, 3, 13, 6, -25, -8, -12, 4, -10, 18, -30, -1 }, - { -10, 6, -10, 6, 6, 1, -10, 0, -7, 5, -2, 17, -18, -4, 0, -3, + { -10, 6, -10, 6, 6, 1, -10, 0, -7, 5, -2, 17, -18, -4, 0, -3, -16, -6, -3, -8, 5, 1, -4, 6, -7, 16, 6, 10, -1, 0, -32, -11 }, - { -1, 9, 9, -5, 4, 9, 6, 9, -4, -2, 7, 11, 4, 2, -5, -4, + { -1, 9, 9, -5, 4, 9, 6, 9, -4, -2, 7, 11, 4, 2, -5, -4, -6, 0, 2, -3, -1, 5, 10, 0, 12, -10, -18, -3, -1, 14, -33, 2 }, - { 4, -8, -18, -4, -5, -11, 4, -10, -4, 9, 13, -12, 1, -6, 1, 2, + { 4, -8, -18, -4, -5, -11, 4, -10, -4, 9, 13, -12, 1, -6, 1, 2, 4, -9, 8, 3, -6, 21, 13, -1, -2, 1, -2, 6, -7, 0, -30, 1 }, - { 6, -1, 2, -3, -1, -4, 6, -4, 0, 4, 2, 2, -9, 2, 6, 3, + { 6, -1, 2, -3, -1, -4, 6, -4, 0, 4, 2, 2, -9, 2, 6, 3, -2, 4, -1, 9, -6, 0, 7, -8, 5, 19, -2, 9, -5, 2, -33, -8 }, - { 2, 1, 12, -5, -8, 8, 3, -2, -4, 1, -2, 5, -4, -9, -8, -8, + { 2, 1, 12, -5, -8, 8, 3, -2, -4, 1, -2, 5, -4, -9, -8, -8, 7, -11, -4, 6, -10, 7, -1, -1, -2, -1, 16, 32, -7, 20, -33, -6 }, - { -18, 2, 6, 13, 9, 9, -1, 3, -17, 24, -2, -6, 28, 8, -2, 6, + { -18, 2, 6, 13, 9, 9, -1, 3, -17, 24, -2, -6, 28, 8, -2, 6, 3, -10, -34, -16, -13, -4, -15, -11, -12, -3, -10, 4, -8, 4, -31, -4 }, - { -11, 0, 18, 2, -16, -9, -13, -2, -2, -12, -3, -22, 30, 0, 8, 3, + { -11, 0, 18, 2, -16, -9, -13, -2, -2, -12, -3, -22, 30, 0, 8, 3, 9, -4, -16, 1, 0, -11, 15, -2, -4, 6, -5, 6, 1, 2, -25, -12 }, - { 14, -1, 5, 7, 3, -15, -8, 1, 5, -2, 12, 13, 11, -25, 3, 1, + { 14, -1, 5, 7, 3, -15, -8, 1, 5, -2, 12, 13, 11, -25, 3, 1, 0, -2, -4, -16, -23, 0, -5, -17, 7, 5, -9, 6, -5, 2, -32, -7 }, - { 3, -1, 6, 14, 2, -12, -9, -9, 4, 7, 4, 6, 5, -8, 4, 2, + { 3, -1, 6, 14, 2, -12, -9, -9, 4, 7, 4, 6, 5, -8, 4, 2, 4, 5, -2, 8, 8, -6, 0, 10, -20, -1, 3, -1, 8, 23, -33, -5 }, - { -3, 11, -6, 3, -4, 5, 7, 3, 4, 5, -2, 3, -1, 30, 6, 1, + { -3, 11, -6, 3, -4, 5, 7, 3, 4, 5, -2, 3, -1, 30, 6, 1, 8, -6, 0, 0, -9, 6, -9, 4, 2, 9, -6, 1, -12, 0, -34, 18 }, - { -17, 13, 0, 1, 9, -4, -11, 0, 7, 0, -10, -4, -1, 6, -6, 4, + { -17, 13, 0, 1, 9, -4, -11, 0, 7, 0, -10, -4, -1, 6, -6, 4, 1, 6, -9, 3, -5, -6, -11, 2, -4, 14, 23, -3, 2, 5, -30, 12 }, - { -14, 5, -27, 2, 0, 7, 1, 4, 30, 8, 7, 5, 1, -1, 0, 5, + { -14, 5, -27, 2, 0, 7, 1, 4, 30, 8, 7, 5, 1, -1, 0, 5, 8, -10, 48, -11, 12, 33, 6, 8, -15, 20, -2, -5, 32, 5, -19, 10 }, - { -16, -4, -12, -7, -2, 0, 8, -6, -20, -18, 16, -3, 0, 31, -2, 11, + { -16, -4, -12, -7, -2, 0, 8, -6, -20, -18, 16, -3, 0, 31, -2, 11, 2, -9, 49, -19, -12, -23, 10, 26, 16, -2, 4, -21, -14, 13, -11, -9 }, - { -5, -9, -1, 3, -5, -21, 2, 10, 0, 0, 10, -21, -7, 7, -26, -9, + { -5, -9, -1, 3, -5, -21, 2, 10, 0, 0, 10, -21, -7, 7, -26, -9, 22, 32, 58, 11, -3, 11, -5, -8, -13, 6, -5, -9, 1, 10, 14, -8 }, - { 7, 7, 10, 3, -2, -1, -11, -11, -6, -43, -3, 14, -19, -18, 19, 18, + { 7, 7, 10, 3, -2, -1, -11, -11, -6, -43, -3, 14, -19, -18, 19, 18, -32, 10, 45, -6, 6, 21, -20, -12, 2, 4, 6, 6, -4, 3, 3, 1 }, - { 21, 22, -3, -2, -11, -6, -1, -2, 8, 8, 32, -21, 7, 28, -4, -6, + { 21, 22, -3, -2, -11, -6, -1, -2, 8, 8, 32, -21, 7, 28, -4, -6, -3, -2, 50, 2, 2, 27, -5, -8, 12, 7, -5, -1, -4, -17, 27, 6 }, - { 13, 7, 2, -6, -12, 2, -10, -5, -17, 11, 4, 17, -12, -2, 5, -17, + { 13, 7, 2, -6, -12, 2, -10, -5, -17, 11, 4, 17, -12, -2, 5, -17, 37, -16, 48, -14, -18, 29, 8, 24, 11, -5, -9, 11, -1, 1, -13, -3 }, - { 1, 1, -1, 2, 0, 0, 0, -1, 1, -1, 7, 2, -3, 3, 0, 6, + { 1, 1, -1, 2, 0, 0, 0, -1, 1, -1, 7, 2, -3, 3, 0, 6, 2, 10, 54, -25, 7, 54, -5, -6, -1, -15, 9, 13, -24, -15, -12, 3 }, - { 21, 5, 8, 3, -3, -4, -2, -4, 3, -11, -5, -8, 9, 16, 8, -9, + { 21, 5, 8, 3, -3, -4, -2, -4, 3, -11, -5, -8, 9, 16, 8, -9, -10, -3, 46, -46, 2, 1, -10, 10, 17, 11, -20, -36, 10, 14, 0, -5 }, - { 7, -13, -6, -9, -24, 45, 2, 8, 8, 0, 17, 20, 12, -24, 1, -7, + { 7, -13, -6, -9, -24, 45, 2, 8, 8, 0, 17, 20, 12, -24, 1, -7, -15, -3, 46, -13, -2, 20, 1, -13, -11, -13, 2, 15, 1, 10, -1, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, -1, -16, -9, 31, -69, -34, 26, 7, 17, -1, -6, -1, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -4, -5, -20, 18, -82, 22, 3, -7, 9, 4, 6, 2, -4, -1, 0, -2, 2 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 4, -1, 15, -5, 62, -36, 4, 52, -7, 5, 0, 6, 1, 2, 1, 1, -1, 0 }, - { 3, -19, 19, -20, 13, -4, -11, 8, 8, -16, 10, 1, -14, 30, 1, -33, + { 3, -19, 19, -20, 13, -4, -11, 8, 8, -16, 10, 1, -14, 30, 1, -33, 10, -11, 45, -30, 3, -4, -3, -13, 7, 12, 3, -22, 3, -2, -4, -2 }, - { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, + { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, 11, 8, 70, 48, -10, 21, 4, 9, -9, -9, -4, -6, 0, -1, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, -1, 80, 2, -15, -36, -10, -5, -2, 8, -2, 2, 0, 0, 0, 0 }, - { 10, 8, -8, -8, -24, 12, -1, 0, 20, 9, -1, -2, 2, -2, 12, -10, + { 10, 8, -8, -8, -24, 12, -1, 0, 20, 9, -1, -2, 2, -2, 12, -10, -2, -13, 35, -43, 44, 15, -10, -25, 4, 10, -3, -5, -5, 7, -1, 3 }, - { 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -1, + { 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, -2, -1, -18, 9, 49, -72, 7, -8, 7, -5, 2, 3, 2, -2, 1, -2, -3, 1 }, - { -1, 4, -3, 10, 19, 4, 3, 20, 6, -24, 6, 9, 8, 15, 18, 18, + { -1, 4, -3, 10, 19, 4, 3, 20, 6, -24, 6, 9, 8, 15, 18, 18, -36, 19, 57, -11, 4, -3, 8, 7, 2, -3, -2, -9, -15, -2, 12, -4 }, - { 20, 3, 11, -9, -4, 22, 42, -25, 1, 5, -10, -19, 0, 9, -16, 5, + { 20, 3, 11, -9, -4, 22, 42, -25, 1, 5, -10, -19, 0, 9, -16, 5, 2, 10, 44, -29, 17, -3, -9, -2, -1, 8, 14, -7, -1, 16, -5, 1 }, - { -7, 16, -11, 12, 6, 33, -15, 14, -23, 2, -26, 8, 2, 10, 0, -5, + { -7, 16, -11, 12, 6, 33, -15, 14, -23, 2, -26, 8, 2, 10, 0, -5, 8, -8, 38, -38, -4, 5, 5, 5, 1, 22, -15, 7, 6, 0, 4, 28 }, - { -1, -12, 2, 10, -2, 0, 7, 17, 12, 22, -4, 10, 25, 29, 5, 18, + { -1, -12, 2, 10, -2, 0, 7, 17, 12, 22, -4, 10, 25, 29, 5, 18, 4, 1, 27, -39, 31, 17, 2, 2, 22, -23, 13, 16, 1, -7, -4, -5 }, - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 0, -14, 0, + { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -2, 0, -14, 0, -7, -11, 49, -22, -4, 19, 17, -39, 4, -29, 10, 2, 36, -4, 23, -1 }, - { -2, -2, -2, -2, 1, 15, -5, -7, -16, -8, -19, 16, -3, -20, 36, -9, + { -2, -2, -2, -2, 1, 15, -5, -7, -16, -8, -19, 16, -3, -20, 36, -9, -3, 20, 39, -20, 0, 2, 27, -16, 10, 10, -14, -22, -16, -3, 13, -8 }, - { 5, -9, 6, -25, 7, 37, 13, -10, -5, 3, -5, 7, 18, -22, -7, 9, + { 5, -9, 6, -25, 7, 37, 13, -10, -5, 3, -5, 7, 18, -22, -7, 9, -5, -4, 50, -11, -4, -5, -5, 8, -4, -2, -4, -27, 14, 20, 7, -9 }, - { 0, -14, -10, -27, -14, -17, -6, 26, 10, 2, 14, -12, -5, 0, 8, 9, + { 0, -14, -10, -27, -14, -17, -6, 26, 10, 2, 14, -12, -5, 0, 8, 9, 0, -28, 55, -7, -12, -7, 4, -10, 10, 7, -12, 11, 3, 5, 9, -8 }, - { 2, 23, 4, -2, -1, -20, -2, 14, 10, -9, -9, -24, 10, 0, 11, -12, + { 2, 23, 4, -2, -1, -20, -2, 14, 10, -9, -9, -24, 10, 0, 11, -12, 12, 11, 49, -25, -2, 29, 7, -13, 21, -10, 11, -17, 3, 1, -8, 5 }, - { 3, 0, -14, -6, 18, -2, 17, -9, -19, 9, -5, 9, 14, 6, 19, -3, + { 3, 0, -14, -6, 18, -2, 17, -9, -19, 9, -5, 9, 14, 6, 19, -3, 27, 1, 41, -21, 20, -15, 33, 0, 26, 14, 7, 10, 3, 20, -3, -12 }, - { -1, 16, 15, -8, 3, -8, -8, 21, -5, -16, -29, 4, 1, -6, -4, -28, + { -1, 16, 15, -8, 3, -8, -8, 21, -5, -16, -29, 4, 1, -6, -4, -28, 2, 31, 37, -26, -2, 13, 24, 8, -9, -6, -29, 10, 7, 2, 7, 8 }, - { -10, -10, 11, 13, -32, 2, 16, 9, 14, 23, -15, -13, 24, 13, 4, -27, + { -10, -10, 11, 13, -32, 2, 16, 9, 14, 23, -15, -13, 24, 13, 4, -27, 14, 12, 31, -18, 17, 23, -2, -7, -14, 9, -17, -6, -10, 20, 9, 6 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 5, 1, 89, 8, 10, -6, 2, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, -1, 4, -7, 64, -50, 7, 37, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, - { -2, 5, 3, -4, -4, -3, 2, -3, 3, -3, 5, 4, 1, -6, -1, 1, + { -2, 5, 3, -4, -4, -3, 2, -3, 3, -3, 5, 4, 1, -6, -1, 1, 6, -2, 50, -35, -7, 43, 7, -7, -5, -26, 24, 21, 3, -15, 5, 6 }, - { -8, 21, -19, 33, -8, 22, -11, 17, 3, 0, 0, -2, 1, -3, 6, -1, + { -8, 21, -19, 33, -8, 22, -11, 17, 3, 0, 0, -2, 1, -3, 6, -1, 10, -8, 4, -11, -4, -5, 0, 8, -4, 3, 1, -4, 4, 2, 8, 4 }, - { -7, 5, -20, 9, -22, 3, -14, 1, 6, 13, 23, -2, -4, -7, 2, 0, + { -7, 5, -20, 9, -22, 3, -14, 1, 6, 13, 23, -2, -4, -7, 2, 0, 11, 4, 6, 3, -7, -11, -7, 4, 5, 5, -12, 8, 2, 4, 7, -3 }, - { -7, 6, -4, 20, -20, 16, -2, 7, 6, 16, 11, 12, -7, -7, 5, 3, + { -7, 6, -4, 20, -20, 16, -2, 7, 6, 16, 11, 12, -7, -7, 5, 3, -9, -4, 1, 2, 5, 2, 1, -9, -2, -17, -4, 6, -10, 7, -7, -6 }, - { -9, 18, -17, 12, -24, 1, -1, 4, 14, 9, 4, 3, 2, 8, -12, -14, + { -9, 18, -17, 12, -24, 1, -1, 4, 14, 9, 4, 3, 2, 8, -12, -14, 4, -8, -4, 7, 7, 6, -1, 13, -9, -4, -1, 1, 0, -4, 15, 8 }, - { -25, 2, -11, 6, -5, 24, -28, -5, 8, 12, -2, 6, 8, -3, 8, -9, + { -25, 2, -11, 6, -5, 24, -28, -5, 8, 12, -2, 6, 8, -3, 8, -9, -1, -5, -1, -5, 6, -1, -1, -1, -4, 8, -12, -2, -13, 7, 2, 1 }, - { -14, 14, -18, 20, -10, 12, -2, 9, 1, 0, 12, -2, 15, -10, 26, -17, + { -14, 14, -18, 20, -10, 12, -2, 9, 1, 0, 12, -2, 15, -10, 26, -17, 16, -11, 10, -10, 9, -2, 4, -8, 2, -3, 4, 4, 2, -3, -5, 1 }, - { -18, 12, -18, 21, -6, 12, -6, 13, -25, 18, 1, 11, -9, -5, 0, 10, + { -18, 12, -18, 21, -6, 12, -6, 13, -25, 18, 1, 11, -9, -5, 0, 10, -5, 3, -3, 8, -9, 7, 4, 2, -9, 0, 5, 0, 2, -3, 9, -8 }, - { -4, 16, 1, 18, -30, 9, 1, 6, -8, 13, 13, -12, -6, -1, 13, 7, + { -4, 16, 1, 18, -30, 9, 1, 6, -8, 13, 13, -12, -6, -1, 13, 7, 6, 2, -15, -3, 5, 5, 1, -6, 1, -5, 0, 2, -16, 0, 3, -4 }, - { -21, 1, -2, 6, -43, 18, -1, 5, -1, 4, 6, -2, -1, -3, -1, -3, + { -21, 1, -2, 6, -43, 18, -1, 5, -1, 4, 6, -2, -1, -3, -1, -3, 0, 1, 2, -9, 0, -1, 0, -2, 0, -1, -1, -2, 6, 0, 1, -2 }, - { -23, 10, 4, 7, -32, -11, -18, 2, -2, -7, -6, -3, -3, -12, 19, 3, + { -23, 10, 4, 7, -32, -11, -18, 2, -2, -7, -6, -3, -3, -12, 19, 3, -5, -6, 16, -6, 16, 2, 16, 16, 8, -2, 13, 8, -15, -11, 2, 10 }, - { -8, 2, -13, 2, -29, 24, -20, 19, 1, 10, -4, 10, 1, 2, -9, 11, + { -8, 2, -13, 2, -29, 24, -20, 19, 1, 10, -4, 10, 1, 2, -9, 11, -1, -2, 9, -5, 19, -7, 16, -9, -2, -18, 11, 1, 1, 0, 7, -3 }, - { -6, 3, 4, 13, -26, 10, -10, 28, -7, 28, 1, 7, 0, -14, 5, 7, + { -6, 3, 4, 13, -26, 10, -10, 28, -7, 28, 1, 7, 0, -14, 5, 7, 4, -4, 3, -2, 3, 3, -11, 7, 6, 4, 0, -1, 2, -1, -3, 2 }, - { -6, 16, -31, 13, -10, 17, -6, 4, -14, 4, 4, -1, -10, 12, -5, 1, + { -6, 16, -31, 13, -10, 17, -6, 4, -14, 4, 4, -1, -10, 12, -5, 1, -14, 15, 0, -8, 1, -5, 3, 3, 9, -5, 7, -20, 7, 4, 11, -5 }, - { -19, 3, -17, 14, -12, 16, -22, 18, 14, 8, -2, 4, 10, 12, -14, 4, + { -19, 3, -17, 14, -12, 16, -22, 18, 14, 8, -2, 4, 10, 12, -14, 4, -3, 2, 3, 7, -7, 7, -6, 2, -2, -4, -5, 0, -5, -2, 2, 1 }, - { -9, -7, -11, 24, -36, -9, -11, 5, 7, -12, -13, 18, -2, 20, 1, -4, + { -9, -7, -11, 24, -36, -9, -11, 5, 7, -12, -13, 18, -2, 20, 1, -4, -1, -10, 15, -6, 14, 1, 0, 2, 1, 2, -9, -16, -11, 7, 13, 0 }, - { -24, 24, -18, 18, -22, 14, -11, 13, -12, 11, -10, 11, -7, 11, -5, -4, + { -24, 24, -18, 18, -22, 14, -11, 13, -12, 11, -10, 11, -7, 11, -5, -4, -1, 1, 5, 2, 3, -1, 1, -5, 7, -4, 5, -6, 8, -7, 8, -6 }, - { -6, 18, -22, 22, 5, 11, -1, 6, 19, 22, 8, 4, -8, 20, -2, 15, + { -6, 18, -22, 22, 5, 11, -1, 6, 19, 22, 8, 4, -8, 20, -2, 15, -6, -18, 0, -33, -9, -12, -1, 6, 5, 2, 5, 5, -5, -17, -3, -3 }, - { 1, 11, -16, 9, -18, 11, -4, 18, 20, 26, -10, 8, 1, -11, 8, -4, + { 1, 11, -16, 9, -18, 11, -4, 18, 20, 26, -10, 8, 1, -11, 8, -4, 0, 7, 3, 5, 2, 2, 10, -2, -4, 4, -4, -2, 1, -4, -5, -1 }, - { -10, 6, -1, 18, -17, 27, -3, 10, -2, 12, -7, -9, 1, 1, -1, 7, + { -10, 6, -1, 18, -17, 27, -3, 10, -2, 12, -7, -9, 1, 1, -1, 7, -12, -1, -7, -6, -1, 8, 3, -15, 8, 9, 3, -7, 4, -1, 1, -1 }, - { -14, 6, -16, 22, 2, 5, 0, 5, -18, 11, 6, -3, 22, -20, -9, -3, + { -14, 6, -16, 22, 2, 5, 0, 5, -18, 11, 6, -3, 22, -20, -9, -3, 6, -6, -7, -15, 1, 15, -8, 11, 8, -3, -8, 1, -8, 2, 6, -2 }, - { -21, 5, -19, 19, -7, 4, -7, 0, -8, 6, 12, 5, -3, -22, -13, -6, + { -21, 5, -19, 19, -7, 4, -7, 0, -8, 6, 12, 5, -3, -22, -13, -6, -1, -3, -2, -14, 6, -3, 1, -8, -7, -5, -6, 11, -3, -10, -5, 2 }, - { -1, 9, -12, 15, -6, 6, -19, 14, -9, 11, 3, 12, -17, -3, 8, -4, + { -1, 9, -12, 15, -6, 6, -19, 14, -9, 11, 3, 12, -17, -3, 8, -4, -3, -4, 1, -5, 4, 5, -7, -15, -7, 15, -6, -5, 1, -5, -3, 1 }, - { -12, 20, -15, 20, -14, 3, -14, 9, -6, 33, -13, 6, -2, 8, -6, 7, + { -12, 20, -15, 20, -14, 3, -14, 9, -6, 33, -13, 6, -2, 8, -6, 7, -5, -6, -3, -3, 0, 8, -3, -3, 1, -2, 2, 2, 6, -5, -5, -2 }, - { -7, 12, -18, 12, -18, 10, -4, 8, 2, 4, 8, 9, 0, 3, -8, 3, + { -7, 12, -18, 12, -18, 10, -4, 8, 2, 4, 8, 9, 0, 3, -8, 3, 6, -12, -4, 1, 25, -5, -9, 6, -7, 0, -9, -7, 3, -5, -4, -4 }, - { -18, 12, -10, 11, -22, 0, -15, 5, -2, 2, -3, 6, -4, -4, -3, -15, + { -18, 12, -10, 11, -22, 0, -15, 5, -2, 2, -3, 6, -4, -4, -3, -15, -2, -3, 21, 6, -12, -11, 19, 3, 3, -14, 7, 0, -11, -22, -10, 0 }, - { -15, 2, -30, 15, -17, 13, -16, 8, -7, 10, -8, 2, 11, 3, 10, -7, + { -15, 2, -30, 15, -17, 13, -16, 8, -7, 10, -8, 2, 11, 3, 10, -7, 7, -22, 12, -10, 3, -12, 6, -10, 12, -10, 7, -8, 5, 2, 9, 1 }, - { -9, 11, -14, 6, -10, 21, 5, 12, -5, 5, 7, 21, 6, 2, -2, -1, + { -9, 11, -14, 6, -10, 21, 5, 12, -5, 5, 7, 21, 6, 2, -2, -1, -1, 4, 2, -20, -18, -1, -14, 3, -1, 4, -7, 10, 1, 11, 4, -4 }, - { -22, 8, -30, 13, -21, -4, 4, -1, 12, 9, -2, -3, 2, -6, 4, -13, + { -22, 8, -30, 13, -21, -4, 4, -1, 12, 9, -2, -3, 2, -6, 4, -13, -2, 8, 8, 1, -7, 3, -4, -5, -1, -7, -2, 8, 8, 7, 8, 0 }, - { -6, -4, -35, 16, -13, 15, -11, 14, -7, 9, -1, 11, 7, 0, 13, 10, + { -6, -4, -35, 16, -13, 15, -11, 14, -7, 9, -1, 11, 7, 0, 13, 10, -1, 8, 1, 1, -2, 8, -1, 2, 2, 3, -10, -1, 7, -13, -3, -7 }, - { -15, 7, -16, 14, -18, 17, -6, 14, 3, 4, 7, -3, 10, -22, 5, -15, + { -15, 7, -16, 14, -18, 17, -6, 14, 3, 4, 7, -3, 10, -22, 5, -15, 4, -4, -11, 15, -15, 11, -11, 20, 1, 0, 2, 1, 11, -3, 11, -7 }, - { -12, 3, 5, 16, -37, -1, 15, 15, -15, 10, 3, -10, 1, 15, 7, -15, + { -12, 3, 5, 16, -37, -1, 15, 15, -15, 10, 3, -10, 1, 15, 7, -15, -13, 8, 9, -3, 2, 12, -8, 2, -5, 0, -3, 4, 5, -9, -4, 5 }, - { -16, 26, -4, 14, -22, 26, 6, -3, -8, 4, 21, 6, 16, -4, -11, 7, + { -16, 26, -4, 14, -22, 26, 6, -3, -8, 4, 21, 6, 16, -4, -11, 7, -10, 3, 3, 7, -4, 2, -9, 8, -2, 2, 5, -2, -4, -2, 7, -1 }, - { -7, -10, 4, 3, 2, -4, -12, -10, -4, -5, 16, 19, -16, 1, 2, -9, + { -7, -10, 4, 3, 2, -4, -12, -10, -4, -5, 16, 19, -16, 1, 2, -9, -10, 0, 9, 7, -8, 3, 12, 8, -6, -11, -13, -1, -3, -20, 6, -5 }, - { -14, -17, 3, -5, 14, -12, -12, 8, -6, -25, 21, 21, 10, -8, -12, 4, + { -14, -17, 3, -5, 14, -12, -12, 8, -6, -25, 21, 21, 10, -8, -12, 4, 10, -4, 3, -9, 11, 9, 0, 4, 2, -15, 1, -14, 4, 1, 0, -4 }, - { -4, -9, -3, -1, 6, 3, -6, 6, -10, -4, 14, 8, 2, -3, -12, -19, + { -4, -9, -3, -1, 6, 3, -6, 6, -10, -4, 14, 8, 2, -3, -12, -19, 0, 11, -20, 1, 6, -2, -27, -6, 10, -17, -14, -17, -9, 8, -8, 3 }, - { -12, -13, 16, -4, -2, 12, -7, -11, 2, -13, 3, 7, -16, -18, -1, -12, + { -12, -13, 16, -4, -2, 12, -7, -11, 2, -13, 3, 7, -16, -18, -1, -12, -2, 1, -12, -9, -2, -6, 2, 9, -22, -3, -4, -14, -7, 7, -1, 2 }, - { -7, -8, -8, 15, 15, 18, 15, 16, -4, -37, 11, 15, -12, -1, -3, 3, + { -7, -8, -8, 15, 15, 18, 15, 16, -4, -37, 11, 15, -12, -1, -3, 3, 6, 6, 0, -5, -3, -5, 9, 1, 1, -11, -1, -8, -6, 2, 3, 0 }, - { -6, 7, -5, -12, 13, 10, -18, -4, -3, -21, 6, 16, -15, -7, -12, -9, + { -6, 7, -5, -12, 13, 10, -18, -4, -3, -21, 6, 16, -15, -7, -12, -9, 1, -12, -1, 10, -2, -1, -3, 4, -4, 1, -16, -1, 12, -9, 5, 9 }, - { -14, -5, 9, 3, 4, 26, -28, 3, -6, -24, 4, 5, 3, 13, 5, -1, + { -14, -5, 9, 3, 4, 26, -28, 3, -6, -24, 4, 5, 3, 13, 5, -1, 3, -1, 3, 1, 1, -5, 3, 0, -7, -8, -7, -3, 3, -5, 4, 0 }, - { -4, 2, -10, -6, 25, 26, -6, 10, -6, -8, 15, 11, -6, -3, 2, -7, + { -4, 2, -10, -6, 25, 26, -6, 10, -6, -8, 15, 11, -6, -3, 2, -7, 5, 14, 9, -1, 0, -12, 4, -4, -10, 1, -3, 3, -2, -2, -6, -1 }, - { -10, 8, -15, -10, 19, 17, -8, 0, -3, -7, 7, 5, -13, -1, 7, -7, + { -10, 8, -15, -10, 19, 17, -8, 0, -3, -7, 7, 5, -13, -1, 7, -7, 1, 13, -12, -13, 17, -12, 1, 26, -18, -3, -5, -6, 4, 5, 8, 1 }, - { 2, -5, 3, 0, 0, 0, 2, -3, -2, -5, 7, 13, -4, 9, 0, -5, + { 2, -5, 3, 0, 0, 0, 2, -3, -2, -5, 7, 13, -4, 9, 0, -5, 4, -1, -11, -8, -4, 0, -13, 2, -47, -23, -8, -11, -4, 4, -2, -3 }, - { -18, -4, 4, 5, -1, 17, -12, -8, 1, -12, 7, 20, -12, 3, -2, -11, + { -18, -4, 4, 5, -1, 17, -12, -8, 1, -12, 7, 20, -12, 3, -2, -11, 16, 12, -6, 1, -13, -16, -6, -3, -3, -5, 4, -12, -5, -9, 10, 1 }, - { -11, 0, 4, 7, 7, 8, 3, -1, 3, -19, 32, 8, -19, -8, 2, 4, + { -11, 0, 4, 7, 7, 8, 3, -1, 3, -19, 32, 8, -19, -8, 2, 4, -12, 15, -16, 3, 1, 9, -2, 1, -2, 8, 5, 6, -4, -1, 11, -8 }, - { 3, -1, 4, -2, 14, 32, -9, -23, -10, -12, 22, 15, -1, -2, 10, 0, + { 3, -1, 4, -2, 14, 32, -9, -23, -10, -12, 22, 15, -1, -2, 10, 0, 4, 6, -8, 4, -15, -2, -1, -4, 0, -8, 4, 1, -8, 3, 4, 1 }, - { -17, -12, 6, -8, 16, 13, -20, -8, -1, -16, 10, 21, -19, 11, -9, -5, + { -17, -12, 6, -8, 16, 13, -20, -8, -1, -16, 10, 21, -19, 11, -9, -5, 7, 18, -6, 7, -7, -18, 13, 2, -2, 8, -12, -9, 2, 4, -5, 16 }, - { 4, 0, 17, -11, 12, 7, -12, 5, -1, -25, 30, -8, -7, -6, -4, -7, + { 4, 0, 17, -11, 12, 7, -12, 5, -1, -25, 30, -8, -7, -6, -4, -7, 9, 8, 7, 3, 3, -16, 8, 0, -2, -2, -18, -3, -4, -5, 1, 4 }, - { -3, -6, 6, -16, 17, 6, -3, 2, -9, -17, 12, 11, 11, 2, -20, 8, + { -3, -6, 6, -16, 17, 6, -3, 2, -9, -17, 12, 11, 11, 2, -20, 8, 1, 1, 0, 2, -2, -6, -21, -13, -9, -15, -1, -8, -6, -8, 0, -2 }, - { -11, -7, 6, -9, 3, 6, 8, 16, 4, -5, 23, 26, -10, -3, 4, 0, + { -11, -7, 6, -9, 3, 6, 8, 16, 4, -5, 23, 26, -10, -3, 4, 0, 2, 2, -4, 4, -2, -12, 12, 10, -11, 0, -10, -16, 3, 0, 0, -10 }, - { -5, -16, 10, -6, 27, 13, -3, 4, -2, -13, 15, 5, 2, 5, 3, -4, + { -5, -16, 10, -6, 27, 13, -3, 4, -2, -13, 15, 5, 2, 5, 3, -4, 13, 12, -11, -7, 0, 1, 11, 12, 2, 13, -15, -8, 9, -2, 3, 8 }, - { -5, -8, 4, 3, 9, 3, -11, 10, 14, -25, 14, 8, -2, 5, -12, -21, + { -5, -8, 4, 3, 9, 3, -11, 10, 14, -25, 14, 8, -2, 5, -12, -21, 2, 10, -7, 2, -3, 2, 0, 2, -1, -3, -5, -6, -1, -16, 2, 8 }, - { -1, 5, 1, -11, 5, 9, -7, 8, -13, -12, 4, 12, -4, 1, -1, -1, + { -1, 5, 1, -11, 5, 9, -7, 8, -13, -12, 4, 12, -4, 1, -1, -1, 27, 29, 10, 15, 2, -6, -3, 4, -21, 10, -9, -11, -6, -1, -9, -3 }, - { -6, -3, -1, -6, 11, -5, 0, -2, -5, -31, 11, 3, -1, 5, -3, 4, + { -6, -3, -1, -6, 11, -5, 0, -2, -5, -31, 11, 3, -1, 5, -3, 4, 5, 7, -10, 5, -10, -13, 4, 12, -15, -2, 2, -7, 1, -9, -3, -10 }, - { -3, -7, 17, -8, -5, 36, 8, -7, -8, -20, 12, 8, 1, -1, 3, 0, + { -3, -7, 17, -8, -5, 36, 8, -7, -8, -20, 12, 8, 1, -1, 3, 0, 1, 4, -10, 3, 1, 4, -2, -3, -2, -3, -10, 4, -1, -7, 3, 2 }, - { -13, -3, -5, 9, 22, 6, -23, 3, -10, -7, 17, 17, 18, -14, -8, -8, + { -13, -3, -5, 9, 22, 6, -23, 3, -10, -7, 17, 17, 18, -14, -8, -8, 2, 4, -8, 2, -3, -8, 6, 4, -1, 7, 0, 0, -3, 0, -12, -3 }, - { -3, -10, -15, -3, 9, 3, -23, -9, -13, -18, 12, 13, -2, 0, 1, 8, + { -3, -10, -15, -3, 9, 3, -23, -9, -13, -18, 12, 13, -2, 0, 1, 8, -1, 2, -7, -12, -5, 14, 2, 1, -22, 6, -10, -8, -9, 28, -7, -14 }, - { -3, 1, 2, -1, 13, 7, -2, -7, 1, -3, 6, 9, -3, -2, 4, -2, + { -3, 1, 2, -1, 13, 7, -2, -7, 1, -3, 6, 9, -3, -2, 4, -2, 2, 1, -10, -2, -2, -22, -2, -7, -10, -5, -11, -27, -12, -16, 4, -7 }, - { 2, -6, -3, 1, 8, 0, -2, 12, -3, -4, 58, 15, -10, -4, -2, 2, + { 2, -6, -3, 1, 8, 0, -2, 12, -3, -4, 58, 15, -10, -4, -2, 2, -2, 0, -2, -6, 2, 4, -1, 1, -4, 1, -1, -5, -4, -3, 3, 1 }, - { 10, -1, 0, 5, 21, 7, -14, 6, -3, -16, 15, 17, -16, 13, 3, -6, + { 10, -1, 0, 5, 21, 7, -14, 6, -3, -16, 15, 17, -16, 13, 3, -6, -4, 6, -12, -5, 1, -4, -7, -8, 2, 3, -6, 6, -1, -8, 5, 4 }, - { -6, -2, -8, -11, 15, 10, 0, 8, -6, -15, 33, 8, -2, 18, -15, -11, + { -6, -2, -8, -11, 15, 10, 0, 8, -6, -15, 33, 8, -2, 18, -15, -11, 5, -1, 0, 15, -15, -4, -4, -1, 10, 7, -13, 4, -4, 0, 8, 3 }, - { -7, -2, 0, -2, 0, -2, -4, -5, -14, -16, 12, 38, 7, 12, 6, -4, + { -7, -2, 0, -2, 0, -2, -4, -5, -14, -16, 12, 38, 7, 12, 6, -4, 0, -1, 0, 3, -2, -6, 0, 2, -9, 1, 0, -1, 0, -2, 4, 1 }, - { -8, -4, 18, 1, 14, 5, -12, -3, 20, -17, 5, 19, -11, -8, 11, -3, + { -8, -4, 18, 1, 14, 5, -12, -3, 20, -17, 5, 19, -11, -8, 11, -3, 3, 9, -7, -8, 9, -17, 2, 15, -10, -11, 5, -5, 7, 15, -6, -2 }, - { -7, 2, 38, 5, 19, 16, -5, 4, -13, -20, 0, 4, -4, 6, 4, 2, + { -7, 2, 38, 5, 19, 16, -5, 4, -13, -20, 0, 4, -4, 6, 4, 2, -7, 6, -8, -2, -5, -7, 6, 3, -4, -3, -2, -3, 7, -6, -4, 0 }, - { -11, -12, 8, -15, -3, 14, -7, -22, -11, 2, 22, 14, -19, 2, -19, -6, + { -11, -12, 8, -15, -3, 14, -7, -22, -11, 2, 22, 14, -19, 2, -19, -6, 1, 3, -18, 14, 2, -6, -2, -8, -3, -6, 5, -7, -8, -4, 1, 1 }, - { 8, 7, 25, -21, 12, -6, -5, -4, -10, 6, 0, 10, 1, -12, 18, -5, + { 8, 7, 25, -21, 12, -6, -5, -4, -10, 6, 0, 10, 1, -12, 18, -5, -15, 4, 1, 14, -1, 5, 8, -7, 1, -7, -3, 9, 10, 1, -1, 0 }, - { 9, 10, 32, -15, 8, 2, 11, -7, -18, -8, 2, -6, -9, -16, -3, 3, + { 9, 10, 32, -15, 8, 2, 11, -7, -18, -8, 2, -6, -9, -16, -3, 3, -1, 3, 1, -5, 4, -2, 1, -8, 0, -6, -3, -11, 1, 5, 0, 0 }, - { 14, 0, 23, -25, 22, 3, 7, 10, 0, -2, 7, 8, 0, 10, 0, 0, + { 14, 0, 23, -25, 22, 3, 7, 10, 0, -2, 7, 8, 0, 10, 0, 0, 3, 2, 3, -10, 0, 10, 0, -7, 0, 10, -1, -5, -7, 1, -1, 2 }, - { 12, 0, 25, -18, -5, -4, 13, -10, 3, -6, 7, 21, 0, -16, 3, -10, + { 12, 0, 25, -18, -5, -4, 13, -10, 3, -6, 7, 21, 0, -16, 3, -10, -6, 5, -7, -3, 2, 5, 3, -6, 4, 9, -8, 12, -2, 3, 2, 4 }, - { 31, 15, 27, -20, 10, -7, 15, -10, 9, -8, 4, -5, 3, -3, 5, 6, + { 31, 15, 27, -20, 10, -7, 15, -10, 9, -8, 4, -5, 3, -3, 5, 6, 11, -2, -12, -2, 6, -2, 1, 2, -1, -1, 1, 1, 3, 1, 1, 2 }, - { 12, -4, 13, -23, 12, -6, 2, 4, -3, 13, 6, -7, 5, -19, -7, 18, + { 12, -4, 13, -23, 12, -6, 2, 4, -3, 13, 6, -7, 5, -19, -7, 18, 1, -7, 7, 1, 16, -7, 3, 0, 3, 0, -12, 8, -11, 9, 4, 7 }, - { 29, 1, 3, -22, -5, 6, 0, 12, -14, 11, 1, 6, -3, 4, 6, -2, + { 29, 1, 3, -22, -5, 6, 0, 12, -14, 11, 1, 6, -3, 4, 6, -2, 4, -13, 12, 1, 1, 3, -11, 9, -10, -1, -7, 16, -11, -1, 3, 9 }, - { 4, 4, 36, -23, -5, -8, -15, 1, -6, 3, 13, -1, -5, -7, 4, 9, + { 4, 4, 36, -23, -5, -8, -15, 1, -6, 3, 13, -1, -5, -7, 4, 9, 2, -11, -3, 5, 1, 3, -6, -1, -4, -4, -2, 2, 3, -1, -5, -2 }, - { 19, 10, 6, -17, 2, -4, -2, -4, -3, 13, 2, 2, -13, -7, -3, -11, + { 19, 10, 6, -17, 2, -4, -2, -4, -3, 13, 2, 2, -13, -7, -3, -11, 9, -6, 1, -9, -5, 4, -5, -9, -18, -7, -11, 9, 4, -11, 8, 4 }, - { 16, -3, 9, -16, 18, -2, -12, -16, -11, 11, -18, 16, -13, 6, 2, 8, + { 16, -3, 9, -16, 18, -2, -12, -16, -11, 11, -18, 16, -13, 6, 2, 8, 3, 8, -4, -16, 10, -11, -1, -3, -8, 5, -9, -4, 9, -4, 0, -3 }, - { 14, 15, 3, -23, -5, 7, -8, -6, 2, 17, 2, 12, -8, -12, 13, -1, + { 14, 15, 3, -23, -5, 7, -8, -6, 2, 17, 2, 12, -8, -12, 13, -1, -9, 3, 1, 1, 19, 15, 4, -1, 1, 2, -3, 2, -3, 1, 5, 3 }, - { 32, 5, -10, -47, -5, -1, 4, 11, -7, 0, 2, -2, 1, -7, 6, -4, + { 32, 5, -10, -47, -5, -1, 4, 11, -7, 0, 2, -2, 1, -7, 6, -4, 6, 2, -4, -2, 2, -2, 0, -4, 1, -6, -5, 2, -2, -1, -3, -4 }, - { 20, 8, 10, -21, -7, -9, -16, 12, 1, 4, 6, -5, 9, -11, -7, 4, + { 20, 8, 10, -21, -7, -9, -16, 12, 1, 4, 6, -5, 9, -11, -7, 4, -11, 28, -3, 2, 4, -6, 10, -8, -5, -5, -9, 9, -2, -1, 6, -5 }, - { 38, 3, 23, -25, -6, -18, 3, -10, -8, 6, -10, 1, -10, 2, 2, 0, + { 38, 3, 23, -25, -6, -18, 3, -10, -8, 6, -10, 1, -10, 2, 2, 0, -7, 2, -4, 5, -1, 8, -3, 0, 3, 3, -1, 1, 0, -4, -4, 0 }, - { 20, 5, 16, -22, 24, -18, 2, -12, -14, -7, -3, 10, 2, 7, -10, 2, + { 20, 5, 16, -22, 24, -18, 2, -12, -14, -7, -3, 10, 2, 7, -10, 2, -8, 1, 8, -1, 4, 1, 4, -2, 5, -9, -18, -8, -13, 5, -11, 10 }, - { 14, 8, -12, -16, 9, -11, -3, -6, -25, -7, 6, 5, -7, -16, 10, 2, + { 14, 8, -12, -16, 9, -11, -3, -6, -25, -7, 6, 5, -7, -16, 10, 2, -7, -1, -9, -3, 16, 4, 3, 3, -3, -3, -15, 13, -3, 4, 13, -7 }, - { 16, -9, 19, -23, 7, -19, -3, -5, -15, 11, -21, 21, -16, 18, -1, 6, + { 16, -9, 19, -23, 7, -19, -3, -5, -15, 11, -21, 21, -16, 18, -1, 6, 10, -10, 18, -14, 16, -15, 6, -5, -9, 5, -17, 13, -10, 13, 0, 10 }, - { 8, -4, 4, -24, 8, -21, -18, 9, -11, 4, -6, 17, 5, -9, -2, -2, + { 8, -4, 4, -24, 8, -21, -18, 9, -11, 4, -6, 17, 5, -9, -2, -2, 2, 15, -2, -3, -2, 1, 7, -13, 15, -10, -8, -11, 3, 3, -1, -1 }, - { 14, 17, 6, -32, 5, -17, -2, 0, 15, -1, -5, 16, 1, -5, -2, 9, + { 14, 17, 6, -32, 5, -17, -2, 0, 15, -1, -5, 16, 1, -5, -2, 9, -3, 8, 4, -2, -2, -4, -3, 1, 0, 7, -3, 4, -5, 0, -7, 2 }, - { 24, 6, 22, -12, 8, 3, -14, 4, -7, 8, 6, 5, 6, 1, 6, -12, + { 24, 6, 22, -12, 8, 3, -14, 4, -7, 8, 6, 5, 6, 1, 6, -12, 15, 10, 4, 11, 9, 6, -7, -4, 10, -9, 2, -1, -5, 11, 15, 3 }, - { 17, 12, 3, -23, 5, -1, -2, 1, -9, -1, -3, 1, 8, 1, -5, 17, + { 17, 12, 3, -23, 5, -1, -2, 1, -9, -1, -3, 1, 8, 1, -5, 17, 11, 0, -2, -11, 7, 4, 0, -27, -7, 1, 2, -8, 9, 7, 5, 3 }, - { 12, 10, 12, -10, -4, 5, -1, 2, -24, 5, -8, 2, 6, -17, 19, 5, + { 12, 10, 12, -10, -4, 5, -1, 2, -24, 5, -8, 2, 6, -17, 19, 5, 12, -2, 16, -7, -6, -14, 4, 1, -3, 13, -16, 5, -1, 4, 1, 1 }, - { 31, 9, 11, -17, 10, -3, -7, 7, 1, 2, 2, 4, -3, -1, 11, 4, + { 31, 9, 11, -17, 10, -3, -7, 7, 1, 2, 2, 4, -3, -1, 11, 4, -5, -8, 1, 4, 15, -6, -28, 1, 8, 3, -6, 5, 17, -2, 2, -4 }, - { 11, 19, 16, -26, 0, -7, -7, 2, -13, -15, -12, 9, -3, 27, 8, 4, + { 11, 19, 16, -26, 0, -7, -7, 2, -13, -15, -12, 9, -3, 27, 8, 4, -6, 1, 4, -6, 11, -1, -6, -7, -3, 0, -6, 4, -6, -7, -3, -1 }, - { 10, 18, 16, -32, 19, -9, -4, -3, -7, 8, 8, -3, -11, -2, -6, -16, + { 10, 18, 16, -32, 19, -9, -4, -3, -7, 8, 8, -3, -11, -2, -6, -16, 13, 13, -6, -1, 10, -2, -2, -9, 0, -3, 9, 4, 11, -2, -6, 6 }, - { 9, 4, 19, -33, 4, 7, -12, 36, -3, -1, 8, -2, 2, -8, -9, -4, + { 9, 4, 19, -33, 4, 7, -12, 36, -3, -1, 8, -2, 2, -8, -9, -4, -8, 0, 1, -1, 0, -4, -4, 3, 0, 3, 6, 0, -6, 2, 0, -2 }, - { 25, 7, 15, -12, 2, -24, -1, 24, -4, 4, 9, 0, -2, -9, 4, 6, + { 25, 7, 15, -12, 2, -24, -1, 24, -4, 4, 9, 0, -2, -9, 4, 6, 3, 13, -3, 1, 5, -1, -3, -5, -1, 7, -2, 3, 4, 4, 1, 0 }, - { 19, 6, 8, -20, 9, -9, 5, -4, -13, 7, 11, -3, 5, -13, -9, 6, + { 19, 6, 8, -20, 9, -9, 5, -4, -13, 7, 11, -3, 5, -13, -9, 6, -11, -1, 0, 4, 11, 26, 3, 6, -7, 12, 6, -3, 1, -9, 7, 1 }, - { 15, 6, 19, -23, -3, -9, 3, 16, -6, -4, 6, -5, -10, 1, 16, -14, + { 15, 6, 19, -23, -3, -9, 3, 16, -6, -4, 6, -5, -10, 1, 16, -14, 2, 0, 2, -13, -3, 8, -6, 3, 1, 1, 2, -5, 12, -4, -8, -3 }, - { 14, 4, 16, -20, 1, 12, 0, 6, -3, 9, 4, 16, 10, -16, 5, 7, + { 14, 4, 16, -20, 1, 12, 0, 6, -3, 9, 4, 16, 10, -16, 5, 7, 5, -4, -4, -18, -3, -11, -4, 4, -7, 3, 13, 7, 3, 3, 2, -7 }, - { 22, 3, -1, -30, 18, -3, -9, 9, -2, 11, -16, -2, -14, 12, 0, 4, + { 22, 3, -1, -30, 18, -3, -9, 9, -2, 11, -16, -2, -14, 12, 0, 4, -5, 4, -1, 3, -20, 12, 4, -10, -2, -2, -12, -12, 10, 6, 11, -3 }, - { 15, 7, 2, -21, 5, 4, 9, -9, -33, 7, 7, 3, -6, -14, -8, 10, + { 15, 7, 2, -21, 5, 4, 9, -9, -33, 7, 7, 3, -6, -14, -8, 10, 12, 0, 2, -1, 5, 4, -2, 0, -7, 0, 2, 4, 0, 1, -3, 8 }, - { -7, 0, 12, 3, 0, -6, 8, -4, 0, 2, 14, -15, 2, -7, -31, -3, + { -7, 0, 12, 3, 0, -6, 8, -4, 0, 2, 14, -15, 2, -7, -31, -3, 14, 0, 14, -15, -1, -4, -15, 10, 1, -3, 1, 2, 5, 2, -8, 1 }, - { -2, 5, 1, 0, -3, 3, 3, -6, -1, 2, -4, 1, -19, 0, -11, 18, + { -2, 5, 1, 0, -3, 3, 3, -6, -1, 2, -4, 1, -19, 0, -11, 18, 11, 10, 21, 5, 6, 2, 10, 3, -6, 0, -2, 13, 5, -1, -2, 9 }, - { -9, 1, -5, 0, 0, -15, 8, 4, 8, 3, 8, 12, -13, -2, -39, -2, + { -9, 1, -5, 0, 0, -15, 8, 4, 8, 3, 8, 12, -13, -2, -39, -2, 4, -4, 5, -3, -4, 3, -3, 3, 10, 5, 3, 2, -3, 5, -2, 8 }, - { -9, 6, 6, -8, 12, -12, 23, -18, 4, -15, -5, 2, -20, 13, -7, 7, + { -9, 6, 6, -8, 12, -12, 23, -18, 4, -15, -5, 2, -20, 13, -7, 7, 7, -12, 14, -12, 6, 1, 1, -3, -8, 9, 0, 1, -7, 3, 7, -6 }, - { -18, 13, 4, 3, -10, -30, -10, -6, -14, 1, -7, -4, -35, 5, -25, 11, + { -18, 13, 4, 3, -10, -30, -10, -6, -14, 1, -7, -4, -35, 5, -25, 11, 9, 8, 19, -4, -7, -3, -18, -8, 1, 5, 10, -4, -14, -9, 3, -4 }, - { -6, -1, 4, -9, -9, 4, 20, 0, 0, 3, 11, 7, -16, -17, -20, 11, + { -6, -1, 4, -9, -9, 4, 20, 0, 0, 3, 11, 7, -16, -17, -20, 11, -6, -14, 1, 4, 19, 2, -8, 6, -15, 3, 6, -5, -14, 3, 7, 2 }, - { 1, 6, -2, -8, -5, -3, 3, -8, 21, 1, 3, 16, -14, -2, -9, -4, + { 1, 6, -2, -8, -5, -3, 3, -8, 21, 1, 3, 16, -14, -2, -9, -4, 13, -2, 18, 14, 14, 19, -13, 5, -10, 2, -3, 3, 5, 5, 1, -1 }, - { -1, -5, -6, -2, -11, -7, 5, -4, 5, -1, 0, 3, -3, 2, -19, 18, + { -1, -5, -6, -2, -11, -7, 5, -4, 5, -1, 0, 3, -3, 2, -19, 18, 16, 4, 14, -22, -2, -11, -22, 1, -1, 11, 1, 2, 11, -10, 7, -12 }, - { 1, 4, 5, -1, -9, -5, 1, 12, 5, 6, 12, 9, -24, 23, 1, 20, + { 1, 4, 5, -1, -9, -5, 1, 12, 5, 6, 12, 9, -24, 23, 1, 20, 14, -11, 13, 5, -2, -2, 5, 6, 2, 1, -9, 6, 10, 5, -4, 11 }, - { -1, -1, 1, 7, -3, -4, 8, -16, 15, -1, -7, 9, -22, -11, -11, 10, + { -1, -1, 1, 7, -3, -4, 8, -16, 15, -1, -7, 9, -22, -11, -11, 10, 16, 9, -2, 4, 13, 10, 6, 16, 4, 7, 1, -8, -7, -14, -7, 4 }, - { 1, 3, -6, 0, 15, -9, -4, 0, 4, 6, 12, 9, -6, -5, -22, 17, + { 1, 3, -6, 0, 15, -9, -4, 0, 4, 6, 12, 9, -6, -5, -22, 17, 7, -11, 15, -5, 1, 3, -19, 0, -15, -3, 16, 5, 5, -7, -11, 12 }, - { -2, -1, 13, 2, 4, -24, 37, -5, -2, -6, 12, 7, -2, -23, -4, 9, + { -2, -1, 13, 2, 4, -24, 37, -5, -2, -6, 12, 7, -2, -23, -4, 9, 2, -3, 3, 2, 3, 3, -14, 11, 0, -4, -2, -2, 3, 10, -10, 4 }, - { 2, 9, 8, -6, -28, 14, 28, -11, 18, -11, 0, 2, -2, 4, -12, 3, + { 2, 9, 8, -6, -28, 14, 28, -11, 18, -11, 0, 2, -2, 4, -12, 3, 6, 0, 7, -7, -6, 2, 5, -1, -1, -1, 5, 2, 3, 0, -3, 9 }, - { -7, 14, 5, -10, -3, 7, 4, -5, 7, -8, -7, 4, -12, 14, -16, 25, + { -7, 14, 5, -10, -3, 7, 4, -5, 7, -8, -7, 4, -12, 14, -16, 25, 3, 0, 1, -5, 12, -10, 0, -10, 0, 12, 12, 17, 12, 10, -1, 0 }, - { -4, -2, 5, -2, -17, -3, 5, -5, 7, -17, 1, 5, -4, 4, -20, 0, + { -4, -2, 5, -2, -17, -3, 5, -5, 7, -17, 1, 5, -4, 4, -20, 0, 11, -15, 13, -8, 10, 1, 1, 5, -12, 9, -8, 0, 6, -1, -11, 4 }, - { -3, 12, 13, -15, -7, -7, 0, 5, 33, 3, 3, -6, -13, -7, -15, 10, + { -3, 12, 13, -15, -7, -7, 0, 5, 33, 3, 3, -6, -13, -7, -15, 10, 3, 3, 3, -5, 2, 7, -1, 0, -12, 2, 11, -6, -9, 0, 5, 11 }, - { -8, 5, 10, -7, -14, -4, 13, 0, 18, -3, -6, 7, 1, -6, 0, 21, + { -8, 5, 10, -7, -14, -4, 13, 0, 18, -3, -6, 7, 1, -6, 0, 21, 8, -7, 10, -8, -3, 17, -9, 0, -5, 1, 4, 8, -3, 11, -5, 0 }, - { -8, 8, -3, -8, 8, -11, 16, -16, 17, 0, 8, 16, -17, 10, -16, 10, + { -8, 8, -3, -8, 8, -11, 16, -16, 17, 0, 8, 16, -17, 10, -16, 10, -8, 6, 11, 0, 10, 7, 4, 5, 7, -5, -5, -6, -7, -5, -1, 16 }, - { -6, 0, 6, 1, -8, -8, 8, -7, -5, -10, -11, 8, -19, 6, -7, 13, + { -6, 0, 6, 1, -8, -8, 8, -7, -5, -10, -11, 8, -19, 6, -7, 13, 5, -3, 4, -8, 7, -1, -18, 9, 0, -5, 6, 26, 3, 8, 2, 4 }, - { -2, -2, 23, -2, -20, 2, 7, -7, -6, -15, 3, 9, -19, -2, -10, 7, + { -2, -2, 23, -2, -20, 2, 7, -7, -6, -15, 3, 9, -19, -2, -10, 7, -2, 7, 9, 11, 0, 4, -4, 6, 9, -2, 4, -3, 4, 3, 2, 8 }, - { -6, 12, 10, -10, -7, 4, 17, 11, -6, 1, 12, 11, -18, 8, -12, 4, + { -6, 12, 10, -10, -7, 4, 17, 11, -6, 1, 12, 11, -18, 8, -12, 4, 1, 13, 6, -13, 23, 9, -5, 8, -2, -5, 1, 3, 0, -2, -4, 4 }, - { 7, 1, 7, -17, -8, 8, -1, -7, 5, -6, 4, -3, -16, 9, -24, 18, + { 7, 1, 7, -17, -8, 8, -1, -7, 5, -6, 4, -3, -16, 9, -24, 18, -3, 10, 13, -11, -6, -11, -4, 10, 0, 11, 8, 2, 6, -5, -11, 4 }, - { -4, 1, -5, -10, 0, -3, 9, -2, 4, -1, 1, 5, -41, -10, -7, 4, + { -4, 1, -5, -10, 0, -3, 9, -2, 4, -1, 1, 5, -41, -10, -7, 4, -3, 3, 1, 0, -12, 4, -3, 0, 2, -1, -2, -5, 3, 2, -7, 5 }, - { -2, 1, 4, 4, -3, -6, 1, 0, 12, -5, 11, 0, -17, -3, -1, 11, + { -2, 1, 4, 4, -3, -6, 1, 0, 12, -5, 11, 0, -17, -3, -1, 11, 4, 1, 27, -12, 0, -14, 2, -15, -3, -9, 0, -7, -3, 15, -8, 6 }, - { -6, 4, 9, 2, 4, 3, 7, -10, 28, 1, -2, 48, 7, 0, -10, 10, + { -6, 4, 9, 2, 4, 3, 7, -10, 28, 1, -2, 48, 7, 0, -10, 10, 1, -9, 2, -1, 0, 3, -5, 5, -4, -2, 7, 7, 1, 3, 2, 5 }, - { -3, 3, -1, 3, -9, 0, -1, 3, 2, -6, 39, -14, -12, 5, -19, 21, + { -3, 3, -1, 3, -9, 0, -1, 3, 2, -6, 39, -14, -12, 5, -19, 21, 7, -6, 4, -1, -4, 0, -4, 1, 0, -9, 1, 10, 0, -2, 0, 7 }, - { 4, 2, -29, 12, 5, -3, 16, -6, 15, -13, -4, -1, -13, 22, -16, 17, + { 4, 2, -29, 12, 5, -3, 16, -6, 15, -13, -4, -1, -13, 22, -16, 17, 16, 4, 9, -4, 4, -6, -4, 11, -8, 7, 8, 4, 3, -3, -7, -13 }, - { 0, 3, 3, -6, -4, 0, 9, 0, 5, 0, 10, 10, 4, -13, -12, 16, + { 0, 3, 3, -6, -4, 0, 9, 0, 5, 0, 10, 10, 4, -13, -12, 16, 23, -4, -12, -6, -4, 20, 2, 0, -4, 23, 1, 8, 11, -4, -5, 15 }, - { -6, 4, -15, -9, -1, -19, 12, -30, -17, -4, 1, -13, -13, 4, -3, 26, + { -6, 4, -15, -9, -1, -19, 12, -30, -17, -4, 1, -13, -13, 4, -3, 26, 5, -25, 11, -14, -6, -13, 0, -7, 9, 2, 8, -1, -8, 1, -8, 13 }, - { 1, 6, 1, -4, -4, 1, 2, 0, -3, 2, 10, 6, -6, -2, -11, 4, + { 1, 6, 1, -4, -4, 1, 2, 0, -3, 2, 10, 6, -6, -2, -11, 4, 32, 15, 15, -47, -8, 3, -12, 4, -5, 4, -1, 0, -5, 5, 1, -7 }, - { 2, -1, 0, 0, -1, -6, 0, -6, 4, -4, 5, 9, -5, 1, -3, 51, + { 2, -1, 0, 0, -1, -6, 0, -6, 4, -4, 5, 9, -5, 1, -3, 51, 4, -5, 4, -14, -1, -4, -3, 1, -4, -1, 0, 2, -8, 0, 1, 2 }, - { 0, 4, -2, -7, -2, -9, 6, -8, 11, -3, -6, 3, -11, -8, -12, 8, + { 0, 4, -2, -7, -2, -9, 6, -8, 11, -3, -6, 3, -11, -8, -12, 8, 11, 5, 19, 3, -24, 19, -14, 11, -5, -18, -8, -12, -5, -4, -1, 4 }, - { 16, 9, 10, 14, -18, -2, -18, -27, 10, -5, 12, 14, 4, 0, -2, -6, + { 16, 9, 10, 14, -18, -2, -18, -27, 10, -5, 12, 14, 4, 0, -2, -6, -12, -7, -1, 3, 4, 7, 11, 10, 5, -5, -7, -16, -3, -6, 6, 9 }, - { 7, 15, -9, 10, -19, 4, -5, -37, -2, -4, 8, 2, 4, -1, 1, 9, + { 7, 15, -9, 10, -19, 4, -5, -37, -2, -4, 8, 2, 4, -1, 1, 9, -5, -5, -12, 1, -1, -8, 3, -3, 4, 6, 9, 3, 3, -1, 2, 4 }, - { 13, 17, 3, 9, -7, -7, -15, -17, -8, -13, -4, -8, 19, 2, 16, 25, + { 13, 17, 3, 9, -7, -7, -15, -17, -8, -13, -4, -8, 19, 2, 16, 25, 7, 15, 2, 16, -5, -6, -10, -9, -7, -6, -2, -7, 7, 2, 4, 5 }, - { 24, 7, 9, 8, -13, -2, 0, -4, 1, -13, 3, 6, 7, 10, -4, 15, + { 24, 7, 9, 8, -13, -2, 0, -4, 1, -13, 3, 6, 7, 10, -4, 15, 5, 7, -4, 5, -5, 3, 13, -7, 5, 15, -11, -2, 7, 5, 8, 6 }, - { 17, 6, -15, 23, -2, -1, -6, -2, 0, -4, 11, -3, 12, 15, 6, -8, + { 17, 6, -15, 23, -2, -1, -6, -2, 0, -4, 11, -3, 12, 15, 6, -8, -15, 10, -9, 7, -1, -11, 2, -8, -4, 3, 4, -10, 4, 4, 11, 1 }, - { 21, 12, -3, 6, -8, 8, -11, -8, -5, -5, 3, 7, -1, -5, 12, 15, + { 21, 12, -3, 6, -8, 8, -11, -8, -5, -5, 3, 7, -1, -5, 12, 15, -10, -11, 3, 15, 8, 4, 2, -15, 0, 14, 1, -8, -1, 3, 10, -7 }, - { 16, 12, 5, 13, -6, 15, -23, 0, -17, -9, 0, 4, -9, 13, 6, 18, + { 16, 12, 5, 13, -6, 15, -23, 0, -17, -9, 0, 4, -9, 13, 6, 18, 0, 0, -4, -1, 0, 14, 5, -1, 8, -4, -8, -6, 5, -2, -2, 0 }, - { 14, 16, -1, 12, -15, -9, -6, -20, 4, 6, 8, 9, 3, 1, -9, -4, + { 14, 16, -1, 12, -15, -9, -6, -20, 4, 6, 8, 9, 3, 1, -9, -4, -1, -11, 9, 11, -12, 1, -14, -7, 2, -8, 11, 9, -4, 10, 4, -16 }, - { 13, 10, 3, 7, 0, -8, -33, -6, 4, -4, 19, -2, 14, 6, 5, 7, + { 13, 10, 3, 7, 0, -8, -33, -6, 4, -4, 19, -2, 14, 6, 5, 7, 6, -3, -1, -10, -10, -9, 4, -3, 5, 9, 2, 2, 10, 9, -2, -3 }, - { 11, 10, 25, 18, -1, -6, -21, -21, -11, -16, 6, 5, 14, 4, 8, 7, + { 11, 10, 25, 18, -1, -6, -21, -21, -11, -16, 6, 5, 14, 4, 8, 7, 0, -10, -7, -9, -5, -4, 3, -1, 1, 6, -1, 6, -2, 2, -3, -9 }, - { 15, 9, 5, 22, -17, 15, -9, 7, 7, -9, 13, 9, 10, -1, 8, -3, + { 15, 9, 5, 22, -17, 15, -9, 7, 7, -9, 13, 9, 10, -1, 8, -3, -2, 6, 1, 17, 8, -14, 7, -3, 12, 9, 1, 0, 1, -5, 17, -18 }, - { 25, 19, -17, 12, -4, -10, 1, -13, -19, -7, -3, 9, 6, -2, 3, 1, + { 25, 19, -17, 12, -4, -10, 1, -13, -19, -7, -3, 9, 6, -2, 3, 1, 4, -2, -11, -14, -1, -7, -5, -9, 7, -1, -3, 4, -5, 1, 0, -1 }, - { 20, 8, -3, -10, -24, 3, -6, -2, 0, -12, 14, 6, 7, 11, 4, 7, + { 20, 8, -3, -10, -24, 3, -6, -2, 0, -12, 14, 6, 7, 11, 4, 7, -12, -5, -8, -10, 5, -1, -4, 4, 16, 7, -14, 6, -1, -2, -7, -11 }, - { 16, 18, 17, 1, -15, -6, -5, -3, -1, -19, 8, -2, 2, 8, 12, -19, + { 16, 18, 17, 1, -15, -6, -5, -3, -1, -19, 8, -2, 2, 8, 12, -19, -12, 8, 0, -3, -1, -1, 4, -14, 9, -1, -12, -1, -7, 10, -3, 5 }, - { 18, 12, -7, 7, 0, -3, -13, 0, -1, -4, 9, -2, 6, -1, 0, 1, + { 18, 12, -7, 7, 0, -3, -13, 0, -1, -4, 9, -2, 6, -1, 0, 1, 15, -21, 1, -8, 25, -19, 13, -9, 2, 12, 5, -7, -3, -1, -3, 1 }, - { 13, 16, -4, 9, -2, 2, -1, -19, -7, -4, 18, -6, 14, 18, -5, 4, + { 13, 16, -4, 9, -2, 2, -1, -19, -7, -4, 18, -6, 14, 18, -5, 4, -6, -3, -19, -14, -1, -12, 10, 6, 7, 17, -12, -13, -10, -4, 5, 4 }, - { 27, 17, 4, 14, -9, -2, -4, -8, 0, -6, 14, -11, -7, 2, -3, -3, + { 27, 17, 4, 14, -9, -2, -4, -8, 0, -6, 14, -11, -7, 2, -3, -3, -2, -3, -13, 12, 16, 1, -5, -9, -10, -11, -2, 3, -7, 5, 11, -7 }, - { 7, 17, -16, -2, -14, -28, -7, -8, 15, -10, 7, 15, 8, 17, 13, -1, + { 7, 17, -16, -2, -14, -28, -7, -8, 15, -10, 7, 15, 8, 17, 13, -1, 4, -7, -12, -11, 0, 0, 2, 3, -3, 7, -6, 6, 1, -16, 1, -2 }, - { 23, 11, -9, 15, -23, -4, -6, -4, 2, -9, -7, 9, -8, 3, -13, -4, + { 23, 11, -9, 15, -23, -4, -6, -4, 2, -9, -7, 9, -8, 3, -13, -4, 8, 18, -6, -2, 1, -5, 6, -14, -5, -2, -6, -5, -3, -2, 4, -5 }, - { 12, 13, 18, 18, -35, 2, 7, -17, 3, -11, 6, 9, -3, -2, 10, -4, + { 12, 13, 18, 18, -35, 2, 7, -17, 3, -11, 6, 9, -3, -2, 10, -4, 3, 3, -2, -7, 0, 2, -4, 0, -4, 0, -6, 5, 10, 4, -3, -1 }, - { 19, 11, 1, 20, -14, 4, -9, -13, -2, 11, 0, 17, -1, -1, -1, -1, + { 19, 11, 1, 20, -14, 4, -9, -13, -2, 11, 0, 17, -1, -1, -1, -1, -5, -8, 0, 5, -1, -8, 5, -1, 3, 2, -12, 21, -2, -24, 5, 7 }, - { 15, 15, -15, 17, -14, -22, 3, -4, -11, -3, -7, 1, 18, 10, 1, 10, + { 15, 15, -15, 17, -14, -22, 3, -4, -11, -3, -7, 1, 18, 10, 1, 10, -6, -3, 8, 2, -7, 0, -2, 1, 1, 2, -9, -2, 1, 2, -3, 4 }, - { 45, 13, 8, 17, -5, 2, -16, 2, 8, -2, 8, -15, 4, 5, -1, 7, + { 45, 13, 8, 17, -5, 2, -16, 2, 8, -2, 8, -15, 4, 5, -1, 7, -6, -2, -6, 2, -3, 0, 0, -9, -1, 7, 2, 3, -3, -3, -1, 5 }, - { 1, 18, -8, 18, -12, -10, 3, 4, -22, -12, 20, 8, -3, 9, 2, 10, + { 1, 18, -8, 18, -12, -10, 3, 4, -22, -12, 20, 8, -3, 9, 2, 10, -10, -3, 9, 3, 6, -3, 10, -1, -3, 2, -2, 4, 2, 3, -3, -18 }, - { 9, 10, -5, 9, -35, -21, -18, -16, -1, -12, -6, -7, -15, -19, 12, 4, + { 9, 10, -5, 9, -35, -21, -18, -16, -1, -12, -6, -7, -15, -19, 12, 4, 4, 9, -7, 2, 14, 1, 4, 0, -1, 6, -7, 2, 1, 1, -4, 4 }, - { 31, 8, -17, 35, -8, 1, -5, -6, -7, -6, 10, -2, -3, 6, 9, 3, + { 31, 8, -17, 35, -8, 1, -5, -6, -7, -6, 10, -2, -3, 6, 9, 3, -6, -2, 3, 3, 5, -3, 0, 6, 0, 1, -5, -3, -2, -4, -1, 0 }, - { 18, 4, -8, 7, -8, -15, -1, -16, 12, 18, 3, 19, 2, 4, 8, 8, + { 18, 4, -8, 7, -8, -15, -1, -16, 12, 18, 3, 19, 2, 4, 8, 8, 0, -5, -8, -12, 10, -5, 0, 1, 0, 4, -3, 16, 11, 11, -2, -6 }, - { 27, 15, -17, -10, -23, -22, -1, -14, -4, -7, 20, -2, -7, 6, 15, -5, + { 27, 15, -17, -10, -23, -22, -1, -14, -4, -7, 20, -2, -7, 6, 15, -5, 32, 4, 9, -11, -3, -8, 11, -4, -1, -4, -8, -6, -4, -5, -2, -7 }, - { 22, 4, -7, 2, -15, -11, -17, -10, 2, 0, 15, 11, 7, 12, -8, 6, + { 22, 4, -7, 2, -15, -11, -17, -10, 2, 0, 15, 11, 7, 12, -8, 6, -10, -18, -6, -12, 7, 3, 22, 3, -7, 14, -5, -2, -13, -7, -1, -7 }, - { 18, 13, 9, 24, -4, -19, -9, -11, 13, 8, 2, 4, -1, 8, 14, 10, + { 18, 13, 9, 24, -4, -19, -9, -11, 13, 8, 2, 4, -1, 8, 14, 10, -12, 0, 0, 5, 10, 5, 4, -1, 5, 1, -1, 11, 2, -4, 0, -9 }, - { 15, 19, -5, 1, -4, -10, -8, -27, 6, 8, 5, 10, 4, 11, 5, -5, + { 15, 19, -5, 1, -4, -10, -8, -27, 6, 8, 5, 10, 4, 11, 5, -5, -11, 0, -11, -14, -4, -9, -8, -8, 6, -9, 4, -5, -1, 1, 5, -4 }, - { 18, 1, -13, 14, -14, 9, -15, -7, 12, 1, 13, -4, -20, 12, 10, 12, + { 18, 1, -13, 14, -14, 9, -15, -7, 12, 1, 13, -4, -20, 12, 10, 12, -12, 7, 1, -13, 10, -6, 5, -3, 4, 8, 10, -13, -3, -6, 9, -3 }, - { 19, -14, 5, -8, -6, 2, -5, 5, -3, -1, -28, 11, 18, -6, -4, -2, + { 19, -14, 5, -8, -6, 2, -5, 5, -3, -1, -28, 11, 18, -6, -4, -2, 11, 14, -43, -42, 9, 2, 20, -23, 6, 32, 0, 5, 0, 6, 9, 5 }, - { 8, 11, -14, -1, 7, 12, -7, 2, -16, 2, 10, -3, -1, -7, -7, -1, + { 8, 11, -14, -1, 7, 12, -7, 2, -16, 2, 10, -3, -1, -7, -7, -1, 1, -10, -60, -23, -18, 42, -13, 9, 18, -11, 0, 1, 0, 2, -5, 1 }, - { -5, -1, 2, 0, 3, -3, 3, -2, -6, 0, -3, -3, 7, 2, 0, -2, + { -5, -1, 2, 0, 3, -3, 3, -2, -6, 0, -3, -3, 7, 2, 0, -2, -2, 3, -34, -15, 37, 47, 10, 20, 9, 1, 3, -21, -25, -33, -14, 8 }, - { 5, 6, 2, -2, -2, -2, 6, 5, -5, 7, -3, 1, -5, -13, 9, 3, + { 5, 6, 2, -2, -2, -2, 6, 5, -5, 7, -3, 1, -5, -13, 9, 3, -17, -19, -2, -79, -12, -7, -8, -6, -2, -2, -1, -1, -7, -13, 6, -1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 3, 4, -87, 6, -11, 16, -9, -1, 8, 0, 5, 0, 1, 2, 1 }, - { -5, 6, 2, -24, 5, -9, -7, 0, 7, 3, -3, 16, -14, -16, 0, 18, + { -5, 6, 2, -24, 5, -9, -7, 0, 7, 3, -3, 16, -14, -16, 0, 18, 15, -9, -14, -28, -17, 53, 14, -6, -28, -1, -3, -10, -7, -14, 19, -15 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -3, 0, -13, 0, -53, 3, -22, 63, 19, 16, 1, -11, 0, -3, 0, -3, 0, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -6, -43, -43, -2, 65, -13, -4, 9, 1, 1, 2, 1, 0, 0, 1 }, - { 0, 1, 0, 0, -1, 0, 1, 1, 0, 0, 1, 2, -1, -1, -3, -1, + { 0, 1, 0, 0, -1, 0, 1, 1, 0, 0, 1, 2, -1, -1, -3, -1, -23, 1, -61, -55, 3, -28, -6, -4, -4, 8, 2, 1, 1, -1, 0, 0 }, - { 0, 1, -1, 1, -1, 0, -1, 0, 1, -1, 0, 1, -1, 0, -9, -4, + { 0, 1, -1, 1, -1, 0, -1, 0, 1, -1, 0, 1, -1, 0, -9, -4, -48, -19, -52, -46, 11, -12, 5, -14, 0, -10, 0, 0, -1, -2, -1, 0 }, - { 0, -3, -1, -4, 2, -1, -7, 3, 1, 3, -1, 1, -3, 0, -7, 0, + { 0, -3, -1, -4, 2, -1, -7, 3, 1, 3, -1, 1, -3, 0, -7, 0, 3, -7, -61, -51, -4, -21, -16, -21, -11, 14, -7, 8, 3, -5, 1, 2 }, - { 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 9, -3, + { 0, 0, 0, 1, 0, 0, -1, 0, 0, 0, 0, 0, 1, -1, 9, -3, 56, -11, -6, -67, -1, 13, 0, 7, 1, -9, -1, -1, 0, 0, 1, 0 }, - { 14, 9, -2, 14, -10, -10, 9, -5, 1, -8, -23, 30, 8, -7, 23, 8, + { 14, 9, -2, 14, -10, -10, 9, -5, 1, -8, -23, 30, 8, -7, 23, 8, 2, 10, -1, -27, -17, 57, 22, 4, -5, 2, -12, -6, 2, -7, -4, -9 }, - { 1, 5, 12, -2, -2, -3, 2, -3, 6, 0, 4, -2, -8, -6, 0, 16, + { 1, 5, 12, -2, -2, -3, 2, -3, 6, 0, 4, -2, -8, -6, 0, 16, -15, 29, -55, -29, -24, 29, 3, 10, 6, 13, 10, -5, 21, 11, -14, 5 }, - { 4, 2, 26, -6, 10, 11, -23, -10, -27, -20, 3, -24, -11, -10, -13, 25, + { 4, 2, 26, -6, 10, 11, -23, -10, -27, -20, 3, -24, -11, -10, -13, 25, -10, 5, -9, -36, -7, 43, 3, -13, 6, 13, -2, 0, 1, 3, -3, -4 }, - { -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, -1, 0, 0, 0, -1, 1, + { -1, 0, -1, 0, 0, 0, 0, -1, 1, 0, -1, 0, 0, 0, -1, 1, -12, 12, -26, -64, -15, 29, 37, -7, -3, -12, -5, 14, 8, -8, -10, -2 }, - { 19, -4, -11, -16, 8, 14, 5, 19, 3, 22, -11, -21, -1, -6, -11, 11, + { 19, -4, -11, -16, 8, 14, 5, 19, 3, 22, -11, -21, -1, -6, -11, 11, 10, -24, -23, -40, -8, 20, 17, 5, 13, -6, 3, 14, -20, -8, 3, 28 }, - { 2, -12, 10, -14, -18, 26, -22, 4, -2, 5, -21, 8, 3, 1, 19, 0, + { 2, -12, 10, -14, -18, 26, -22, 4, -2, 5, -21, 8, 3, 1, 19, 0, -12, 24, -14, -40, 15, 29, -15, 6, 15, 1, -19, 2, 4, 7, -12, -3 }, - { 0, 17, 13, 7, -5, -11, 2, -19, 3, 38, -21, -3, -6, -4, 7, 1, + { 0, 17, 13, 7, -5, -11, 2, -19, 3, 38, -21, -3, -6, -4, 7, 1, 1, -5, -40, -10, -2, 35, 8, 8, -10, -8, -9, 33, 4, 4, 0, -2 }, - { -2, -12, 7, 29, -24, 2, 16, -1, -7, 16, 10, -2, -2, -2, 13, -2, + { -2, -12, 7, 29, -24, 2, 16, -1, -7, 16, 10, -2, -2, -2, 13, -2, -37, 15, -22, -40, -11, 33, 10, -1, 8, 10, 6, 8, 9, 0, -12, 2 }, - { 15, -8, -9, -2, 7, -17, 7, 19, 14, 4, 12, 27, 11, 10, 4, 11, + { 15, -8, -9, -2, 7, -17, 7, 19, 14, 4, 12, 27, 11, 10, 4, 11, -15, 14, -13, -48, 5, 18, 0, -9, -36, -11, 2, 4, 5, 5, -15, -12 }, - { -12, 0, 3, 4, 7, -5, 5, -14, -24, -18, -6, -15, -8, -20, 1, -7, + { -12, 0, 3, 4, 7, -5, 5, -14, -24, -18, -6, -15, -8, -20, 1, -7, -33, -28, -40, -38, -18, -10, -5, 17, -12, 4, 3, -5, 5, -13, 4, -7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -3, -9, -49, -60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -3, -9, -49, -60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 3, -2, 9, -29, -11, 55, 8, 32, -36, -13, -7, 37, 4, 11, 0, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, -1, -39, -4, -30, 63, 28, -17, -6, 10, 7, -14, -9, 11, 9, 7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 13, -2, -50, -32, 22, 51, 4, 7, 6, 11, -20, -13, 9, -5, 21, -4 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -3, -9, -49, -60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -3, -9, -49, -60, -5, 45, -1, 6, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, + { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0, 3, -2, 9, -29, -11, 55, 8, 32, -36, -13, -7, 37, 4, 11, 0, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, -1, -39, -4, -30, 63, 28, -17, -6, 10, 7, -14, -9, 11, 9, 7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 13, -2, -50, -32, 22, 51, 4, 7, 6, 11, -20, -13, 9, -5, 21, -4 }, - { -8, 2, 1, 22, -31, -6, -25, -3, -3, 1, -15, -11, -2, -3, 4, -13, + { -8, 2, 1, 22, -31, -6, -25, -3, -3, 1, -15, -11, -2, -3, 4, -13, -9, 15, -18, 37, -7, -37, 12, -13, -11, -25, -10, -11, -22, 7, 16, 7 }, - { 14, 10, 4, -10, -1, -5, -7, -3, 16, 13, -5, -15, 5, 11, -1, 8, + { 14, 10, 4, -10, -1, -5, -7, -3, 16, 13, -5, -15, 5, 11, -1, 8, -27, 7, -12, 49, 17, -22, 9, -2, -9, -1, 2, -15, -1, 41, -18, -17 }, - { -4, -9, -15, -3, 3, 4, 4, 2, 7, -3, -7, -8, -5, 17, -19, -7, + { -4, -9, -15, -3, 3, 4, 4, 2, 7, -3, -7, -8, -5, 17, -19, -7, 36, -9, -38, 17, 1, -48, 11, -18, -13, -2, -8, 4, -10, -5, 21, 11 }, - { 15, -13, 4, 2, 1, -5, -2, 1, -10, 7, -1, 3, -6, 0, 11, -11, + { 15, -13, 4, 2, 1, -5, -2, 1, -10, 7, -1, 3, -6, 0, 11, -11, 8, 20, -17, 51, -17, -41, 2, 15, 4, 8, -2, 16, -32, -1, 17, 6 }, - { -8, 8, -18, -5, 4, 6, -3, 8, 0, -4, 2, 0, -1, -4, 5, 8, + { -8, 8, -18, -5, 4, 6, -3, 8, 0, -4, 2, 0, -1, -4, 5, 8, 30, 30, -8, 70, 2, 8, 2, 0, 7, 1, 13, -1, -6, -7, -11, 2 }, - { -8, -7, 9, -10, -13, 6, -11, -14, 13, 25, -26, 5, 2, -5, -5, 5, + { -8, -7, 9, -10, -13, 6, -11, -14, 13, 25, -26, 5, 2, -5, -5, 5, -8, 4, 0, 33, 12, -38, -4, 6, 13, 6, 25, 34, -1, 25, -19, -5 }, - { 18, 3, -17, 4, -8, 7, 20, 1, -1, 5, -5, -2, -8, 8, -35, 15, + { 18, 3, -17, 4, -8, 7, 20, 1, -1, 5, -5, -2, -8, 8, -35, 15, 24, 43, -5, 51, 5, -12, -3, 1, -2, 3, -3, -3, -9, 8, -9, 2 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 10, 24, 76, -2, -22, 11, -1, 4, 33, 4, 1, -1, 1, 2, 0 }, - { 0, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 2, 0, + { 0, -1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 2, 0, 24, 13, 32, 70, 26, 5, -21, -9, -6, -15, 2, -2, 2, 4, 1, 1 }, - { 5, -4, -11, 4, -4, 22, 10, -2, 13, -11, -4, -21, -17, 0, -7, 4, + { 5, -4, -11, 4, -4, 22, 10, -2, 13, -11, -4, -21, -17, 0, -7, 4, 10, -34, 11, 52, 2, -46, -5, 0, 0, -1, 2, 4, -9, 1, 1, -7 }, - { 0, 1, 1, 0, -1, 0, 1, 0, 1, 1, 0, 1, 0, 0, -3, 1, + { 0, 1, 1, 0, -1, 0, 1, 0, 1, 1, 0, 1, 0, 0, -3, 1, -8, 9, -1, 64, -13, -61, -3, 3, -5, 10, 1, 3, -1, -1, -1, -1 }, - { 0, 1, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, + { 0, 1, 0, -1, 0, -1, 0, 0, 1, 0, 0, 0, 1, 1, 2, 1, 10, -2, -31, 79, -10, 27, 0, -1, 3, 8, 1, 1, 0, -1, 0, -1 }, - { 3, 12, 10, 26, -19, 10, -9, 6, -4, -15, 10, 3, -16, 6, 11, -19, + { 3, 12, 10, 26, -19, 10, -9, 6, -4, -15, 10, 3, -16, 6, 11, -19, 3, 10, 18, 44, 5, -30, 5, -9, 21, 4, 20, 10, 14, -25, 8, -17 }, - { 0, 0, 0, 1, -1, 0, -1, 0, 1, 0, 1, 1, 0, 0, -6, -2, + { 0, 0, 0, 1, -1, 0, -1, 0, 1, 0, 1, 1, 0, 0, -6, -2, 8, -8, 13, 69, 26, -19, -25, -17, 16, 6, -12, 22, 2, -6, 9, 5 }, - { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, + { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, -34, -15, -33, 56, 9, -42, 9, 10, 6, 9, -8, -11, 0, -6, 15, 5 }, - { 10, 2, -14, -3, -15, -35, -1, 7, -18, 14, 8, -1, -15, -26, 6, -15, + { 10, 2, -14, -3, -15, -35, -1, 7, -18, 14, 8, -1, -15, -26, 6, -15, -18, 22, 9, 33, 0, -32, -9, 3, -11, 7, 4, -1, 5, 30, 9, 1 }, - { 4, 15, 0, 6, -5, -11, 9, 6, 6, 6, 14, 2, -1, 10, -24, -25, + { 4, 15, 0, 6, -5, -11, 9, 6, 6, 6, 14, 2, -1, 10, -24, -25, -2, -4, -1, 37, 2, -29, 14, -9, 22, 17, -2, 33, 10, -25, 11, -11 }, - { 0, 5, 2, 18, -12, 21, 22, 33, -7, 21, -9, -7, 7, -15, -7, 16, + { 0, 5, 2, 18, -12, 21, 22, 33, -7, 21, -9, -7, 7, -15, -7, 16, 7, 0, -14, 44, 10, -25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, - { 3, 13, 12, 12, 8, 25, -23, 8, -22, -3, -18, -8, 15, 12, 9, 19, + { 3, 13, 12, 12, 8, 25, -23, 8, -22, -3, -18, -8, 15, 12, 9, 19, 0, 0, -9, 49, -27, -15, -9, -15, 12, -8, -16, -7, 13, 5, 13, 2 }, - { 12, -6, 7, -2, 20, -9, -14, 12, 13, -5, -17, 22, -8, -4, 2, 7, + { 12, -6, 7, -2, 20, -9, -14, 12, 13, -5, -17, 22, -8, -4, 2, 7, -13, -2, -15, 43, -5, -30, 27, 4, 10, -27, 5, 27, -10, -10, -18, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 10, -18, 70, -2, -52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 10, -18, 70, -2, -52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 15, -13, -20, 16, 2, 13, 5, -11, -8, -5, -3, 2, 24, -23, 30, -7, + { 15, -13, -20, 16, 2, 13, 5, -11, -8, -5, -3, 2, 24, -23, 30, -7, 11, 30, -15, 43, 5, -15, 15, -3, -14, 1, -23, 8, 3, 9, 4, -11 }, - { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, + { 0, -1, 0, 1, 0, -1, -1, 0, 0, 1, -2, 1, 0, 0, -4, -1, -34, -15, -33, 56, 9, -42, 9, 10, 6, 9, -8, -11, 0, -6, 15, 5 }, - { 10, 2, -14, -3, -15, -35, -1, 7, -18, 14, 8, -1, -15, -26, 6, -15, + { 10, 2, -14, -3, -15, -35, -1, 7, -18, 14, 8, -1, -15, -26, 6, -15, -18, 22, 9, 33, 0, -32, -9, 3, -11, 7, 4, -1, 5, 30, 9, 1 }, - { 4, 15, 0, 6, -5, -11, 9, 6, 6, 6, 14, 2, -1, 10, -24, -25, + { 4, 15, 0, 6, -5, -11, 9, 6, 6, 6, 14, 2, -1, 10, -24, -25, -2, -4, -1, 37, 2, -29, 14, -9, 22, 17, -2, 33, 10, -25, 11, -11 }, - { 0, 5, 2, 18, -12, 21, 22, 33, -7, 21, -9, -7, 7, -15, -7, 16, + { 0, 5, 2, 18, -12, 21, 22, 33, -7, 21, -9, -7, 7, -15, -7, 16, 7, 0, -14, 44, 10, -25, 5, -4, 15, -8, 10, -4, 5, 9, -1, 16 }, - { 3, 13, 12, 12, 8, 25, -23, 8, -22, -3, -18, -8, 15, 12, 9, 19, + { 3, 13, 12, 12, 8, 25, -23, 8, -22, -3, -18, -8, 15, 12, 9, 19, 0, 0, -9, 49, -27, -15, -9, -15, 12, -8, -16, -7, 13, 5, 13, 2 }, - { 12, -6, 7, -2, 20, -9, -14, 12, 13, -5, -17, 22, -8, -4, 2, 7, + { 12, -6, 7, -2, 20, -9, -14, 12, 13, -5, -17, 22, -8, -4, 2, 7, -13, -2, -15, 43, -5, -30, 27, 4, 10, -27, 5, 27, -10, -10, -18, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 10, -18, 70, -2, -52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 10, -18, 70, -2, -52, -1, -7, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 15, -13, -20, 16, 2, 13, 5, -11, -8, -5, -3, 2, 24, -23, 30, -7, + { 15, -13, -20, 16, 2, 13, 5, -11, -8, -5, -3, 2, 24, -23, 30, -7, 11, 30, -15, 43, 5, -15, 15, -3, -14, 1, -23, 8, 3, 9, 4, -11 }, - { 16, -18, 7, -4, 31, -15, -9, -13, 20, -12, -6, 0, 12, -6, -2, 4, + { 16, -18, 7, -4, 31, -15, -9, -13, 20, -12, -6, 0, 12, -6, -2, 4, 3, -3, -1, 0, 1, 3, 3, -2, 1, 6, 4, 0, -3, 2, -5, 1 }, - { 38, -5, -13, -4, 8, -15, 11, 1, 2, -4, -1, 9, 13, 4, -12, -7, + { 38, -5, -13, -4, 8, -15, 11, 1, 2, -4, -1, 9, 13, 4, -12, -7, 0, -2, 7, 2, -6, -2, -3, -2, 3, -4, 6, 15, 1, 1, -11, -2 }, - { 47, -22, 9, -26, 3, -5, 2, -7, 4, -2, 2, -2, 3, 0, 3, -4, + { 47, -22, 9, -26, 3, -5, 2, -7, 4, -2, 2, -2, 3, 0, 3, -4, 3, -3, 2, -3, 7, -3, -1, 1, 1, -5, 5, 0, 2, -5, -3, -2 }, - { 14, -16, 2, -6, 7, -2, -7, -4, -4, -7, 14, -3, 7, -19, -14, -17, + { 14, -16, 2, -6, 7, -2, -7, -4, -4, -7, 14, -3, 7, -19, -14, -17, -29, 6, 26, 16, -5, 13, -4, -1, 21, 14, 1, 3, -6, 0, -7, -1 }, - { 29, -11, 5, -3, 4, 11, 4, -10, 1, -22, -3, -10, 5, 4, 2, 8, + { 29, -11, 5, -3, 4, 11, 4, -10, 1, -22, -3, -10, 5, 4, 2, 8, -2, -7, -12, -12, -8, -3, -18, -2, -9, -5, -1, -3, 2, -14, -14, 7 }, - { 28, -12, 5, 3, 9, -7, 0, -2, 2, 1, 4, 0, -7, -3, -2, 4, + { 28, -12, 5, 3, 9, -7, 0, -2, 2, 1, 4, 0, -7, -3, -2, 4, 4, 14, 8, -1, -4, 14, -7, 17, -2, -2, -9, 2, 19, -7, 9, -8 }, - { 31, -18, -22, 8, 15, -5, -10, -15, 1, 10, 6, 7, 6, -8, 2, -1, + { 31, -18, -22, 8, 15, -5, -10, -15, 1, 10, 6, 7, 6, -8, 2, -1, 12, -3, 3, -1, 1, 5, -6, -4, 0, 1, 7, -10, -2, 4, -3, -4 }, - { 53, -30, -4, 12, 2, 3, -3, -3, 0, 1, 6, 5, -5, -4, -7, 1, + { 53, -30, -4, 12, 2, 3, -3, -3, 0, 1, 6, 5, -5, -4, -7, 1, 0, 2, 1, 3, 1, 5, 0, 2, 2, -1, 0, 4, 2, 0, -2, 0 }, - { 27, -18, -3, -2, 4, -8, 3, -2, -11, 2, 10, -8, -8, -4, 0, -2, + { 27, -18, -3, -2, 4, -8, 3, -2, -11, 2, 10, -8, -8, -4, 0, -2, 8, 0, 9, 0, -16, 11, 1, -6, 13, -3, -10, -13, -15, 25, 1, 0 }, - { 35, -5, -1, -8, 23, 11, -14, -3, 2, -2, 8, -6, 17, -2, 7, 0, + { 35, -5, -1, -8, 23, 11, -14, -3, 2, -2, 8, -6, 17, -2, 7, 0, -2, 10, -17, 13, -2, -2, 11, 11, -14, 2, -2, -3, -8, -1, -12, -5 }, - { 29, -9, 7, 3, 2, -10, 0, 3, 9, 0, -3, 5, 1, -10, 10, -5, + { 29, -9, 7, 3, 2, -10, 0, 3, 9, 0, -3, 5, 1, -10, 10, -5, 3, 6, -20, -9, -6, -4, 1, 0, 12, 17, -8, 9, 3, -1, -9, 0 }, - { 15, -16, 18, -19, 16, -15, 17, -18, 13, -16, 17, -14, 15, -9, 13, -17, + { 15, -16, 18, -19, 16, -15, 17, -18, 13, -16, 17, -14, 15, -9, 13, -17, 9, -7, 4, -5, 3, -4, -3, 0, -6, 7, -9, 7, -2, 7, -9, 9 }, - { 21, -10, 7, -2, 12, -7, 13, -17, 11, -2, 20, 3, 5, -11, -6, -6, + { 21, -10, 7, -2, 12, -7, 13, -17, 11, -2, 20, 3, 5, -11, -6, -6, -15, 0, -9, 5, -11, 7, -1, 7, 8, -10, -9, 3, -5, 9, -8, -2 }, - { 23, -22, 15, -5, 16, -4, -3, -12, 9, 3, -1, -2, -8, 2, -2, -16, + { 23, -22, 15, -5, 16, -4, -3, -12, 9, 3, -1, -2, -8, 2, -2, -16, 3, 4, -2, -6, -7, 12, -8, 2, -14, 2, -7, 11, -2, 6, -4, -1 }, - { 34, -17, -4, 8, 4, -6, 1, 8, 4, 16, 3, 6, 12, -1, -1, -15, + { 34, -17, -4, 8, 4, -6, 1, 8, 4, 16, 3, 6, 12, -1, -1, -15, 6, 4, -7, -6, 6, 0, 2, 1, -2, 2, 3, 3, -3, -2, 8, -6 }, - { 18, -18, 2, -2, 10, 1, 18, -23, -3, -10, 0, 4, 20, -19, -3, -4, + { 18, -18, 2, -2, 10, 1, 18, -23, -3, -10, 0, 4, 20, -19, -3, -4, 2, 8, 6, 1, -3, 1, 1, 3, 5, -1, -11, 3, -7, 5, -1, 1 }, - { 15, -14, 2, 3, 10, -8, 12, -13, 13, -15, 6, -8, -4, -10, 14, -9, + { 15, -14, 2, 3, 10, -8, 12, -13, 13, -15, 6, -8, -4, -10, 14, -9, 24, 2, -7, -18, 13, -11, 8, 14, -6, -2, 3, -1, -4, 7, -7, -4 }, - { 20, -12, 13, 5, -1, -10, 15, -6, 8, -1, -3, -10, 17, 0, -6, -19, + { 20, -12, 13, 5, -1, -10, 15, -6, 8, -1, -3, -10, 17, 0, -6, -19, 2, -1, 8, -3, -16, 0, -3, 2, -2, 0, 8, -9, 0, 1, -10, -9 }, - { 32, 0, -9, -5, -1, 5, 13, -11, 8, 3, 11, -11, 0, -8, -2, -14, + { 32, 0, -9, -5, -1, 5, 13, -11, 8, 3, 11, -11, 0, -8, -2, -14, 7, 10, 6, -5, 1, 10, 2, 12, -10, 4, 4, 6, 4, 0, -7, -10 }, - { 16, -14, 10, -7, 11, -11, 11, -11, 18, -13, 8, -15, 16, -11, 13, -9, + { 16, -14, 10, -7, 11, -11, 11, -11, 18, -13, 8, -15, 16, -11, 13, -9, 8, -7, 12, -11, 7, -6, 3, -5, 9, -5, 4, -1, 7, -4, 8, -3 }, - { 24, -27, -1, 5, 8, -5, 12, 7, 4, -3, 3, -1, -9, -11, -13, -5, + { 24, -27, -1, 5, 8, -5, 12, 7, 4, -3, 3, -1, -9, -11, -13, -5, 10, 0, -13, 7, 1, -5, 4, -9, 7, -3, 13, 2, -5, -3, -17, -2 }, - { 23, -19, 15, 1, -10, -18, -12, -6, 8, -3, 12, 0, -12, -10, -4, -4, + { 23, -19, 15, 1, -10, -18, -12, -6, 8, -3, 12, 0, -12, -10, -4, -4, 8, -10, 4, 2, -2, -8, 13, -3, -2, -6, 2, -3, 5, -2, 2, 11 }, - { 25, -12, 4, 2, 24, -3, 3, -6, 14, 11, 0, -21, -3, -3, 1, -8, + { 25, -12, 4, 2, 24, -3, 3, -6, 14, 11, 0, -21, -3, -3, 1, -8, 7, 0, 0, 3, 3, -6, -7, 6, 2, 1, -4, 5, -1, 10, -2, 9 }, - { 24, -8, -6, 7, 16, -12, 13, -1, 11, -21, 2, -6, 3, -12, 0, 9, + { 24, -8, -6, 7, 16, -12, 13, -1, 11, -21, 2, -6, 3, -12, 0, 9, 4, 11, -7, 1, 4, 1, -8, 3, 3, -6, 3, 3, 0, -8, 8, 4 }, - { 25, -21, 13, 14, 13, -18, 4, -3, 0, -5, -4, 5, -3, 0, 4, 12, + { 25, -21, 13, 14, 13, -18, 4, -3, 0, -5, -4, 5, -3, 0, 4, 12, 7, 3, 5, -5, 2, -2, 3, -10, 2, -9, -15, 6, 1, 7, -5, 1 }, - { 23, -16, -2, 10, 4, -1, 3, 1, 32, 3, -5, -2, 9, 10, -1, -4, + { 23, -16, -2, 10, 4, -1, 3, 1, 32, 3, -5, -2, 9, 10, -1, -4, -6, 2, 9, -1, 14, 12, -6, -1, -17, -2, -4, -9, -7, -6, -8, 3 }, - { 50, -8, 5, 2, -11, 10, 0, 0, 6, -3, 7, 0, -3, -2, -3, 0, + { 50, -8, 5, 2, -11, 10, 0, 0, 6, -3, 7, 0, -3, -2, -3, 0, 6, -4, 2, -5, -9, 0, 3, 10, 1, -7, -2, -3, -6, -9, 1, -2 }, - { 28, -17, 0, -2, 2, -9, 1, 5, -4, -1, 0, 0, 19, -27, 5, -12, + { 28, -17, 0, -2, 2, -9, 1, 5, -4, -1, 0, 0, 19, -27, 5, -12, 7, -14, -3, -6, 10, -2, -4, -2, 4, -5, -2, -7, 1, 7, -9, 4 }, - { 22, -19, -6, -6, 3, -22, 3, 5, 20, -8, -14, -5, 1, 1, 20, 2, + { 22, -19, -6, -6, 3, -22, 3, 5, 20, -8, -14, -5, 1, 1, 20, 2, 16, 6, 3, 14, 4, 3, 5, 1, 5, -7, -10, -6, 3, -6, 1, -14 }, - { 29, -14, -8, 13, 8, -10, -6, 4, 4, -6, 5, -7, 1, 12, 14, 11, + { 29, -14, -8, 13, 8, -10, -6, 4, 4, -6, 5, -7, 1, 12, 14, 11, -7, 1, 2, -9, -11, -9, 0, 4, -1, 7, 10, 4, 4, 20, -1, -11 }, - { 18, -9, 4, 1, 7, -29, 12, 1, -1, -9, -2, -1, -2, 2, 9, -8, + { 18, -9, 4, 1, 7, -29, 12, 1, -1, -9, -2, -1, -2, 2, 9, -8, -13, 5, 4, -13, -4, 2, -5, -7, -6, 14, -10, -34, -3, 1, -3, -13 }, - { 38, -9, 24, 8, 11, 4, -6, -11, -2, -12, 1, 1, -11, -8, -5, -2, + { 38, -9, 24, 8, 11, 4, -6, -11, -2, -12, 1, 1, -11, -8, -5, -2, -15, -8, 8, 0, 1, -7, 5, 4, -1, 8, -2, 11, -3, -1, -5, -5 }, - { -20, 11, -4, 24, -11, 1, 15, 4, 0, -28, -10, -1, 10, 10, -6, 5, + { -20, 11, -4, 24, -11, 1, 15, 4, 0, -28, -10, -1, 10, 10, -6, 5, -6, 2, 7, -2, 1, -2, -6, -3, -7, 1, 2, 12, -1, 7, 0, -2 }, - { -9, 10, -23, 27, -4, -17, 20, -6, 14, -17, 5, -1, 5, -9, -7, 5, + { -9, 10, -23, 27, -4, -17, 20, -6, 14, -17, 5, -1, 5, -9, -7, 5, -6, 4, -2, 9, 0, 8, 0, 1, -3, -3, -5, -8, 5, -2, -2, 12 }, - { -10, 19, 4, 9, 1, -16, 17, -2, 9, -29, -16, -11, -4, 7, -5, 4, + { -10, 19, 4, 9, 1, -16, 17, -2, 9, -29, -16, -11, -4, 7, -5, 4, -1, -3, 3, 2, 3, -4, 5, -12, -2, 6, 5, -4, 4, 1, 4, 10 }, - { -20, 10, -24, 14, -5, 11, 9, 0, 16, -20, 10, -5, -6, -6, -1, 2, + { -20, 10, -24, 14, -5, 11, 9, 0, 16, -20, 10, -5, -6, -6, -1, 2, -4, 5, -16, 8, -2, 5, 5, -11, 9, -11, 4, -11, -1, -1, 4, 3 }, - { -9, 11, 3, 19, 24, 4, 5, -14, 30, -17, -4, -2, -17, 7, 2, 3, + { -9, 11, 3, 19, 24, 4, 5, -14, 30, -17, -4, -2, -17, 7, 2, 3, 1, 3, -7, -4, 2, -3, 1, 4, -1, -1, 3, -12, -2, 3, -3, 10 }, - { -19, 18, 11, 19, 19, 19, 10, 4, 13, 6, 5, 4, 8, 3, -2, 12, + { -19, 18, 11, 19, 19, 19, 10, 4, 13, 6, 5, 4, 8, 3, -2, 12, -6, -2, 7, -6, 15, 12, 16, 16, 18, -3, -4, -20, 0, 10, -9, -3 }, - { -21, 9, 20, 12, 0, -3, 5, -9, 15, -13, 5, -5, -6, 24, 2, 9, + { -21, 9, 20, 12, 0, -3, 5, -9, 15, -13, 5, -5, -6, 24, 2, 9, -5, 2, -7, 2, 5, 7, -5, 2, 15, 3, 1, -1, -4, -2, 7, 0 }, - { -18, 16, 13, 15, 2, -10, 14, -11, 4, -11, 5, 12, 12, 20, 8, 30, + { -18, 16, 13, 15, 2, -10, 14, -11, 4, -11, 5, 12, 12, 20, 8, 30, 2, 11, -9, 7, 0, -3, -16, -5, -6, 5, -4, -21, 0, 5, 6, 1 }, - { -26, 8, -13, 9, 6, -10, 2, -11, 7, -4, 6, -19, -11, -6, -12, 16, + { -26, 8, -13, 9, 6, -10, 2, -11, 7, -4, 6, -19, -11, -6, -12, 16, 0, 5, -7, 8, 5, 6, 17, -9, 10, -10, 5, -3, -11, 2, 4, 10 }, - { -11, 17, -3, 22, -5, 18, 3, 1, 4, -5, 14, -27, 5, -7, -4, -5, + { -11, 17, -3, 22, -5, 18, 3, 1, 4, -5, 14, -27, 5, -7, -4, -5, -10, 11, 1, 15, 1, 1, -6, -5, 10, -22, -7, -7, -15, 13, -4, 5 }, - { -17, 14, -7, 13, 3, 0, 13, -6, 9, -14, -22, -1, 1, 19, 14, -3, + { -17, 14, -7, 13, 3, 0, 13, -6, 9, -14, -22, -1, 1, 19, 14, -3, 4, -13, -13, 2, -4, 8, -2, -2, 13, -12, 13, -12, -7, -5, -3, 6 }, - { -17, 17, -1, 33, 6, 3, 9, -16, 3, -14, -8, 6, -17, 8, 3, 13, + { -17, 17, -1, 33, 6, 3, 9, -16, 3, -14, -8, 6, -17, 8, 3, 13, 8, -6, 3, 1, -2, 0, -2, 8, 4, 9, 13, -10, 4, -17, 0, -6 }, - { -20, 7, 7, 21, 1, -3, 7, -3, -2, -12, 9, -7, 2, -3, 14, 1, + { -20, 7, 7, 21, 1, -3, 7, -3, -2, -12, 9, -7, 2, -3, 14, 1, -1, -7, 12, -10, 5, -20, 11, -2, 0, -24, -17, 6, 6, -4, 3, -1 }, - { -8, 10, 6, 7, -1, -6, 28, -6, 10, -33, 1, -20, 0, -12, 10, 1, + { -8, 10, 6, 7, -1, -6, 28, -6, 10, -33, 1, -20, 0, -12, 10, 1, -6, 8, -3, -1, -10, 8, 5, 0, 10, -2, 8, 16, -5, -3, -7, 4 }, - { -17, 13, 3, 15, 1, -5, 27, -5, 6, -6, 12, 2, -4, 8, -1, -3, + { -17, 13, 3, 15, 1, -5, 27, -5, 6, -6, 12, 2, -4, 8, -1, -3, -2, 12, -15, 3, 4, 1, 2, -9, 0, -16, -21, 2, -4, 16, -7, 4 }, - { -15, 20, 8, 17, 5, -14, 15, -11, 21, -11, 13, -13, 2, -15, -13, 1, + { -15, 20, 8, 17, 5, -14, 15, -11, 21, -11, 13, -13, 2, -15, -13, 1, -5, 5, 2, 10, -9, 4, -1, 3, 2, -4, 13, -5, 1, -4, 5, -3 }, - { -21, 8, 2, 16, -1, 2, 15, -16, 13, -12, -12, -7, -8, 2, -7, 11, + { -21, 8, 2, 16, -1, 2, 15, -16, 13, -12, -12, -7, -8, 2, -7, 11, -8, 5, 2, -7, 16, -4, 1, -7, 3, -15, 6, -5, -8, 2, -8, 5 }, - { -15, 17, -6, 3, -3, 3, 9, -7, 14, -23, 11, 1, -1, 4, 7, 6, + { -15, 17, -6, 3, -3, 3, 9, -7, 14, -23, 11, 1, -1, 4, 7, 6, -1, -14, 7, 6, -8, 5, 1, -15, 10, -9, 2, -3, -1, 4, -10, -4 }, - { -10, 18, 3, 11, 1, 4, 14, -14, 7, -4, 15, -10, 10, -11, 10, -4, + { -10, 18, 3, 11, 1, 4, 14, -14, 7, -4, 15, -10, 10, -11, 10, -4, 5, -14, 10, 4, 15, -12, 15, -13, 20, -15, 14, -15, 8, -11, 4, -6 }, - { -7, 23, 2, 20, 7, 8, 19, -5, 9, -16, -8, -17, -5, 1, 5, -6, + { -7, 23, 2, 20, 7, 8, 19, -5, 9, -16, -8, -17, -5, 1, 5, -6, -8, 1, -6, -4, 10, 6, 6, 2, -11, -4, 0, 2, 4, 7, 9, -4 }, - { -15, 20, -5, 22, 11, -8, 9, -5, 10, -13, -8, 8, 2, -2, -3, 7, + { -15, 20, -5, 22, 11, -8, 9, -5, 10, -13, -8, 8, 2, -2, -3, 7, 6, 10, 1, 2, -5, -9, 1, 10, 16, -22, -7, 0, 7, 7, 6, 1 }, - { -26, 19, -5, 3, 5, 25, 18, -5, 9, -14, -8, -6, -2, -6, 2, 3, + { -26, 19, -5, 3, 5, 25, 18, -5, 9, -14, -8, -6, -2, -6, 2, 3, -8, -2, -7, 7, -3, 7, 3, 4, -8, 0, 1, -8, -4, -2, -2, 1 }, - { -20, 14, -10, 6, -3, 7, 8, -32, -2, -7, -2, -10, 16, -12, -9, 15, + { -20, 14, -10, 6, -3, 7, 8, -32, -2, -7, -2, -10, 16, -12, -9, 15, -2, -5, -6, 2, -7, 5, 9, 1, 6, -7, -1, 0, -2, -4, -7, 3 }, - { -14, 16, 4, 11, -8, 1, 23, -4, 17, -13, -10, 1, 12, 9, 12, -4, + { -14, 16, 4, 11, -8, 1, 23, -4, 17, -13, -10, 1, 12, 9, 12, -4, 7, -1, -1, 5, -8, -6, 3, 3, -6, -3, -18, 0, 18, 20, 4, -2 }, - { -33, 19, -10, 30, 15, 2, -3, -1, -4, -14, 7, -7, -1, 7, -8, 9, + { -33, 19, -10, 30, 15, 2, -3, -1, -4, -14, 7, -7, -1, 7, -8, 9, -1, -3, -5, 2, 2, 4, 0, 5, 0, 0, 2, 3, 3, -3, -3, 4 }, - { -6, 20, 0, 5, 17, -10, 18, -17, 9, -16, 4, -13, -6, 2, -14, 14, + { -6, 20, 0, 5, 17, -10, 18, -17, 9, -16, 4, -13, -6, 2, -14, 14, -28, 9, -12, 25, -4, 7, 7, -8, 6, -6, -2, -10, 2, -11, -1, 2 }, - { -12, 14, 12, 52, -3, 5, -5, 4, 8, -13, 2, -5, -4, 2, -2, -1, + { -12, 14, 12, 52, -3, 5, -5, 4, 8, -13, 2, -5, -4, 2, -2, -1, -2, 3, 3, 5, 2, 3, 0, 1, -5, 2, -4, -3, 1, -5, -2, 0 }, - { -13, 6, 9, 24, 0, 8, 14, -15, 18, -9, -11, -8, 3, 15, -2, -4, + { -13, 6, 9, 24, 0, 8, 14, -15, 18, -9, -11, -8, 3, 15, -2, -4, -9, 4, -3, 12, 14, -13, 11, -4, 2, -4, 0, -6, -6, -6, -14, -1 }, - { -10, 28, 3, 12, 9, 3, 11, -28, 6, -11, -7, 4, 0, 7, 8, -9, + { -10, 28, 3, 12, 9, 3, 11, -28, 6, -11, -7, 4, 0, 7, 8, -9, 0, -6, 0, -16, 4, 7, 4, 4, 7, 3, 4, -7, 0, -3, -10, 6 }, - { -11, 14, -2, 19, -1, -1, 7, 9, -2, -27, 10, -14, 15, -4, 12, -4, + { -11, 14, -2, 19, -1, -1, 7, 9, -2, -27, 10, -14, 15, -4, 12, -4, 2, -2, -6, 12, -6, 0, -5, -4, -5, 1, 3, -11, 5, -9, 3, -8 }, - { -18, 7, 13, 16, -4, 3, 9, -10, 10, -10, -3, -22, -4, -12, 3, -16, + { -18, 7, 13, 16, -4, 3, 9, -10, 10, -10, -3, -22, -4, -12, 3, -16, 0, -3, -16, 8, -11, 1, 10, -7, 15, 3, 0, -1, -13, 8, 1, 6 }, - { -20, 10, -10, 10, 8, -1, 6, 0, 16, -12, 9, -10, -1, -5, -4, -13, + { -20, 10, -10, 10, 8, -1, 6, 0, 16, -12, 9, -10, -1, -5, -4, -13, 13, 16, -8, 12, -2, 14, 18, 13, 0, -16, 2, -5, -5, -5, -4, 3 }, - { -14, 5, -7, -17, 5, -13, 23, 20, -4, -1, 1, -6, 13, 5, -1, 4, + { -14, 5, -7, -17, 5, -13, 23, 20, -4, -1, 1, -6, 13, 5, -1, 4, -14, -2, -7, 8, 3, 2, 2, -7, 2, -1, 4, 7, 3, -9, -1, -5 }, - { -19, 3, -24, -28, -9, -7, 19, 3, 2, 19, 7, 5, -13, 8, -15, -17, + { -19, 3, -24, -28, -9, -7, 19, 3, 2, 19, 7, 5, -13, 8, -15, -17, 3, -11, 4, 13, 3, 2, -1, -3, -4, -4, 2, 0, -5, -6, 6, 2 }, - { -17, 18, -30, -20, -2, -3, 1, 15, -1, -11, 6, -4, 11, 11, -4, -5, + { -17, 18, -30, -20, -2, -3, 1, 15, -1, -11, 6, -4, 11, 11, -4, -5, -10, 0, 0, 1, 3, -7, 8, 2, 5, 1, 5, -5, 1, 6, 4, 1 }, - { -6, 1, -30, -25, -1, -8, -2, -9, -17, 16, 3, -1, -2, -9, -6, -7, + { -6, 1, -30, -25, -1, -8, -2, -9, -17, 16, 3, -1, -2, -9, -6, -7, -3, 12, 6, -4, -10, 0, 10, -8, -6, -5, -3, -11, -4, 0, -1, -3 }, - { -1, -1, -34, -28, 1, -10, 2, 9, 4, 16, 2, 6, 14, 17, 0, 7, + { -1, -1, -34, -28, 1, -10, 2, 9, 4, 16, 2, 6, 14, 17, 0, 7, -4, 4, 4, 4, 0, 1, -1, -5, 8, 1, -4, 1, -9, -2, 5, 6 }, - { -11, 14, 1, -31, -7, -24, 9, 7, 6, 5, -13, 1, -1, 3, 4, -1, + { -11, 14, 1, -31, -7, -24, 9, 7, 6, 5, -13, 1, -1, 3, 4, -1, -2, -8, -6, 3, 5, -4, -6, 7, -2, 5, 3, 3, 0, 0, -5, 2 }, - { -25, 8, -11, -18, 1, -4, 8, -3, -4, 15, 6, -5, 8, 2, 3, 4, + { -25, 8, -11, -18, 1, -4, 8, -3, -4, 15, 6, -5, 8, 2, 3, 4, -4, 5, 6, 8, -7, 6, 1, -11, -15, -13, 9, -4, -14, 10, 12, 7 }, - { -20, 11, -15, -25, 3, 4, 18, 13, -4, -5, -9, -1, -5, -2, -2, -7, + { -20, 11, -15, -25, 3, 4, 18, 13, -4, -5, -9, -1, -5, -2, -2, -7, 16, 5, -4, -5, -7, -2, -3, -9, 11, -2, 0, -7, -17, -6, -11, 6 }, - { -11, 18, -5, -20, -15, -3, 9, 11, -20, 12, 5, 5, 11, -3, 7, 1, + { -11, 18, -5, -20, -15, -3, 9, 11, -20, 12, 5, 5, 11, -3, 7, 1, 10, -6, -3, -3, 3, 3, 14, -7, 10, -17, 9, -11, -2, -6, 7, -12 }, - { -20, 8, -14, -17, -9, -13, -3, 0, -27, -14, -3, -14, 4, 3, 6, -6, + { -20, 8, -14, -17, -9, -13, -3, 0, -27, -14, -3, -14, 4, 3, 6, -6, 7, 4, 23, 9, 11, 9, 3, -4, 9, 2, 4, -1, -6, 1, -8, -11 }, - { -9, 14, 2, -37, -7, 13, 6, -11, -6, 9, 18, -11, -6, 2, 12, 4, + { -9, 14, 2, -37, -7, 13, 6, -11, -6, 9, 18, -11, -6, 2, 12, 4, -1, 3, 1, -2, -2, 1, -9, -4, -2, -3, 3, 5, -6, 0, -2, -8 }, - { -29, 8, -1, -13, -2, 8, 23, 2, -10, 7, 13, -6, -5, 11, 13, 0, + { -29, 8, -1, -13, -2, 8, 23, 2, -10, 7, 13, -6, -5, 11, 13, 0, -10, -13, 11, -12, -10, 6, 4, 6, 4, 3, 6, -5, -9, -2, -1, 3 }, - { -18, 6, -10, -55, -4, -11, -2, 0, 1, -3, -9, -6, 3, -2, -1, 6, + { -18, 6, -10, -55, -4, -11, -2, 0, 1, -3, -9, -6, 3, -2, -1, 6, 3, -1, 3, 1, -4, -7, -2, 6, 3, -2, -1, -3, -2, 0, 4, 1 }, - { -14, 5, 3, -21, -8, -16, -4, -2, -11, 27, 15, -20, 3, 0, 1, 1, + { -14, 5, 3, -21, -8, -16, -4, -2, -11, 27, 15, -20, 3, 0, 1, 1, 2, -5, -5, 4, 1, -9, 5, -3, 3, 0, -4, -2, -11, -4, -3, 7 }, - { -17, -1, -9, -17, -8, -18, 12, -13, -9, 13, -3, 3, 3, -3, 1, -2, + { -17, -1, -9, -17, -8, -18, 12, -13, -9, 13, -3, 3, 3, -3, 1, -2, 0, 16, -9, 6, 12, 9, 5, 11, 2, -15, 1, -4, -16, 7, -4, -12 }, - { -18, 8, -6, -11, -8, -7, 13, 7, 1, 6, 8, -1, 21, -4, 14, 15, + { -18, 8, -6, -11, -8, -7, 13, 7, 1, 6, 8, -1, 21, -4, 14, 15, 18, -4, -3, 15, 0, 9, 4, 7, 3, -1, 9, -2, 0, 7, -8, 2 }, - { -10, 7, -18, -29, 3, 12, 12, 9, 11, 4, -1, -15, 1, -1, 8, -2, + { -10, 7, -18, -29, 3, 12, 12, 9, 11, 4, -1, -15, 1, -1, 8, -2, -2, 10, -15, -1, 0, 6, 12, -6, -1, 10, -6, -3, -11, -4, 9, -6 }, - { -14, 14, -9, -21, -12, -2, -1, -7, -5, -10, 5, -8, 0, 6, 9, -11, + { -14, 14, -9, -21, -12, -2, -1, -7, -5, -10, 5, -8, 0, 6, 9, -11, 11, -3, -5, 3, 8, 15, -2, -4, -22, 4, -6, 12, 2, 13, 6, -7 }, - { -12, 11, -5, -29, -25, 4, 12, -13, -11, -7, 4, 2, 2, -5, 5, 8, + { -12, 11, -5, -29, -25, 4, 12, -13, -11, -7, 4, 2, 2, -5, 5, 8, 7, -5, -5, 6, 3, -10, 1, -6, 6, -6, -5, -1, -2, -4, 7, 6 }, - { -15, 11, -5, -16, 0, -13, 26, -23, -6, -3, 5, -2, -2, 21, -6, -3, + { -15, 11, -5, -16, 0, -13, 26, -23, -6, -3, 5, -2, -2, 21, -6, -3, -5, -1, 6, -1, 0, -13, 2, -3, -9, -1, -4, -3, 5, -4, 12, -16 }, - { -9, 9, -1, -17, -3, -6, 12, 6, -18, -2, 11, -14, -6, 3, 14, -12, + { -9, 9, -1, -17, -3, -6, 12, 6, -18, -2, 11, -14, -6, 3, 14, -12, -11, -5, 14, 2, 5, -8, -4, -11, 2, -5, 16, 6, -7, -4, 8, 13 }, - { -13, 5, 3, -28, -14, 0, 6, 23, 5, 4, -1, -17, 1, -3, 0, 0, + { -13, 5, 3, -28, -14, 0, 6, 23, 5, 4, -1, -17, 1, -3, 0, 0, 5, 4, 0, -18, 14, 10, 4, 2, 5, -2, 4, -3, 2, 0, 2, 0 }, - { -15, 4, -13, -16, -3, -12, -2, 2, 7, 10, 9, 3, 11, 4, 23, 14, + { -15, 4, -13, -16, -3, -12, -2, 2, 7, 10, 9, 3, 11, 4, 23, 14, 9, 16, 4, 1, -12, -3, 4, -7, -15, -7, -10, -14, -6, -8, -1, -6 }, - { -7, 10, -5, -10, -3, -13, 16, -1, -12, 7, -3, -12, 2, 13, 13, 2, + { -7, 10, -5, -10, -3, -13, 16, -1, -12, 7, -3, -12, 2, 13, 13, 2, 17, 15, -13, 1, -5, -2, 3, -1, 1, -3, 6, -3, -12, -16, 7, -7 }, - { -11, -5, -12, -30, -6, -22, 1, 4, -6, -3, 12, 6, 7, 0, 16, 6, + { -11, -5, -12, -30, -6, -22, 1, 4, -6, -3, 12, 6, 7, 0, 16, 6, -2, 0, -22, -2, -9, 2, -13, 8, 6, -8, 4, -7, -1, -6, 4, 6 }, - { -14, 5, 1, -27, -4, 2, 1, 14, -11, -7, -8, -4, 1, 8, 0, -6, + { -14, 5, 1, -27, -4, 2, 1, 14, -11, -7, -8, -4, 1, 8, 0, -6, -13, 11, -12, -7, -5, 1, 10, 7, 3, -2, 0, 6, -8, 2, 10, -1 }, - { -10, 10, -25, -13, -20, -4, 19, 3, 13, 5, 5, 7, -8, 2, 4, 2, + { -10, 10, -25, -13, -20, -4, 19, 3, 13, 5, 5, 7, -8, 2, 4, 2, 3, -1, -1, -9, 14, 10, 9, 14, 3, 3, -6, 0, -5, 4, 1, -1 }, - { -9, 15, -18, -17, 4, -11, 6, 7, -12, 8, -1, -11, 2, 3, 7, 16, + { -9, 15, -18, -17, 4, -11, 6, 7, -12, 8, -1, -11, 2, 3, 7, 16, -3, -9, 7, -12, 23, 0, 6, 7, -14, -9, 8, 1, -2, 6, -2, -1 }, - { -6, 9, -16, -26, -14, -11, 9, -6, 5, -2, 13, 17, 21, 7, 18, -19, + { -6, 9, -16, -26, -14, -11, 9, -6, 5, -2, 13, 17, 21, 7, 18, -19, 6, -23, -2, -15, -2, 2, -10, -8, 2, 1, -2, 4, -3, -4, -5, -4 }, - { 0, 6, -5, -28, -17, -32, 2, -10, 11, 3, -5, 9, 10, 3, 11, 11, + { 0, 6, -5, -28, -17, -32, 2, -10, 11, 3, -5, 9, 10, 3, 11, 11, -3, 12, -2, 2, 4, -6, 9, -4, -4, -4, -4, -9, 2, 0, 2, 4 }, - { 0, -8, -18, -34, -9, -7, -4, -11, 10, 15, 11, -1, -8, 15, 6, -13, + { 0, -8, -18, -34, -9, -7, -4, -11, 10, 15, 11, -1, -8, 15, 6, -13, 9, 2, -4, -12, 0, -1, 19, 12, 6, 5, 0, -3, -10, -12, 3, -5 }, - { -10, 6, -9, -17, -12, -11, 9, -6, 11, 11, 18, -7, 0, 16, 4, 2, + { -10, 6, -9, -17, -12, -11, 9, -6, 11, 11, 18, -7, 0, 16, 4, 2, -6, 3, -12, -1, 0, 1, -5, -22, -2, -12, 0, 6, 17, 5, 5, 6 }, - { 12, -5, 7, 1, -5, -2, -1, 2, 2, -4, -3, -3, -3, -2, -29, 11, + { 12, -5, 7, 1, -5, -2, -1, 2, 2, -4, -3, -3, -3, -2, -29, 11, 5, -13, -73, 24, 12, 4, -14, -10, 5, 1, 0, -11, -7, -7, 7, 3 }, - { 10, -3, -1, -3, 4, -11, -5, -2, -8, 7, 9, 2, -8, -6, 6, 7, + { 10, -3, -1, -3, 4, -11, -5, -2, -8, 7, 9, 2, -8, -6, 6, 7, 21, 17, -54, 47, -14, -10, 14, 19, 13, 21, -4, 3, 1, 2, -4, 2 }, - { -12, 4, -16, -12, 5, -9, -4, 19, -7, -22, -22, -17, 3, 0, -6, 8, + { -12, 4, -16, -12, 5, -9, -4, 19, -7, -22, -22, -17, 3, 0, -6, 8, 23, -4, -55, -28, 2, -26, 2, 1, 4, 0, -13, 6, 0, 10, -7, -11 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, 35, -1, -67, -35, -24, -24, -6, 2, 2, -2, 1, 3, 2, 0, -1, 1 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 5, 0, 41, -4, -73, -15, 18, 4, 17, 8, -1, -16, -1, -2, 1, 0, 0, 0 }, - { -4, -4, 4, 6, -1, 2, -16, -10, -15, -10, 21, -2, -6, -2, 14, -7, + { -4, -4, 4, 6, -1, 2, -16, -10, -15, -10, 21, -2, -6, -2, 14, -7, 10, -5, -55, 34, -12, 11, -13, -2, 2, 28, -26, 0, 7, 4, 21, -7 }, - { 2, 1, 15, -22, 10, -3, 14, -6, -2, 15, -2, -7, 20, 6, -15, -7, + { 2, 1, 15, -22, 10, -3, 14, -6, -2, 15, -2, -7, 20, 6, -15, -7, 23, 10, -60, 8, -4, 29, -22, 2, -13, 9, -10, 12, -1, -3, 4, 7 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -2, 11, -5, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0, -1, -2, 11, -5, -21, -11, -60, -27, -17, -39, 6, 36, 0, -8, 2, 2, 0, 0, -2, 3 }, - { 2, -5, 9, -17, -1, 2, -3, -6, 8, 12, 7, -6, -33, -11, -14, -40, + { 2, -5, 9, -17, -1, 2, -3, -6, 8, 12, 7, -6, -33, -11, -14, -40, 10, 36, -46, 0, -19, 5, 0, -10, 3, 12, -6, -8, 6, -12, -7, 1 }, - { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, -2, 0, + { 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, -1, 0, 1, 0, -2, 0, 4, -2, -87, -3, -2, 2, -2, 20, 2, 6, -1, 6, 0, 0, 2, -1 }, - { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, + { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 7, -76, 41, -7, -24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, - { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, + { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, -32, -11, -64, -29, -9, -43, 2, -11, -1, -7, 0, -4, -2, -2, -2, 2 }, - { 10, -20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2, -20, -20, + { 10, -20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2, -20, -20, -19, 3, -47, -18, -16, -6, -15, -42, -17, 14, -6, 8, 12, -10, 11, -12 }, - { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, + { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, 10, 13, -68, -9, 26, 3, 5, 3, -21, 10, -15, 21, -22, 19, 11, -14 }, - { 1, 5, 18, -19, -29, -13, -2, 18, -10, 20, 2, 10, -10, 11, 1, 8, + { 1, 5, 18, -19, -29, -13, -2, 18, -10, 20, 2, 10, -10, 11, 1, 8, -16, -17, -41, 10, -14, -25, 0, -14, -19, 17, 7, -12, 14, -11, 14, 5 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, -43, 5, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, -43, 5, 6, -12, -48, 19, 8, -38, -8, -3, 22, -21, -10, 15, 20, -9, -5, 8 }, - { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, + { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, 22, -14, -71, -24, -2, -33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, - { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10, -11, + { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10, -11, -17, -32, -58, 14, -14, -11, -2, 15, 2, -8, 12, 10, -9, 13, -33, -14 }, - { 15, -17, -19, 7, -8, -15, -32, -22, 7, 12, 18, 0, 0, -15, -4, 16, + { 15, -17, -19, 7, -8, -15, -32, -22, 7, 12, 18, 0, 0, -15, -4, 16, 37, -2, -46, 11, 2, -8, -10, -8, 14, 9, -4, 5, 7, -17, 4, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -5, 3, -85, 23, -9, -17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -5, 3, -85, 23, -9, -17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, + { 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, -1, 0, 0, 1, 1, 7, -76, 41, -7, -24, 0, -6, 3, 6, 0, -2, -1, 1, 0, 0 }, - { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, + { 0, -3, 4, 2, 3, 2, 2, 0, 3, -1, 4, 0, -1, 4, -2, -4, -32, -11, -64, -29, -9, -43, 2, -11, -1, -7, 0, -4, -2, -2, -2, 2 }, - { 10, -20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2, -20, -20, + { 10, -20, 3, -3, 13, 13, 0, -4, 2, 7, -8, 7, -2, 2, -20, -20, -19, 3, -47, -18, -16, -6, -15, -42, -17, 14, -6, 8, 12, -10, 11, -12 }, - { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, + { -3, -2, -2, -1, -1, 4, -3, -1, -6, -2, 3, 2, -3, 6, -1, -9, 10, 13, -68, -9, 26, 3, 5, 3, -21, 10, -15, 21, -22, 19, 11, -14 }, - { 1, 5, 18, -19, -29, -13, -2, 18, -10, 20, 2, 10, -10, 11, 1, 8, + { 1, 5, 18, -19, -29, -13, -2, 18, -10, 20, 2, 10, -10, 11, 1, 8, -16, -17, -41, 10, -14, -25, 0, -14, -19, 17, 7, -12, 14, -11, 14, 5 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, -43, 5, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, -1, -43, 5, 6, -12, -48, 19, 8, -38, -8, -3, 22, -21, -10, 15, 20, -9, -5, 8 }, - { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, + { 0, 0, 0, 0, -1, 1, -1, 0, 0, 0, 0, 0, 0, 0, 6, -3, 22, -14, -71, -24, -2, -33, 23, 7, -8, 7, -3, 2, -4, 1, -8, -2 }, - { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10, -11, + { 1, 0, -1, 2, 0, -2, 0, 0, -1, 0, 4, 0, 26, -1, 10, -11, -17, -32, -58, 14, -14, -11, -2, 15, 2, -8, 12, 10, -9, 13, -33, -14 }, - { 15, -17, -19, 7, -8, -15, -32, -22, 7, 12, 18, 0, 0, -15, -4, 16, + { 15, -17, -19, 7, -8, -15, -32, -22, 7, 12, 18, 0, 0, -15, -4, 16, 37, -2, -46, 11, 2, -8, -10, -8, 14, 9, -4, 5, 7, -17, 4, 3 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -5, 3, -85, 23, -9, -17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, 0, -5, 3, -85, 23, -9, -17, -2, -2, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 16, 65, -2, -2, 4, 3, 0, -7, 3, 1, 3, 1, 0, 5, 1, -5, + { 16, 65, -2, -2, 4, 3, 0, -7, 3, 1, 3, 1, 0, 5, 1, -5, 0, 2, -1, 3, 0, 0, -1, -2, 6, 0, -2, 0, 0, -1, 1, 1 }, - { 5, 37, -4, 8, -4, -1, 9, 17, 6, -7, 5, -1, 11, 6, -4, 7, + { 5, 37, -4, 8, -4, -1, 9, 17, 6, -7, 5, -1, 11, 6, -4, 7, -2, 4, 1, -3, 11, 3, 3, -9, 6, 0, -2, -4, -5, 4, -12, -11 }, - { 15, 24, -14, 2, 6, 17, 26, 5, 8, 11, -9, -7, -6, -8, 3, -5, + { 15, 24, -14, 2, 6, 17, 26, 5, 8, 11, -9, -7, -6, -8, 3, -5, 9, 10, -3, 10, 0, 1, 4, -9, 4, 9, 3, 0, 4, 0, -5, 3 }, - { 9, 36, -9, -8, 7, 7, 4, 3, -1, -16, -2, 7, -5, -6, 6, 12, + { 9, 36, -9, -8, 7, 7, 4, 3, -1, -16, -2, 7, -5, -6, 6, 12, -11, -12, 9, -1, -3, -9, 12, 6, -6, 2, 2, 5, 0, 5, 6, -6 }, - { 25, 39, -5, 24, 3, 10, 3, -6, 13, -8, 3, -7, 2, -10, -5, 2, + { 25, 39, -5, 24, 3, 10, 3, -6, 13, -8, 3, -7, 2, -10, -5, 2, -2, 3, 5, -2, 1, 5, -2, 3, -4, 1, -5, -4, 0, 1, -2, 0 }, - { 16, 27, -1, 0, -14, 6, 4, -5, 7, -2, -6, 0, -3, -5, 2, -1, + { 16, 27, -1, 0, -14, 6, 4, -5, 7, -2, -6, 0, -3, -5, 2, -1, -1, -19, 5, -8, 0, 11, 12, 5, 0, 3, 10, 6, -14, 14, -13, -15 }, - { 12, 23, -14, 2, 1, 4, -3, 16, 7, -8, 2, -8, 8, 6, -8, -7, + { 12, 23, -14, 2, 1, 4, -3, 16, 7, -8, 2, -8, 8, 6, -8, -7, -3, 0, 2, 8, -13, 7, 13, -6, -4, 6, -13, -16, 14, 11, -7, 5 }, - { 16, 28, -7, -1, 6, -3, 9, 0, -7, 3, 0, 3, -12, 20, 8, 9, + { 16, 28, -7, -1, 6, -3, 9, 0, -7, 3, 0, 3, -12, 20, 8, 9, 8, 23, 8, -13, -2, 4, 9, 3, -5, 13, 5, -2, 12, 14, 5, -1 }, - { 19, 37, 19, 5, 7, 5, 10, 5, 19, 10, 14, 0, 2, 5, 1, -4, + { 19, 37, 19, 5, 7, 5, 10, 5, 19, 10, 14, 0, 2, 5, 1, -4, -4, 2, 2, -5, -2, -1, 2, -6, -4, -4, -5, -3, 2, -2, -2, -2 }, - { 24, 21, 1, -11, -10, 17, -14, 14, 6, -1, -6, -1, 0, -13, -1, -12, + { 24, 21, 1, -11, -10, 17, -14, 14, 6, -1, -6, -1, 0, -13, -1, -12, -2, -5, 6, -4, -12, 14, 5, -2, -8, -8, 15, -7, -30, -12, 4, 0 }, - { 11, 26, -3, 3, 5, -1, -2, 3, -2, 10, 15, -4, 10, -28, 10, -17, + { 11, 26, -3, 3, 5, -1, -2, 3, -2, 10, 15, -4, 10, -28, 10, -17, -8, 1, 2, -7, -1, -6, -15, -1, 4, 5, -7, 9, 0, -5, -4, 4 }, - { 18, 32, 1, 2, -7, 4, 15, 2, -9, -2, 12, -11, 7, 11, 13, 2, + { 18, 32, 1, 2, -7, 4, 15, 2, -9, -2, 12, -11, 7, 11, 13, 2, 0, 5, 9, -10, 16, 3, -3, 5, -9, -23, 2, -2, -1, 5, 2, 11 }, - { 35, 24, -20, 2, 4, -1, 5, 14, -10, -9, 8, -7, 0, 5, -7, -7, + { 35, 24, -20, 2, 4, -1, 5, 14, -10, -9, 8, -7, 0, 5, -7, -7, 11, 1, 5, 3, 2, 0, -2, 3, 0, 1, 4, 0, -2, -8, 0, -4 }, - { 9, 35, -1, 2, -1, -19, -3, 12, -1, 8, 8, -13, -1, -2, 2, 5, + { 9, 35, -1, 2, -1, -19, -3, 12, -1, 8, 8, -13, -1, -2, 2, 5, -8, -1, 13, -2, 11, 1, 0, -10, 0, -3, -7, 2, 1, -12, 3, 12 }, - { 20, 27, -12, -12, 7, 4, -1, -13, -1, -9, 2, 13, -11, 5, 7, -9, + { 20, 27, -12, -12, 7, 4, -1, -13, -1, -9, 2, 13, -11, 5, 7, -9, 9, 1, 1, 8, -9, 0, -6, 7, 4, 2, -2, 7, 3, -2, 1, -9 }, - { 8, 37, -20, -5, 0, -21, 10, -8, 3, 19, -9, 7, -3, -8, 10, -2, + { 8, 37, -20, -5, 0, -21, 10, -8, 3, 19, -9, 7, -3, -8, 10, -2, 0, 5, 6, -4, -2, -1, 0, -7, 6, 1, 0, 4, -5, 6, -8, 2 }, - { 8, 27, 1, -3, -5, 1, 6, 0, 15, 2, 17, -1, 3, -17, 10, 5, + { 8, 27, 1, -3, -5, 1, 6, 0, 15, 2, 17, -1, 3, -17, 10, 5, 5, -6, -6, 6, -10, 18, -5, 0, 0, 13, 7, 10, -5, -6, -2, -4 }, - { 14, 29, -20, -4, -3, 1, -5, -1, 2, 12, -10, -3, 4, -18, 4, 14, + { 14, 29, -20, -4, -3, 1, -5, -1, 2, 12, -10, -3, 4, -18, 4, 14, -4, -1, -9, 15, -2, 2, -5, -3, 2, 9, -2, -14, -3, 4, -4, -7 }, - { 23, 23, -23, -11, 27, 4, 4, -1, 7, 0, -5, 9, 2, -11, 3, 7, + { 23, 23, -23, -11, 27, 4, 4, -1, 7, 0, -5, 9, 2, -11, 3, 7, -2, -5, 2, -7, -7, 13, -3, -6, 2, 3, 3, -4, -1, -8, 5, -2 }, - { 16, 26, -6, 8, -9, -1, -2, -1, -8, 4, -2, 0, -12, 9, -1, 0, + { 16, 26, -6, 8, -9, -1, -2, -1, -8, 4, -2, 0, -12, 9, -1, 0, -17, -9, 30, -5, -15, -16, -13, 0, 10, -11, -7, -3, -1, 0, -11, -2 }, - { 12, 32, -4, -5, 10, 19, -10, 4, -12, 5, -6, 9, -12, -6, -6, -8, + { 12, 32, -4, -5, 10, 19, -10, 4, -12, 5, -6, 9, -12, -6, -6, -8, 4, 1, 3, 0, 8, 0, -3, -4, -7, -4, 10, 8, 6, 5, -1, 4 }, - { 46, 42, -3, -14, -2, -6, 6, -2, -5, -1, -3, -3, 1, -1, 3, 1, + { 46, 42, -3, -14, -2, -6, 6, -2, -5, -1, -3, -3, 1, -1, 3, 1, 1, 4, -1, 2, 3, 1, -2, 6, 0, -1, -2, 4, -2, -1, 2, 2 }, - { 9, 33, -13, 4, -11, 3, -8, 22, 12, -2, 4, 0, -16, 5, 4, -1, + { 9, 33, -13, 4, -11, 3, -8, 22, 12, -2, 4, 0, -16, 5, 4, -1, 7, -6, -9, 1, 7, 5, 0, -5, 5, -1, 10, 3, -2, -1, 3, -2 }, - { 9, 30, 6, -3, 6, 1, -7, 5, 11, 14, 7, 1, 0, 2, 2, -1, + { 9, 30, 6, -3, 6, 1, -7, 5, 11, 14, 7, 1, 0, 2, 2, -1, 8, 7, -6, -13, -10, -2, 1, -6, 10, 7, 6, 5, -2, -5, -1, -16 }, - { 9, 28, -11, -10, 9, -10, 15, 8, 4, 9, -4, -7, 0, -5, 9, 8, + { 9, 28, -11, -10, 9, -10, 15, 8, 4, 9, -4, -7, 0, -5, 9, 8, -7, 2, -15, -23, 4, -4, 4, 16, -8, -3, 0, -8, 14, 5, -3, 15 }, - { 17, 26, -5, -5, -1, -8, 20, 18, -7, -2, 4, -7, -8, -5, -4, 16, + { 17, 26, -5, -5, -1, -8, 20, 18, -7, -2, 4, -7, -8, -5, -4, 16, 0, 0, -7, -2, -13, -5, -2, 3, 12, 1, 3, -5, 2, 2, 0, -1 }, - { 11, 37, 7, -23, 6, -1, 15, 13, 4, -9, 7, 5, 3, -3, -5, -8, + { 11, 37, 7, -23, 6, -1, 15, 13, 4, -9, 7, 5, 3, -3, -5, -8, -2, 3, -5, -1, -8, 7, 2, 13, 1, 3, 0, -3, -1, 2, 0, -2 }, - { 21, 33, 7, 20, 21, -10, 6, -5, -5, -6, -9, 2, 10, 0, 8, -4, + { 21, 33, 7, 20, 21, -10, 6, -5, -5, -6, -9, 2, 10, 0, 8, -4, 10, 2, -2, -2, 0, -10, -6, -2, 0, -5, 3, -11, 3, -9, -3, 1 }, - { 6, 30, -15, -8, 16, 1, 4, 6, 4, 5, 8, -3, 8, -9, -1, -6, + { 6, 30, -15, -8, 16, 1, 4, 6, 4, 5, 8, -3, 8, -9, -1, -6, 8, 2, -2, 4, -2, 5, 11, -21, 3, -10, 16, -11, 24, 10, 14, -6 }, - { 15, 36, -3, -9, -20, 12, 0, -7, -18, -4, -8, -9, 9, -7, -3, -1, + { 15, 36, -3, -9, -20, 12, 0, -7, -18, -4, -8, -9, 9, -7, -3, -1, 2, 7, -5, -8, 6, 2, 2, -1, 7, 1, 1, -3, 3, -4, -8, 1 }, - { 16, 34, 21, 3, -9, 10, 7, 9, -7, 1, -4, -9, -4, -5, -5, 3, + { 16, 34, 21, 3, -9, 10, 7, 9, -7, 1, -4, -9, -4, -5, -5, 3, 3, -19, 1, 5, 4, -2, -6, -5, -10, -11, -8, -2, 2, -5, -8, -7 }, - { 28, 29, -3, 18, -2, 0, -6, 12, -2, 10, -11, -4, -13, -12, -6, -4, + { 28, 29, -3, 18, -2, 0, -6, 12, -2, 10, -11, -4, -13, -12, -6, -4, 0, 4, -1, -8, 6, 4, 12, 11, 10, 10, -3, -6, 1, 2, 1, 7 }, - { 3, 8, 22, -8, 3, 36, -8, -1, 9, 6, -13, -14, 8, -1, 1, 2, + { 3, 8, 22, -8, 3, 36, -8, -1, 9, 6, -13, -14, 8, -1, 1, 2, -2, -8, 0, 3, 1, 2, -1, 5, -1, -8, 0, -2, 2, 2, -1, 1 }, - { 0, 6, 0, 0, 4, 13, -7, -16, -6, 15, -14, -21, -9, -10, -10, -6, + { 0, 6, 0, 0, 4, 13, -7, -16, -6, 15, -14, -21, -9, -10, -10, -6, -21, 5, 4, 2, 12, 4, 12, 11, -4, -6, -6, -10, -7, -18, 1, 4 }, - { -1, 3, 10, 1, -1, 15, 4, -7, -16, 3, 0, -22, 10, 2, -3, -2, + { -1, 3, 10, 1, -1, 15, 4, -7, -16, 3, 0, -22, 10, 2, -3, -2, 13, 5, -8, 16, -5, 4, 0, -11, -10, -22, 0, -4, -17, 5, 2, 1 }, - { 12, 8, -4, -9, 14, 40, -21, 0, 1, -15, -10, -12, 12, 6, -10, 2, + { 12, 8, -4, -9, 14, 40, -21, 0, 1, -15, -10, -12, 12, 6, -10, 2, 8, 6, -12, -10, -11, 1, 0, -11, 2, 1, 13, 0, 6, 3, 8, 4 }, - { -10, 3, 5, -4, -3, 3, 0, -9, 2, 8, -22, -23, 17, 8, -17, -3, + { -10, 3, 5, -4, -3, 3, 0, -9, 2, 8, -22, -23, 17, 8, -17, -3, 14, -8, -4, 1, -8, 3, 0, 5, -1, -3, -2, -4, 1, -10, 0, -2 }, - { 0, -1, 5, -7, 4, 12, -2, 0, -7, 2, -16, -15, 12, 21, -7, -4, + { 0, -1, 5, -7, 4, 12, -2, 0, -7, 2, -16, -15, 12, 21, -7, -4, 7, -7, -11, -15, -7, -9, -5, -8, 0, -6, 8, -3, -8, 22, -7, -9 }, - { 7, 19, 4, -9, 24, 22, 2, -6, 8, 13, -14, -20, -4, 11, 8, -4, + { 7, 19, 4, -9, 24, 22, 2, -6, 8, 13, -14, -20, -4, 11, 8, -4, -1, 2, 0, -7, 5, -17, -3, 3, -6, 5, 3, 4, -5, -7, -3, 14 }, - { -2, 6, 2, 8, -2, 5, -4, -2, -10, 3, -45, -30, -3, -3, -12, -4, + { -2, 6, 2, 8, -2, 5, -4, -2, -10, 3, -45, -30, -3, -3, -12, -4, -3, -3, -1, 9, -6, -6, 5, -4, 0, 5, -1, -2, -1, 0, -6, -1 }, - { -3, 14, -16, -10, 10, 0, -2, -40, -9, 12, 2, -19, 15, -4, 4, 3, + { -3, 14, -16, -10, 10, 0, -2, -40, -9, 12, 2, -19, 15, -4, 4, 3, 3, -4, 7, 1, -4, -5, 0, 4, -1, 0, -9, -2, -4, -1, -2, 0 }, - { 7, 16, 2, -7, 8, 2, 0, 1, 5, 21, -10, -26, 7, 2, -9, -7, + { 7, 16, 2, -7, 8, 2, 0, 1, 5, 21, -10, -26, 7, 2, -9, -7, -3, -16, 8, 5, 5, -6, 10, 4, -14, -6, 5, 3, -2, -2, -4, 1 }, - { -9, 14, -1, 3, 3, 11, 1, -5, -3, 13, -16, -18, 20, 6, -5, 0, + { -9, 14, -1, 3, 3, 11, 1, -5, -3, 13, -16, -18, 20, 6, -5, 0, -3, 2, 8, 4, -19, -9, 12, 0, -8, 2, 2, 1, 6, 13, -7, -11 }, - { 2, 5, 16, -4, 19, 15, 4, 0, -11, 7, -10, -10, -16, 18, -11, -12, + { 2, 5, 16, -4, 19, 15, 4, 0, -11, 7, -10, -10, -16, 18, -11, -12, -9, -4, 7, -4, -4, -17, 1, 1, -8, -3, -3, 5, -2, -6, -11, -5 }, - { 2, 12, 0, -9, -10, 14, 6, 2, -3, 2, -12, -28, 12, 1, -1, 2, + { 2, 12, 0, -9, -10, 14, 6, 2, -3, 2, -12, -28, 12, 1, -1, 2, 0, -3, -4, 7, 16, 5, -7, 8, -4, -3, -1, 3, -12, 4, -17, -5 }, - { -4, 7, 11, 6, 1, 14, -4, -6, 5, 5, -6, -24, 23, -9, -15, 13, + { -4, 7, 11, 6, 1, 14, -4, -6, 5, 5, -6, -24, 23, -9, -15, 13, -7, -9, -15, 10, -1, 8, -5, 1, 12, 6, 2, 0, 4, -2, 9, -10 }, - { 1, 5, 11, 3, 6, 12, -3, 8, -21, 5, -7, -20, 12, -2, -9, -3, + { 1, 5, 11, 3, 6, 12, -3, 8, -21, 5, -7, -20, 12, -2, -9, -3, 17, -7, -8, -9, -14, 3, -13, 18, -8, 9, 2, -8, 4, -8, -5, -2 }, - { -3, -3, -1, 5, -2, 15, 3, 2, 1, -8, 1, -39, -6, 13, -13, 0, + { -3, -3, -1, 5, -2, 15, 3, 2, 1, -8, 1, -39, -6, 13, -13, 0, -2, -5, -6, -3, 0, -5, -2, 15, -9, 5, -3, -6, -2, 7, 0, -13 }, - { 2, 8, 5, -12, -13, 22, 8, -16, 11, 5, -2, -32, -2, -4, 11, 5, + { 2, 8, 5, -12, -13, 22, 8, -16, 11, 5, -2, -32, -2, -4, 11, 5, 5, -6, 1, 3, 1, 5, 3, 6, -5, 4, 4, -8, 8, 4, 1, 3 }, - { 13, 9, 5, -4, 9, 18, -11, 2, -1, 15, -10, -19, -2, 14, 0, -10, + { 13, 9, 5, -4, 9, 18, -11, 2, -1, 15, -10, -19, -2, 14, 0, -10, 1, 1, -18, 3, 2, -6, -8, 20, 7, -8, 16, 9, 9, -13, -3, -2 }, - { -13, 11, 11, -9, -10, 13, -3, -18, 2, 10, 5, -21, 6, 15, -11, -21, + { -13, 11, 11, -9, -10, 13, -3, -18, 2, 10, 5, -21, 6, 15, -11, -21, 3, 14, 0, -12, 9, -1, -2, -4, 3, -3, -9, -8, -5, -2, -8, 2 }, - { 3, 3, 11, 4, 0, 13, 1, -8, 10, 13, -6, -26, 2, 12, -3, -5, + { 3, 3, 11, 4, 0, 13, 1, -8, 10, 13, -6, -26, 2, 12, -3, -5, 12, -2, 1, 8, -7, -17, -19, 5, 10, 7, -3, 2, -3, 0, 5, 0 }, - { 5, 0, 3, -3, -9, 5, -15, -5, -5, 17, -5, -31, 0, 13, 13, 5, + { 5, 0, 3, -3, -9, 5, -15, -5, -5, 17, -5, -31, 0, 13, 13, 5, -1, -6, -14, 7, -8, 9, -14, -2, -16, -4, -4, -6, 6, -6, -10, 6 }, - { 13, 3, 1, 7, -3, 4, -1, -2, -1, 4, -8, -32, -1, -4, 0, 3, + { 13, 3, 1, 7, -3, 4, -1, -2, -1, 4, -8, -32, -1, -4, 0, 3, -10, 7, 10, -10, 4, -1, 6, 2, -16, -9, 4, 3, 13, -23, -3, -4 }, - { 4, 11, -4, -9, 4, 11, -12, -12, -12, 6, 1, -28, -3, 14, 18, -2, + { 4, 11, -4, -9, 4, 11, -12, -12, -12, 6, 1, -28, -3, 14, 18, -2, -12, 7, 15, -3, -5, -7, -3, 2, -6, 4, 4, -2, -5, -3, 2, -13 }, - { 8, 7, -7, 0, 13, 7, -8, -7, 8, 36, -10, -22, 3, 23, -3, -10, + { 8, 7, -7, 0, 13, 7, -8, -7, 8, 36, -10, -22, 3, 23, -3, -10, -3, 11, 1, -7, 3, 3, -1, -7, -4, 2, 3, 2, 5, 3, -4, -1 }, - { -1, 1, 13, 1, -6, -1, -6, -9, -18, 17, -5, -37, -1, -1, -6, -4, + { -1, 1, 13, 1, -6, -1, -6, -9, -18, 17, -5, -37, -1, -1, -6, -4, 1, -6, -15, 2, 17, -9, 0, -3, 0, 4, 0, -5, 0, 4, 1, -5 }, - { 0, 14, 5, 0, -7, 2, -6, 17, -6, -9, 7, -16, -5, 23, -14, -13, + { 0, 14, 5, 0, -7, 2, -6, 17, -6, -9, 7, -16, -5, 23, -14, -13, 8, -15, 11, 10, -11, -13, -33, -5, -2, 1, 6, 8, 0, -13, -9, 5 }, - { 11, 7, -2, -8, 9, 11, 25, -14, 7, 3, -1, -33, 14, 8, -6, -19, + { 11, 7, -2, -8, 9, 11, 25, -14, 7, 3, -1, -33, 14, 8, -6, -19, 3, 3, 2, -1, -3, -1, -2, -10, -3, 1, 2, 1, 4, 2, -3, 4 }, - { -2, 8, 4, -2, 9, 13, -4, -2, -15, -3, 19, -37, 9, 25, -9, 2, + { -2, 8, 4, -2, 9, 13, -4, -2, -15, -3, 19, -37, 9, 25, -9, 2, -5, -2, -2, -4, 4, 2, 2, 0, 3, 3, 3, 5, -2, -3, -4, -3 }, - { 10, 13, -1, -15, 4, 6, -18, -4, 25, 1, -23, -17, 15, 13, -8, -8, + { 10, 13, -1, -15, 4, 6, -18, -4, 25, 1, -23, -17, 15, 13, -8, -8, 7, 4, -5, 3, 6, 9, -7, 6, 0, -5, 8, 0, -6, -1, -2, -2 }, - { 1, 3, 9, -5, 27, 15, -9, -31, -1, 23, -2, -9, 1, 8, -1, -7, + { 1, 3, 9, -5, 27, 15, -9, -31, -1, 23, -2, -9, 1, 8, -1, -7, -2, -8, -4, -4, -2, -1, 3, 5, 0, 0, -1, 1, -7, 7, -3, -3 }, - { -8, 7, 3, -6, 8, 3, -11, -2, 36, 14, 1, -30, 6, 10, -12, -6, + { -8, 7, 3, -6, 8, 3, -11, -2, 36, 14, 1, -30, 6, 10, -12, -6, -6, -2, -4, -3, -5, 0, 9, 4, -5, -5, -8, 12, 4, -3, 1, -8 }, - { -2, 9, 33, 0, 12, -3, -7, -4, -4, -1, 6, -25, 11, -6, -9, -11, + { -2, 9, 33, 0, 12, -3, -7, -4, -4, -1, 6, -25, 11, -6, -9, -11, -2, -4, -2, 6, -1, -3, -6, 15, -6, 3, 10, -4, 1, 0, 5, 8 }, - { -22, -21, -9, -19, -5, -7, -12, -15, -8, 9, -19, 14, -7, -4, 5, -8, + { -22, -21, -9, -19, -5, -7, -12, -15, -8, 9, -19, 14, -7, -4, 5, -8, -2, 7, 1, -3, 4, -4, 6, 11, 2, 6, -3, -5, 2, -2, 0, -3 }, - { -32, -13, 3, -24, 3, -8, 4, 1, -10, 14, -15, 0, 4, 6, -1, 6, + { -32, -13, 3, -24, 3, -8, 4, 1, -10, 14, -15, 0, 4, 6, -1, 6, 7, -1, 6, 4, -3, -17, 1, 4, -6, -1, 1, 0, 3, 3, -7, -4 }, - { -32, -11, 7, -8, -12, 13, -5, -22, -4, 12, -16, 2, 0, 4, 0, 1, + { -32, -11, 7, -8, -12, 13, -5, -22, -4, 12, -16, 2, 0, 4, 0, 1, 0, 6, -5, -8, 2, 6, 5, 0, -3, -6, 5, 6, 5, 5, 13, -4 }, - { -44, -33, 6, -4, 2, 0, -9, 10, 3, 4, 7, 0, -1, 7, 5, 1, + { -44, -33, 6, -4, 2, 0, -9, 10, 3, 4, 7, 0, -1, 7, 5, 1, 1, -3, 1, 6, -1, 0, 2, 3, -4, 0, 0, 1, 0, -1, -2, -1 }, - { -30, -18, -24, -8, 5, 0, -2, 14, 7, 0, 1, 12, 6, 4, -9, 7, + { -30, -18, -24, -8, 5, 0, -2, 14, 7, 0, 1, 12, 6, 4, -9, 7, 5, 7, -11, -5, 1, -8, -1, 2, 2, -9, 7, -1, 7, 5, 6, 6 }, - { -22, -20, -13, -9, 20, -3, 10, -8, 6, -4, 2, -7, 10, 8, 0, -1, + { -22, -20, -13, -9, 20, -3, 10, -8, 6, -4, 2, -7, 10, 8, 0, -1, 2, -3, 6, -19, 2, 4, 3, 3, -7, 2, -1, -6, 1, 1, 6, -2 }, - { -27, -8, -1, 3, -1, -11, 24, 4, -1, 1, -8, 8, 5, -11, 15, -3, + { -27, -8, -1, 3, -1, -11, 24, 4, -1, 1, -8, 8, 5, -11, 15, -3, -15, -1, -1, -13, -1, 1, -5, 5, 2, 3, -9, 0, 4, 3, -7, 6 }, - { -33, -16, -1, -8, 10, -23, 6, 13, -1, -3, -9, 0, 5, -7, -5, -12, + { -33, -16, -1, -8, 10, -23, 6, 13, -1, -3, -9, 0, 5, -7, -5, -12, -2, 3, 3, 6, -2, -3, 2, -3, 9, -6, -3, -2, 0, 5, -3, -4 }, - { -22, -17, 11, -3, 3, 1, -1, -5, 17, 2, -15, -2, 10, -9, 6, 14, + { -22, -17, 11, -3, 3, 1, -1, -5, 17, 2, -15, -2, 10, -9, 6, 14, -16, -12, 20, -1, -7, 6, -3, -12, 1, 10, -10, -1, 7, -3, -1, 10 }, - { -28, -13, 1, -3, -1, -1, 0, 3, 3, 5, 1, 10, -10, -3, 7, 2, + { -28, -13, 1, -3, -1, -1, 0, 3, 3, 5, 1, 10, -10, -3, 7, 2, 4, 19, -1, -1, 10, 5, -8, 1, 11, -15, -4, -3, -5, 4, -13, 3 }, - { -22, -13, 42, -20, 5, -13, 7, -11, 1, 1, -1, 1, 6, 3, 6, -11, + { -22, -13, 42, -20, 5, -13, 7, -11, 1, 1, -1, 1, 6, 3, 6, -11, 3, 3, -2, 0, -4, 4, -3, -1, -5, 2, 0, 0, -9, -1, 4, 4 }, - { -26, -15, -2, -6, -4, -2, 16, 8, 21, 8, 1, -3, -10, 7, -8, -12, + { -26, -15, -2, -6, -4, -2, 16, 8, 21, 8, 1, -3, -10, 7, -8, -12, -5, 12, -9, 3, -2, -3, 18, 1, -12, -15, -4, 5, -3, 0, 12, 7 }, - { -26, -16, 5, 6, 14, -3, 15, 6, 1, -7, -13, 16, -15, 5, 11, -2, + { -26, -16, 5, 6, 14, -3, 15, 6, 1, -7, -13, 16, -15, 5, 11, -2, 9, -7, -4, -2, 0, 0, -2, 7, -8, -6, -5, 2, 7, -3, 2, 12 }, - { -31, -17, -8, -30, 4, 14, 6, -6, 6, -11, 0, 3, -4, 0, 0, -4, + { -31, -17, -8, -30, 4, 14, 6, -6, 6, -11, 0, 3, -4, 0, 0, -4, 0, -4, 1, 4, 3, 4, 0, -5, 3, 2, 2, 0, 2, 1, 3, 5 }, - { -61, -10, 4, 10, 4, 7, 0, -3, 0, 1, 0, -3, 0, 1, 0, -2, + { -61, -10, 4, 10, 4, 7, 0, -3, 0, 1, 0, -3, 0, 1, 0, -2, -1, 1, 2, -2, 4, -3, 1, 1, -1, 1, -2, -4, -4, 4, 0, 0 }, - { -28, -13, -8, -4, 3, -3, 2, 1, 11, 14, 3, 9, 1, 13, 3, 5, + { -28, -13, -8, -4, 3, -3, 2, 1, 11, 14, 3, 9, 1, 13, 3, 5, -3, -2, -2, -12, -14, -9, -11, -15, -12, -5, -4, -12, 3, -3, 0, -5 }, - { -41, 0, 12, -24, 13, 4, 5, 16, -5, -4, 0, 0, 13, -4, 1, -9, + { -41, 0, 12, -24, 13, 4, 5, 16, -5, -4, 0, 0, 13, -4, 1, -9, 9, -6, -1, 6, -2, 5, 2, 9, 6, -9, -8, 8, -2, -3, -6, -4 }, - { -26, -19, -2, -15, 4, -14, 6, 0, 26, 20, 8, 9, 9, 3, -4, -5, + { -26, -19, -2, -15, 4, -14, 6, 0, 26, 20, 8, 9, 9, 3, -4, -5, -8, 1, 0, -1, 5, 9, 3, 4, 4, 7, 1, 3, -2, -2, -10, 0 }, - { -29, -18, 9, -4, 1, -5, -14, -12, 5, -10, -5, 4, -5, 0, -1, -1, + { -29, -18, 9, -4, 1, -5, -14, -12, 5, -10, -5, 4, -5, 0, -1, -1, 4, -5, 7, -16, -11, 2, 7, -15, 2, -4, 6, -4, -6, 7, -3, 7 }, - { -27, -16, 9, -14, 3, -8, 9, 0, 7, -4, -3, -7, 0, -10, -1, 2, + { -27, -16, 9, -14, 3, -8, 9, 0, 7, -4, -3, -7, 0, -10, -1, 2, 1, -2, 15, -10, 14, 7, 6, 17, 3, -4, 3, -10, 8, -8, 3, 11 }, - { -21, -20, -8, -8, 4, 5, -3, -2, 0, -5, 14, -10, 11, -4, 13, 0, + { -21, -20, -8, -8, 4, 5, -3, -2, 0, -5, 14, -10, 11, -4, 13, 0, 5, -11, 19, -18, 18, 3, -5, -3, -4, -8, 11, -10, 10, 3, 4, -9 }, - { -35, -15, 13, -12, 4, 0, -2, -4, -12, -3, -8, -24, -7, 1, 7, 8, + { -35, -15, 13, -12, 4, 0, -2, -4, -12, -3, -8, -24, -7, 1, 7, 8, -3, 0, -2, -1, 3, -2, -2, -6, 8, 1, 0, 1, -6, -1, 2, -6 }, - { -19, -14, 13, -10, 9, -1, 1, 3, -12, 5, -16, 7, 13, 9, 4, -4, + { -19, -14, 13, -10, 9, -1, 1, 3, -12, 5, -16, 7, 13, 9, 4, -4, 6, -5, 4, 9, -3, 17, -4, 12, -11, -6, -5, -6, 13, 2, 7, -9 }, - { -34, -8, -4, 1, 2, -1, 3, 6, -20, -11, 8, -1, 4, 2, -9, 4, + { -34, -8, -4, 1, 2, -1, 3, 6, -20, -11, 8, -1, 4, 2, -9, 4, -4, -5, 16, 10, -4, 14, -13, 1, -6, 0, 2, -10, 0, -3, -3, 7 }, - { -36, -10, -8, -3, 2, -2, 14, -4, -1, -7, -4, 10, -1, -3, 15, -11, + { -36, -10, -8, -3, 2, -2, 14, -4, -1, -7, -4, 10, -1, -3, 15, -11, 0, 2, 3, -1, 4, 0, 8, -1, 0, 18, -11, -5, 15, -5, 13, -12 }, - { -22, -13, 14, -20, 15, 25, 16, 10, 8, -2, -10, -5, -1, -8, 11, 8, + { -22, -13, 14, -20, 15, 25, 16, 10, 8, -2, -10, -5, -1, -8, 11, 8, -1, -2, -4, 1, 2, -1, -7, 0, 0, 0, -3, 0, 2, -1, 0, 2 }, - { -31, -22, 7, 6, -2, 5, -20, 14, -6, 7, 0, 14, 3, -7, 3, -6, + { -31, -22, 7, 6, -2, 5, -20, 14, -6, 7, 0, 14, 3, -7, 3, -6, -2, 1, -3, -5, 1, -10, 1, -24, 6, -2, 3, -7, 1, -7, 8, 7 }, - { -25, -20, -3, -9, 10, 6, 12, 7, 5, 4, -3, 6, -1, -5, -6, -8, + { -25, -20, -3, -9, 10, 6, 12, 7, 5, 4, -3, 6, -1, -5, -6, -8, 3, 5, 6, 5, -10, 10, -4, -15, -15, -2, -9, 2, 18, 1, 8, 12 }, - { -24, -19, -2, -4, -7, 11, 6, 9, 16, 2, -7, 18, 6, -7, 6, 6, + { -24, -19, -2, -4, -7, 11, 6, 9, 16, 2, -7, 18, 6, -7, 6, 6, -2, -9, 3, 12, -2, 3, -1, 6, 7, 8, 0, 8, -11, 8, 4, 2 }, - { -26, -20, -12, -12, -2, -3, 1, -5, -1, -2, 0, 3, 7, 9, -2, 2, + { -26, -20, -12, -12, -2, -3, 1, -5, -1, -2, 0, 3, 7, 9, -2, 2, 9, 22, 13, 4, -4, -1, -2, -14, 5, 15, -8, -5, -7, -11, -14, -6 }, - { -21, -18, -1, -4, 0, 3, 7, -2, 10, 8, -8, -1, 15, 1, -9, 3, + { -21, -18, -1, -4, 0, 3, 7, -2, 10, 8, -8, -1, 15, 1, -9, 3, 1, 3, -5, -2, 2, 4, 0, -1, 10, 2, -19, -8, 8, 30, -7, 8 }, - { -25, -6, 26, 4, -8, 4, -2, 21, 5, -4, -16, 5, 13, 4, -10, -1, + { -25, -6, 26, 4, -8, 4, -2, 21, 5, -4, -16, 5, 13, 4, -10, -1, -6, -2, 2, -10, -13, 1, 3, -3, -6, -8, 2, 11, 1, -7, 0, 5 }, - { 0, -1, -2, 19, -12, -48, -6, 11, 8, -2, -4, -2, -7, 5, -3, 2, + { 0, -1, -2, 19, -12, -48, -6, 11, 8, -2, -4, -2, -7, 5, -3, 2, -2, -1, -1, -7, 0, -3, -3, -4, -4, 4, 1, 3, -3, -1, -2, -5 }, - { -11, -8, -28, 18, 16, -24, -8, 19, 4, 8, -12, 9, -4, -2, 4, -7, + { -11, -8, -28, 18, 16, -24, -8, 19, 4, 8, -12, 9, -4, -2, 4, -7, 6, 2, 3, 3, -4, 0, 1, -6, -4, -2, 2, 6, 0, -3, 1, -16 }, - { -9, -5, -26, 7, -3, -37, -16, -2, 2, -7, 4, -13, 0, -4, -6, -5, + { -9, -5, -26, 7, -3, -37, -16, -2, 2, -7, 4, -13, 0, -4, -6, -5, -6, -4, 0, 3, 4, -3, -4, -4, 4, -3, 9, -4, -2, 2, 7, -4 }, - { 2, 9, -18, 7, 29, -24, -1, 7, 14, 10, 3, -3, -2, -5, 6, -10, + { 2, 9, -18, 7, 29, -24, -1, 7, 14, 10, 3, -3, -2, -5, 6, -10, -6, -3, -8, 0, 5, 1, 4, 3, -12, 2, 6, 1, 3, 4, 1, -3 }, - { -20, 2, 8, 20, -9, -24, -4, 18, 3, 11, -1, -11, 6, 9, -1, -3, + { -20, 2, 8, 20, -9, -24, -4, 18, 3, 11, -1, -11, 6, 9, -1, -3, 1, -1, -15, 3, 15, 9, 3, 2, -13, 2, -8, 8, 1, -1, 1, -8 }, - { -12, 5, -11, 6, 19, -26, -17, -6, 4, 14, 6, -8, 9, 5, -6, -5, + { -12, 5, -11, 6, 19, -26, -17, -6, 4, 14, 6, -8, 9, 5, -6, -5, 2, -1, 20, 1, -11, -10, -18, 20, -7, 0, -3, 4, 2, 0, 10, 4 }, - { -15, 1, -2, 13, -8, -21, -22, 4, 4, 3, 3, -7, -31, 4, -10, -14, + { -15, 1, -2, 13, -8, -21, -22, 4, 4, 3, 3, -7, -31, 4, -10, -14, 0, 8, 4, 5, 8, 11, 2, -8, 6, 7, 0, -2, 6, 8, 8, 7 }, - { -13, -10, -9, 12, 19, -16, -3, -2, 9, 2, 11, -29, -1, 9, 4, -3, + { -13, -10, -9, 12, 19, -16, -3, -2, 9, 2, 11, -29, -1, 9, 4, -3, 1, -10, -10, 16, 1, 7, -7, -6, -4, -1, -5, 3, 6, 0, 3, 1 }, - { -17, -1, -5, 19, 12, -9, -21, -5, 2, 12, -7, -7, -3, 8, 7, -2, + { -17, -1, -5, 19, 12, -9, -21, -5, 2, 12, -7, -7, -3, 8, 7, -2, 6, -9, -9, 1, -4, 1, 1, 3, -14, 2, -8, 0, 10, 1, -12, -6 }, - { -13, -5, 8, 15, 0, -20, -2, 20, 8, -8, 8, -19, 12, 10, 2, -11, + { -13, -5, 8, 15, 0, -20, -2, 20, 8, -8, 8, -19, 12, 10, 2, -11, 0, 12, 1, -11, 0, -11, -15, 5, -11, 2, 4, -4, -11, 5, -4, -5 }, - { 3, -11, -7, 8, 0, -17, -26, 15, 19, -7, 10, -9, -5, -5, 14, -25, + { 3, -11, -7, 8, 0, -17, -26, 15, 19, -7, 10, -9, -5, -5, 14, -25, 0, -8, 2, -9, -3, 9, 1, -6, 4, -4, 3, -9, -1, 6, 2, 2 }, - { -12, 5, 5, 9, 14, -18, -19, 4, 2, 16, 14, -21, -15, -9, -1, 16, + { -12, 5, 5, 9, 14, -18, -19, 4, 2, 16, 14, -21, -15, -9, -1, 16, 12, -11, -10, -5, -7, 4, 15, -8, -5, -1, 1, 14, 13, -7, -1, -4 }, - { -10, -5, -1, 8, 7, -23, -10, 14, 6, 11, 10, -16, -3, 16, 6, 0, + { -10, -5, -1, 8, 7, -23, -10, 14, 6, 11, 10, -16, -3, 16, 6, 0, 0, 9, 6, -2, -7, 1, 22, 5, 3, -8, 0, 3, -2, -10, 3, 0 }, - { -2, -14, 2, 16, 15, -17, -17, 6, 19, 4, -10, -15, -1, 15, 11, -14, + { -2, -14, 2, 16, 15, -17, -17, 6, 19, 4, -10, -15, -1, 15, 11, -14, -8, 5, 8, 8, -2, -8, -11, 10, 10, -8, -14, 2, 13, 4, -2, -12 }, - { -10, 3, 6, 4, 19, -23, -19, 1, 4, -9, -30, 3, -6, 18, 0, 2, + { -10, 3, 6, 4, 19, -23, -19, 1, 4, -9, -30, 3, -6, 18, 0, 2, 0, -11, 0, 3, 7, -2, 8, 5, 2, -3, 6, -9, 1, -4, 7, -6 }, - { 9, 5, -2, 21, 20, -33, -13, 7, -10, 8, 8, -15, -6, -4, 1, 5, + { 9, 5, -2, 21, 20, -33, -13, 7, -10, 8, 8, -15, -6, -4, 1, 5, 3, 7, -2, -9, -1, 4, -6, 1, 0, 9, -1, -5, 2, 1, -3, 3 }, - { -9, -3, 3, 15, -3, -30, -7, -7, -25, 6, 2, -6, 1, 19, 1, -12, + { -9, -3, 3, 15, -3, -30, -7, -7, -25, 6, 2, -6, 1, 19, 1, -12, 1, -8, -13, 9, 13, 1, 8, 2, 5, 15, -2, 3, -9, 0, -4, 4 }, - { -6, -12, -17, 25, 22, -13, -10, 9, 2, 11, -7, -16, 4, 6, 1, 0, + { -6, -12, -17, 25, 22, -13, -10, 9, 2, 11, -7, -16, 4, 6, 1, 0, 0, 18, -4, -5, 4, -2, -1, -5, 0, -4, 6, 1, 6, -1, 7, 0 }, - { -1, 0, -10, 8, 8, -27, 0, -2, 29, 16, -2, -4, 9, -1, 2, 0, + { -1, 0, -10, 8, 8, -27, 0, -2, 29, 16, -2, -4, 9, -1, 2, 0, 6, 10, 6, 4, 2, -7, 9, -18, 3, 3, 3, -10, 17, 10, 9, -6 }, - { -3, -12, -6, 11, 20, -32, 5, 21, 3, -4, -9, 2, -10, 1, 7, -4, + { -3, -12, -6, 11, 20, -32, 5, 21, 3, -4, -9, 2, -10, 1, 7, -4, 5, 0, 0, -1, -8, -9, -7, 4, -10, 5, 0, 2, -5, 4, 9, 1 }, - { -5, -1, -5, 1, 2, -19, -13, 1, 6, 12, 2, -16, -17, 11, 10, 13, + { -5, -1, -5, 1, 2, -19, -13, 1, 6, 12, 2, -16, -17, 11, 10, 13, 16, -12, -11, 3, -6, 0, 6, 4, -3, 1, 8, 2, 5, -11, 3, -14 }, - { -19, 5, 10, 11, 2, -23, -9, 16, -2, 7, 0, -11, -7, 10, 6, -7, + { -19, 5, 10, 11, 2, -23, -9, 16, -2, 7, 0, -11, -7, 10, 6, -7, 26, -15, -4, 8, 6, -4, 7, -9, -15, 1, 8, -4, 4, 2, -12, 16 }, - { -11, 1, 11, -4, 1, -31, -13, -1, 8, 5, 4, -2, 0, 13, 7, -17, + { -11, 1, 11, -4, 1, -31, -13, -1, 8, 5, 4, -2, 0, 13, 7, -17, 7, -10, -6, 1, 4, -1, 2, -9, -4, 9, 3, 3, -4, -5, 3, 4 }, - { -3, 1, 10, -1, 0, -15, -22, 4, 40, -11, -4, -3, -14, 9, 11, -1, + { -3, 1, 10, -1, 0, -15, -22, 4, 40, -11, -4, -3, -14, 9, 11, -1, 9, -1, -6, 6, 3, -6, 0, 0, -12, 7, -2, 0, 9, 3, 1, 3 }, - { -1, -1, -1, 14, 8, -24, -14, -8, 5, 8, 5, -12, -17, 8, 2, 7, + { -1, -1, -1, 14, 8, -24, -14, -8, 5, 8, 5, -12, -17, 8, 2, 7, 10, -8, 0, 4, -6, -6, -10, 8, 4, -12, 3, -9, -12, 5, 4, -3 }, - { -5, 1, -11, 8, 9, -24, 0, 2, 2, 14, -12, -13, 1, 6, 7, 0, + { -5, 1, -11, 8, 9, -24, 0, 2, 2, 14, -12, -13, 1, 6, 7, 0, 7, -6, 9, 26, 11, -14, 8, 10, 1, 9, 0, 11, -2, 6, 2, -10 }, - { -13, 1, 4, 34, 19, -17, -15, 0, 3, -2, -7, -1, 0, -3, -3, -1, + { -13, 1, 4, 34, 19, -17, -15, 0, 3, -2, -7, -1, 0, -3, -3, -1, 1, -1, -10, 8, 5, 0, -8, 4, -17, 9, -2, 0, 0, 6, 2, -3 }, - { -6, -4, 1, 2, 2, -14, -29, 0, 9, 34, -3, -5, -14, 6, -10, -9, + { -6, -4, 1, 2, 2, -14, -29, 0, 9, 34, -3, -5, -14, 6, -10, -9, -5, -1, 0, 3, 3, 0, 1, -1, -2, -1, -1, -3, -3, -4, 3, -3 }, - { -4, 6, 3, 14, 14, -8, -29, 31, 11, 14, -4, -5, -6, 10, 6, -9, + { -4, 6, 3, 14, 14, -8, -29, 31, 11, 14, -4, -5, -6, 10, 6, -9, -1, -11, -7, 1, 7, 4, 1, -6, 4, 0, 10, -7, -5, -1, 2, 4 }, - { -4, -4, -2, 14, 6, -32, -6, -14, 14, -5, -11, 10, -18, -4, 6, -8, + { -4, -4, -2, 14, 6, -32, -6, -14, 14, -5, -11, 10, -18, -4, 6, -8, 9, 5, -4, 1, -4, 5, -2, -9, 3, 5, 2, -10, -6, -17, 3, 17 }, - { -16, 9, 21, 19, 4, -20, -17, 14, 9, 15, -6, -17, -1, 1, 6, -3, + { -16, 9, 21, 19, 4, -20, -17, 14, 9, 15, -6, -17, -1, 1, 6, -3, 1, 1, 8, -3, -6, 6, 9, 4, 9, -9, -5, 1, -1, 0, -1, 2 }, - { -7, -5, 3, 19, 1, -20, -9, 14, 21, -7, -18, -9, 26, -7, -17, -7, + { -7, -5, 3, 19, 1, -20, -9, 14, 21, -7, -18, -9, 26, -7, -17, -7, 12, 6, 0, -9, -6, 14, 9, -9, -8, 4, 15, -7, -9, -1, 9, 1 }, - { -20, 30, -6, 11, 24, -4, 0, -6, -2, 8, -4, 12, -8, -17, 0, 5, + { -20, 30, -6, 11, 24, -4, 0, -6, -2, 8, -4, 12, -8, -17, 0, 5, -4, 1, -1, 3, -3, 5, 3, 3, 7, -2, -3, -2, 4, 0, 0, -1 }, - { -35, 17, 6, 1, -9, -1, -16, 3, -20, -13, 8, 7, -4, -7, -4, -20, + { -35, 17, 6, 1, -9, -1, -16, 3, -20, -13, 8, 7, -4, -7, -4, -20, 7, 12, -5, 5, -5, -11, 12, -1, 15, -9, -6, 16, -4, -9, -13, 4 }, - { -21, 36, -19, 9, 0, -7, -8, 9, -4, -3, 3, 0, 7, -8, -2, -2, + { -21, 36, -19, 9, 0, -7, -8, 9, -4, -3, 3, 0, 7, -8, -2, -2, -11, 13, -1, 5, -3, 7, 2, 3, -1, -2, -5, 1, -1, -2, -5, -3 }, - { -12, 33, -4, 1, -12, -9, 0, -13, -1, 2, -8, 4, -10, 6, -16, -7, + { -12, 33, -4, 1, -12, -9, 0, -13, -1, 2, -8, 4, -10, 6, -16, -7, -1, -4, -10, 15, -1, 0, -5, -8, 5, 5, -3, 0, 2, -7, 1, -7 }, - { -14, 32, 5, -7, -15, 3, -5, 8, 14, 5, 9, 13, 3, 18, -3, 7, + { -14, 32, 5, -7, -15, 3, -5, 8, 14, 5, 9, 13, 3, 18, -3, 7, 4, -10, -10, 10, -1, 2, 0, -2, -11, 5, -3, -4, 2, 2, 7, 4 }, - { -14, 34, 1, 20, -1, -12, 0, -3, -7, -4, 7, 18, 9, -3, 14, -7, + { -14, 34, 1, 20, -1, -12, 0, -3, -7, -4, 7, 18, 9, -3, 14, -7, -9, -20, -7, -4, -13, 12, 1, 12, 5, -6, 2, -4, 0, -15, 1, 3 }, - { -21, 23, 7, -8, 3, -13, -3, 0, -6, -2, -7, 6, -12, 9, -6, -2, + { -21, 23, 7, -8, 3, -13, -3, 0, -6, -2, -7, 6, -12, 9, -6, -2, -2, -4, -1, 6, 9, 5, -9, 15, 0, 8, -8, 7, 6, -15, 3, -5 }, - { -27, 32, -1, -4, -2, 4, -10, 12, -3, 8, 13, 7, 0, -15, 4, -2, + { -27, 32, -1, -4, -2, 4, -10, 12, -3, 8, 13, 7, 0, -15, 4, -2, 3, 5, 7, -4, 9, -12, -1, -2, -1, -4, 0, -4, 2, -5, 6, -6 }, - { -17, 29, 15, 0, -1, -4, -10, 13, 12, -1, -8, -10, -10, 4, 7, -2, + { -17, 29, 15, 0, -1, -4, -10, 13, 12, -1, -8, -10, -10, 4, 7, -2, 6, -5, -13, 19, 6, 1, -7, 2, -9, -2, 12, -4, -8, -3, 2, 4 }, - { -38, 27, 16, -15, -6, 3, -7, -4, 0, -1, 6, -2, -3, -6, 6, -6, + { -38, 27, 16, -15, -6, 3, -7, -4, 0, -1, 6, -2, -3, -6, 6, -6, -3, 0, 2, 0, -4, 6, 1, -1, 0, 4, -1, 3, 4, 1, -2, 5 }, - { -33, 40, -4, 2, 1, 0, 0, -10, -14, 0, -7, 4, -1, 3, -2, 5, + { -33, 40, -4, 2, 1, 0, 0, -10, -14, 0, -7, 4, -1, 3, -2, 5, 7, 6, -1, 4, 1, 3, 1, -7, 1, -4, 5, 7, 0, 4, 3, -4 }, - { -20, 25, 12, -4, 16, -4, 2, 2, -14, -2, -3, 29, -1, 1, 3, 1, + { -20, 25, 12, -4, 16, -4, 2, 2, -14, -2, -3, 29, -1, 1, 3, 1, 9, -5, 2, -8, -3, 1, -7, -2, -7, 1, 0, 4, 16, -2, -1, -1 }, - { -10, 30, 17, 3, -5, -2, 0, -5, -22, 4, 5, 5, -3, -18, -6, 10, + { -10, 30, 17, 3, -5, -2, 0, -5, -22, 4, 5, 5, -3, -18, -6, 10, -5, -7, 2, 8, 7, -7, -11, -2, 0, -3, 3, 2, 11, -4, 4, -4 }, - { -11, 30, 11, 4, -3, -8, 1, -2, 4, 18, 3, 1, -1, 0, -8, -4, + { -11, 30, 11, 4, -3, -8, 1, -2, 4, 18, 3, 1, -1, 0, -8, -4, -3, 10, 13, 14, 5, -5, 1, 1, -10, 2, 15, 4, 9, -1, -5, -3 }, - { -17, 32, 18, -18, -3, -5, 6, 10, 1, -15, -5, 9, 8, -12, -10, -6, + { -17, 32, 18, -18, -3, -5, 6, 10, 1, -15, -5, 9, 8, -12, -10, -6, 11, 9, -5, -8, -7, 10, 5, -10, -14, -4, -3, 1, 9, -11, 2, 1 }, - { -13, 28, -11, -1, 2, -16, -2, 7, -24, 0, 3, 6, 3, -1, -8, -7, + { -13, 28, -11, -1, 2, -16, -2, 7, -24, 0, 3, 6, 3, -1, -8, -7, -12, 2, 2, -20, 10, 4, 0, -13, -2, -2, 1, 8, -14, 0, 4, 1 }, - { -14, 23, 12, 8, 8, -26, 2, -4, -14, 13, -14, 15, 3, -9, -1, -13, + { -14, 23, 12, 8, 8, -26, 2, -4, -14, 13, -14, 15, 3, -9, -1, -13, -10, -2, -10, 6, -16, 12, 8, 0, 9, -10, -7, -4, -4, 7, -8, 8 }, - { -20, 45, 10, -14, 4, 16, 8, -9, 1, -8, 10, 5, -7, -2, 2, -5, + { -20, 45, 10, -14, 4, 16, 8, -9, 1, -8, 10, 5, -7, -2, 2, -5, -1, 0, -5, 4, -6, -2, 4, 1, 3, 4, -4, 2, -2, -2, 5, 1 }, - { -20, 26, -4, 1, 7, 4, -8, 1, -5, -13, 2, 13, -7, -3, 6, -6, + { -20, 26, -4, 1, 7, 4, -8, 1, -5, -13, 2, 13, -7, -3, 6, -6, 22, 0, 5, 11, -4, -11, 8, -9, 2, -2, -4, -2, 2, -13, -4, -8 }, - { -28, 18, 17, 3, -8, -23, -16, -6, 5, -10, 14, 10, 5, -1, -8, 4, + { -28, 18, 17, 3, -8, -23, -16, -6, 5, -10, 14, 10, 5, -1, -8, 4, -2, 13, -3, -2, 3, 4, 3, -2, -3, -4, 0, 1, 3, 4, 0, 4 }, - { -12, 32, -6, -16, 18, 12, -16, 0, 7, 13, -4, 5, -8, -1, -3, 4, + { -12, 32, -6, -16, 18, 12, -16, 0, 7, 13, -4, 5, -8, -1, -3, 4, 6, -2, -1, -13, 4, -1, 3, 12, -3, -10, 1, 6, 8, -11, -2, 4 }, - { -18, 26, 2, 5, 0, -9, -17, 14, 5, 1, 7, -3, -8, -3, 11, 7, + { -18, 26, 2, 5, 0, -9, -17, 14, 5, 1, 7, -3, -8, -3, 11, 7, -5, -12, -8, 7, 0, -7, 2, -12, -9, 13, -11, 9, 6, -11, -5, 11 }, - { -24, 22, -15, -9, 8, 1, -7, -12, -9, 3, 11, 15, 14, -11, 12, -15, + { -24, 22, -15, -9, 8, 1, -7, -12, -9, 3, 11, 15, 14, -11, 12, -15, -5, 7, -2, 0, -8, 3, 3, -1, 2, 11, -11, 14, -6, 13, 1, -6 }, - { -20, 28, 18, -4, -6, -5, 12, 14, 2, 10, -13, -6, -8, -6, -13, -1, + { -20, 28, 18, -4, -6, -5, 12, 14, 2, 10, -13, -6, -8, -6, -13, -1, -26, 22, -3, -14, 6, 0, 10, -15, -13, -9, 6, -7, 1, -5, -4, -1 }, - { -19, 26, -8, -3, -14, -6, -9, -4, -8, 15, -8, 3, -12, -4, -2, -7, + { -19, 26, -8, -3, -14, -6, -9, -4, -8, 15, -8, 3, -12, -4, -2, -7, -5, 3, 13, -3, -4, -25, 4, -1, 5, -12, -1, -13, 5, 2, 0, 6 }, - { -18, 43, 14, -8, 1, -23, -2, -2, 1, 3, -7, 0, 0, 8, -1, -3, + { -18, 43, 14, -8, 1, -23, -2, -2, 1, 3, -7, 0, 0, 8, -1, -3, -5, 1, 5, 2, 0, -2, -2, -2, 1, -1, -1, -7, 0, 3, -3, 9 }, - { -11, 30, 10, -14, 3, 1, 10, -11, 1, -7, -4, 14, 2, 1, -9, 1, + { -11, 30, 10, -14, 3, 1, 10, -11, 1, -7, -4, 14, 2, 1, -9, 1, -11, -2, -7, 5, -11, 1, 3, 14, 1, -16, -8, 3, -5, 7, -4, 4 }, - { -18, 24, 6, 3, 8, 7, -22, -7, -7, 3, -8, 4, 23, 9, 3, -1, + { -18, 24, 6, 3, 8, 7, -22, -7, -7, 3, -8, 4, 23, 9, 3, -1, 3, 6, 7, -1, -7, 6, 4, 1, -3, 1, -6, -1, 2, -7, 3, 3 }, - { -15, 38, -7, -1, -11, 2, -17, -24, 24, 8, 7, -4, -5, 2, 2, -7, + { -15, 38, -7, -1, -11, 2, -17, -24, 24, 8, 7, -4, -5, 2, 2, -7, 1, 4, 0, -9, 5, 0, -1, 1, -1, -5, -6, 3, 0, 7, 8, -3 }, - { -14, 22, 1, -5, 9, -12, -9, -5, -6, 5, 7, 8, -1, -4, -9, -3, + { -14, 22, 1, -5, 9, -12, -9, -5, -6, 5, 7, 8, -1, -4, -9, -3, -33, -16, -9, -1, 12, -11, 17, -7, -3, -1, -7, 3, 2, -3, 16, -4 }, - { -14, 20, 6, 4, -10, -4, -4, -4, 1, -7, 2, 6, 8, -12, 4, 1, + { -14, 20, 6, 4, -10, -4, -4, -4, 1, -7, 2, 6, 8, -12, 4, 1, -1, 12, 10, 3, -14, -10, -3, 18, -2, 33, -5, -17, 17, -5, 9, 7 }, - { -12, 23, 13, 0, -11, -8, -11, 12, -5, -9, -16, 11, 6, 4, 12, -5, + { -12, 23, 13, 0, -11, -8, -11, 12, -5, -9, -16, 11, 6, 4, 12, -5, 5, -13, 7, -12, -3, 1, 2, 12, 1, -4, -1, 5, 4, 11, -12, -3 }, - { 15, 2, 14, 7, 1, 2, 1, 12, 10, 23, 4, 6, -20, -10, 4, 26, + { 15, 2, 14, 7, 1, 2, 1, 12, 10, 23, 4, 6, -20, -10, 4, 26, -6, 13, 4, 3, 2, -11, 5, -7, -10, 4, 9, 1, 10, -4, 11, 4 }, - { 17, 15, 31, 17, 18, 16, 11, 24, 2, 4, 2, 3, -8, -3, 7, -3, + { 17, 15, 31, 17, 18, 16, 11, 24, 2, 4, 2, 3, -8, -3, 7, -3, -5, -7, -2, -6, -4, -5, -4, -1, -4, -2, -5, -6, 2, -1, 4, -2 }, - { 16, 8, 15, 14, 3, 7, 21, 9, 8, 15, 21, 6, 8, 12, 5, -5, + { 16, 8, 15, 14, 3, 7, 21, 9, 8, 15, 21, 6, 8, 12, 5, -5, 7, -3, 10, 2, -3, 8, 6, 0, 5, 5, 6, -3, 2, 4, 0, -5 }, - { 5, -4, 6, 12, 6, 13, 24, 17, -5, 17, -1, -6, -7, -10, -8, -18, + { 5, -4, 6, 12, 6, 13, 24, 17, -5, 17, -1, -6, -7, -10, -8, -18, 3, -2, 2, 7, -15, -11, 12, -3, -2, -2, -4, -7, 2, 0, 5, 5 }, - { 10, -6, 8, 11, 12, 20, 22, -11, -3, 15, -3, 15, -2, -2, 0, 2, + { 10, -6, 8, 11, 12, 20, 22, -11, -3, 15, -3, 15, -2, -2, 0, 2, 5, -8, 4, -5, -9, -4, -1, 2, -1, -3, 1, 3, 13, -1, 9, 7 }, - { -5, 8, 5, 11, 14, -5, 14, -9, 2, 35, 8, 15, 1, -2, 2, -2, + { -5, 8, 5, 11, 14, -5, 14, -9, 2, 35, 8, 15, 1, -2, 2, -2, 4, -9, -3, -14, -12, -2, -2, -4, -2, -8, -3, 1, -6, 3, 10, 0 }, - { 16, 0, -6, 15, -3, 4, 4, 3, 3, 20, 5, -4, 10, 9, -9, -3, + { 16, 0, -6, 15, -3, 4, 4, 3, 3, 20, 5, -4, 10, 9, -9, -3, -10, -2, -7, 11, -11, -10, 17, -1, 3, -15, 2, 9, -15, -10, 16, 10 }, - { 14, 4, -7, 19, 3, 0, 19, 8, 16, 34, -9, 6, -13, -1, 6, 5, + { 14, 4, -7, 19, 3, 0, 19, 8, 16, 34, -9, 6, -13, -1, 6, 5, -1, -2, 4, 3, 2, 1, 1, -1, 0, -7, 2, -1, 1, 0, 6, -1 }, - { 1, 6, 9, 13, 9, 10, 15, 16, 10, 18, 13, 17, 3, -1, -7, 2, + { 1, 6, 9, 13, 9, 10, 15, 16, 10, 18, 13, 17, 3, -1, -7, 2, -15, -11, -10, -4, -13, -6, -17, -13, -6, -14, 1, -10, 6, 4, -1, -1 }, - { 13, 1, 7, 10, 14, 13, -7, 5, 5, 28, 14, 14, -2, 2, 3, -3, + { 13, 1, 7, 10, 14, 13, -7, 5, 5, 28, 14, 14, -2, 2, 3, -3, -13, -4, 10, -9, 19, -4, -3, 4, -5, -5, 0, 5, -5, 0, 3, -4 }, - { 1, 0, 6, 22, 9, 18, 18, -3, 5, 10, 12, -2, 1, -3, -8, -12, + { 1, 0, 6, 22, 9, 18, 18, -3, 5, 10, 12, -2, 1, -3, -8, -12, 9, -10, -7, 1, -1, 19, 0, 2, -8, -11, -10, 9, 6, 11, 0, 3 }, - { 10, 11, 19, 44, 0, 14, 1, -7, 6, 22, 2, -1, 9, 2, 0, -4, + { 10, 11, 19, 44, 0, 14, 1, -7, 6, 22, 2, -1, 9, 2, 0, -4, 4, 0, -6, -6, 3, 0, 0, -2, 2, -5, 1, -2, 0, 1, 1, 1 }, - { 5, 7, 0, 32, 30, 26, 5, 4, -7, -3, 15, -6, 3, -10, 7, 6, + { 5, 7, 0, 32, 30, 26, 5, 4, -7, -3, 15, -6, 3, -10, 7, 6, -8, -7, 2, -13, -5, -1, -3, 7, 3, -2, -8, 0, 6, 4, 5, 0 }, - { 9, 8, -2, 4, 2, 11, 4, 29, -5, 14, 8, -5, -14, 8, 0, 9, + { 9, 8, -2, 4, 2, 11, 4, 29, -5, 14, 8, -5, -14, 8, 0, 9, 8, -10, 5, -15, -6, -9, 9, -1, 18, -16, 9, -21, -3, -13, -2, 8 }, - { 25, 7, -9, 23, 20, 18, 6, 16, -9, 8, 8, -5, 11, 13, -8, 7, + { 25, 7, -9, 23, 20, 18, 6, 16, -9, 8, 8, -5, 11, 13, -8, 7, 4, 10, -2, -1, -7, -9, -7, -9, -4, 1, 1, -5, -10, 8, 4, -5 }, - { 9, 2, 16, 14, -5, 14, 1, 0, -21, 17, -1, 9, 12, -3, -3, 4, + { 9, 2, 16, 14, -5, 14, 1, 0, -21, 17, -1, 9, 12, -3, -3, 4, -4, 14, 10, 3, 0, -10, 7, 4, 4, -11, 2, 4, -1, -3, 9, -1 }, - { 17, 8, 11, 26, 15, -3, 14, -1, 12, 9, 10, -8, 8, -18, -11, -3, + { 17, 8, 11, 26, 15, -3, 14, -1, 12, 9, 10, -8, 8, -18, -11, -3, -14, -7, 7, -3, -3, -4, 1, -7, -3, 2, -3, 16, 10, 0, 9, 6 }, - { 9, 8, 3, 8, 18, 14, 11, 1, 10, 6, 1, -4, -16, -2, 14, -2, + { 9, 8, 3, 8, 18, 14, 11, 1, 10, 6, 1, -4, -16, -2, 14, -2, 1, 8, 12, 14, 3, -3, 8, 8, 12, -15, 3, -3, 3, -2, 14, 10 }, - { 22, -3, -11, 13, -7, 11, 4, 11, 3, 14, 0, -6, -2, -9, 4, 2, + { 22, -3, -11, 13, -7, 11, 4, 11, 3, 14, 0, -6, -2, -9, 4, 2, -2, 0, -5, -27, -10, 3, -1, 5, 8, -24, -3, -11, -3, 2, 11, -1 }, - { 19, 2, 8, 36, 5, -6, 3, 15, -3, -4, -5, 14, -10, 1, -12, -10, + { 19, 2, 8, 36, 5, -6, 3, 15, -3, -4, -5, 14, -10, 1, -12, -10, -3, -4, 3, -2, 1, -8, 4, 3, 5, -3, 0, 4, 8, -2, 8, 4 }, - { 8, 14, 15, 9, -4, 10, 5, 11, 9, 10, 8, 9, -15, 15, 6, -8, + { 8, 14, 15, 9, -4, 10, 5, 11, 9, 10, 8, 9, -15, 15, 6, -8, -10, -13, 5, -8, -20, -13, -6, -11, -1, -3, -6, -4, -1, 0, 13, 15 }, - { -2, -1, 9, 12, 2, 2, 13, 3, -23, 33, 15, 2, -4, -1, 3, 8, + { -2, -1, 9, 12, 2, 2, 13, 3, -23, 33, 15, 2, -4, -1, 3, 8, 8, 6, 6, -7, 8, 6, 9, -1, 3, -8, 0, -4, 1, -8, 11, -1 }, - { 6, 5, -6, 16, 2, -3, 31, 21, -9, 12, 0, -1, -4, 1, -12, 3, + { 6, 5, -6, 16, 2, -3, 31, 21, -9, 12, 0, -1, -4, 1, -12, 3, -13, -18, 2, -11, -9, 2, -8, -6, 11, -3, -1, 0, -1, 0, 13, 5 }, - { 5, -1, 2, 0, 25, 5, 10, 16, -5, 21, 14, 12, 13, 2, -5, 5, + { 5, -1, 2, 0, 25, 5, 10, 16, -5, 21, 14, 12, 13, 2, -5, 5, 5, -3, -2, -14, 0, -12, 7, 11, -1, -7, 19, -1, -1, -1, 8, -1 }, - { 10, 7, 3, 11, 0, 8, 22, 3, 3, 19, -4, 12, 15, 9, 5, 15, + { 10, 7, 3, 11, 0, 8, 22, 3, 3, 19, -4, 12, 15, 9, 5, 15, 2, 1, 2, -10, -10, 0, 2, -1, 0, 1, -12, -1, 21, 16, 9, -7 }, - { 11, -4, -5, 24, -7, 11, 20, 11, -15, 18, 5, -13, -15, 0, -5, 9, + { 11, -4, -5, 24, -7, 11, 20, 11, -15, 18, 5, -13, -15, 0, -5, 9, 1, 0, -1, -9, 4, -8, 6, -8, 1, -2, -7, 20, 9, 3, 9, 3 }, - { 20, 0, -12, -6, 9, 31, 9, 12, 8, 27, 15, 7, -16, 5, -3, -7, + { 20, 0, -12, -6, 9, 31, 9, 12, 8, 27, 15, 7, -16, 5, -3, -7, -1, -9, -2, -7, -3, 4, -8, -3, 3, -6, -2, -2, -3, -6, -1, 2 }, - { 6, -6, 48, 8, -3, 19, 12, 11, -7, 2, 3, 0, -1, 1, 8, -4, + { 6, -6, 48, 8, -3, 19, 12, 11, -7, 2, 3, 0, -1, 1, 8, -4, 4, -6, 0, -4, -4, -3, 3, 6, 3, -13, -8, 5, -3, -7, 8, 5 }, - { 7, -2, 6, 11, 12, 2, 14, 4, -5, 12, 2, 9, 4, 2, 0, -1, + { 7, -2, 6, 11, 12, 2, 14, 4, -5, 12, 2, 9, 4, 2, 0, -1, 2, 0, -15, -9, -16, -2, 8, -17, -5, -22, -19, -5, -1, -10, 1, -2 }, - { 11, -9, 3, 12, 6, 6, 1, 17, -6, 19, 14, 7, -7, -1, -1, -9, + { 11, -9, 3, 12, 6, 6, 1, 17, -6, 19, 14, 7, -7, -1, -1, -9, 9, -11, -17, 0, -6, 16, 0, 1, 9, -24, 3, 3, -9, -3, 3, -2 }, - { 9, 0, 1, 8, 1, 7, 2, -5, -3, 8, -1, 7, 2, 6, -3, -6, + { 9, 0, 1, 8, 1, 7, 2, -5, -3, 8, -1, 7, 2, 6, -3, -6, 5, -2, 6, -2, -4, -3, 0, -3, 13, -50, 1, -2, 2, 4, 4, 3 }, - { 7, 0, 26, 21, -4, 2, 17, 8, 7, 11, -7, 1, -1, -15, -1, -15, + { 7, 0, 26, 21, -4, 2, 17, 8, 7, 11, -7, 1, -1, -15, -1, -15, -11, -4, -17, -4, 1, -7, 3, 6, 3, -9, 2, 3, 6, 10, 6, 12 }, - { 1, -2, 2, -1, -10, -4, 6, -3, -5, -2, -8, 2, 2, 2, 8, 0, + { 1, -2, 2, -1, -10, -4, 6, -3, -5, -2, -8, 2, 2, 2, 8, 0, 1, 1, 6, 0, 11, 13, 3, 4, 0, -12, 11, -5, 19, 20, 2, 5 }, - { 5, 3, -13, -2, 1, -12, 11, -7, -12, 7, 10, 0, 7, 0, -2, 4, + { 5, 3, -13, -2, 1, -12, 11, -7, -12, 7, 10, 0, 7, 0, -2, 4, -6, -9, -11, -12, -23, 12, 10, -3, 0, 6, 19, -1, 24, 18, 9, 12 }, - { 6, -3, 2, 5, 2, 2, -2, -5, -8, -11, -4, 3, -8, -4, 5, -3, + { 6, -3, 2, 5, 2, 2, -2, -5, -8, -11, -4, 3, -8, -4, 5, -3, -16, -4, 3, -12, -4, 3, 32, 7, 2, 8, 32, -18, -1, 12, 1, 7 }, - { 0, -8, -1, 0, -8, 7, -8, -1, -1, 4, -12, -1, 3, 0, 1, -18, + { 0, -8, -1, 0, -8, 7, -8, -1, -1, 4, -12, -1, 3, 0, 1, -18, 8, 8, -14, -10, -11, 19, 9, 5, -7, 6, 8, -4, 26, 12, -1, 6 }, - { 3, 5, -14, 7, 14, 8, 20, -13, -16, -10, -2, 17, -7, 4, -8, -9, + { 3, 5, -14, 7, 14, 8, 20, -13, -16, -10, -2, 17, -7, 4, -8, -9, 14, -5, 3, -4, -12, 7, 14, -10, -19, -20, 35, 8, 13, 14, -2, 9 }, - { -2, -4, -1, 1, -3, 0, -1, 1, 2, 2, 6, 0, 0, 4, 5, -2, + { -2, -4, -1, 1, -3, 0, -1, 1, 2, 2, 6, 0, 0, 4, 5, -2, 3, 3, 3, -2, -7, -3, -3, -1, 6, -2, 29, 22, 13, 34, 0, 14 }, - { -3, -9, 3, 1, 5, -4, 2, 0, 7, -9, 0, 2, -5, -3, 0, 6, + { -3, -9, 3, 1, 5, -4, 2, 0, 7, -9, 0, 2, -5, -3, 0, 6, -1, -1, -1, 2, 2, 4, 8, 7, 20, -6, 7, 16, 33, 20, 6, -1 }, - { -11, 1, -3, -3, -11, 3, -9, -25, -1, -16, 4, -8, 15, 1, -2, 7, + { -11, 1, -3, -3, -11, 3, -9, -25, -1, -16, 4, -8, 15, 1, -2, 7, 8, 23, 2, 18, -13, 16, 3, -7, 6, 3, 16, -8, 12, 16, 3, 4 }, - { 0, 5, 5, -5, 1, -1, 2, -3, -2, 1, -13, 2, 2, 10, 6, 7, + { 0, 5, 5, -5, 1, -1, 2, -3, -2, 1, -13, 2, 2, 10, 6, 7, 18, 18, 7, 9, 8, 9, 21, 14, 7, 12, 15, 14, 15, 12, 11, 5 }, - { 1, -5, 11, -2, 17, 8, 3, 0, -1, 6, 11, -7, 6, 6, 7, 5, + { 1, -5, 11, -2, 17, 8, 3, 0, -1, 6, 11, -7, 6, 6, 7, 5, -15, 14, 1, 11, 4, 10, 12, 1, 2, 4, 30, 1, 11, 1, 6, 13 }, - { 2, 4, 3, -7, 5, 8, -11, 7, -5, 9, -10, 6, 8, -10, -3, 10, + { 2, 4, 3, -7, 5, 8, -11, 7, -5, 9, -10, 6, 8, -10, -3, 10, 1, -29, -4, -26, 5, -8, 13, 4, 3, 6, 35, 1, 3, 6, 3, 0 }, - { -2, 1, 0, 0, -1, -3, -7, -3, -9, -3, -1, -6, 3, 4, 4, 0, + { -2, 1, 0, 0, -1, -3, -7, -3, -9, -3, -1, -6, 3, 4, 4, 0, 5, -1, -2, -2, -1, -4, -10, 8, 0, -6, 10, -4, 46, 12, 2, 28 }, - { 4, -1, 4, 1, 0, 4, -2, -2, -2, -1, 2, -4, 1, 5, 0, -3, + { 4, -1, 4, 1, 0, 4, -2, -2, -2, -1, 2, -4, 1, 5, 0, -3, 1, 1, -2, 0, 1, -2, -1, -1, 3, -6, 35, -11, 13, 53, -3, -1 }, - { -5, -2, 0, -13, -16, 5, -12, -11, 1, -30, 3, -18, -24, -8, -5, -19, + { -5, -2, 0, -13, -16, 5, -12, -11, 1, -30, 3, -18, -24, -8, -5, -19, 1, -3, -8, 7, -7, -8, 15, -19, 4, 10, 30, 24, 6, 1, -9, 10 }, - { -4, 8, -7, -4, -6, 12, -1, -9, -4, 2, -9, 3, 2, -2, 4, 2, + { -4, 8, -7, -4, -6, 12, -1, -9, -4, 2, -9, 3, 2, -2, 4, 2, 22, 9, 4, -5, 0, 5, -2, -9, -3, 1, 18, -12, 18, 16, 4, 16 }, - { -5, -8, -3, -5, -3, 6, -7, -3, -2, -5, -3, 1, 2, 2, 4, -6, + { -5, -8, -3, -5, -3, 6, -7, -3, -2, -5, -3, 1, 2, 2, 4, -6, 10, 3, 12, -3, 20, 0, 27, -4, 16, 5, 18, -3, 23, 4, 12, 11 }, - { 0, 1, 0, 1, -2, 1, 2, 1, -1, 0, -2, 2, -2, -4, 1, -2, + { 0, 1, 0, 1, -2, 1, 2, 1, -1, 0, -2, 2, -2, -4, 1, -2, -2, -1, -5, -2, 0, 0, -2, 2, 9, 7, 63, 5, 12, -1, 1, 0 }, - { 4, -3, -7, -5, -11, -5, -12, -10, -10, -12, -15, -12, -14, -14, 1, 1, + { 4, -3, -7, -5, -11, -5, -12, -10, -10, -12, -15, -12, -14, -14, 1, 1, 10, -10, 16, 6, 2, 9, 11, 9, 9, 8, 12, -1, 13, 12, 6, 3 }, - { 7, -3, -2, 4, 6, -8, 2, -3, -12, -5, -9, -8, -10, 15, -2, -4, + { 7, -3, -2, 4, 6, -8, 2, -3, -12, -5, -9, -8, -10, 15, -2, -4, 8, 9, 7, -13, -18, 34, -5, 7, 12, 22, 16, -11, 13, 25, -15, -11 }, - { -3, -2, 0, -4, 1, 0, -3, -13, -7, 13, 12, -7, -10, 13, 19, 6, + { -3, -2, 0, -4, 1, 0, -3, -13, -7, 13, 12, -7, -10, 13, 19, 6, 16, 15, -12, -15, -3, 34, 1, 5, 1, -9, 11, 21, 8, 17, -5, -6 }, - { 3, -5, 0, -4, 0, 4, -11, 4, -7, -3, -1, -8, 3, -2, 2, 1, + { 3, -5, 0, -4, 0, 4, -11, 4, -7, -3, -1, -8, 3, -2, 2, 1, 11, 5, 6, 14, -3, 2, -4, -7, 0, 31, 15, -2, 24, 11, 5, 4 }, - { -1, -4, -9, 5, -8, -18, -4, -9, -20, -18, 7, -14, -16, 3, 8, -3, + { -1, -4, -9, 5, -8, -18, -4, -9, -20, -18, 7, -14, -16, 3, 8, -3, 29, 11, -13, -13, 7, 1, 17, 6, 6, 21, 11, 1, 14, -8, 2, 5 }, - { -3, 8, -10, -6, 12, 2, 1, 3, 3, 3, 3, -6, -8, -14, 15, -5, + { -3, 8, -10, -6, 12, 2, 1, 3, 3, 3, 3, -6, -8, -14, 15, -5, 16, 4, 16, 0, 7, -1, 0, 16, 2, 1, 22, 4, 19, 13, -11, 1 }, - { 2, -3, 10, 20, -4, -1, -8, 5, -8, -9, -6, -2, -4, -7, 8, -10, + { 2, -3, 10, 20, -4, -1, -8, 5, -8, -9, -6, -2, -4, -7, 8, -10, 0, 8, -6, 1, -8, 14, 13, 5, 17, -6, 26, -1, 7, -1, 0, 12 }, - { -4, -7, -31, -2, -7, -1, 5, -5, -5, -12, 4, -7, -6, 3, 15, -2, + { -4, -7, -31, -2, -7, -1, 5, -5, -5, -12, 4, -7, -6, 3, 15, -2, 5, -2, 7, -1, 10, 7, 8, -1, 14, 20, 14, 9, 16, 16, 8, 24 }, - { -7, 0, -3, -6, 1, 3, -13, -6, -4, -4, -5, -9, -1, -10, -4, -8, + { -7, 0, -3, -6, 1, 3, -13, -6, -4, -4, -5, -9, -1, -10, -4, -8, 2, 0, -1, 1, 24, 24, 21, 31, 5, 2, 11, 12, 7, 4, 3, 6 }, - { -3, -5, 6, -4, -3, -1, 2, -1, -2, 1, 0, -8, -1, 2, 0, -4, + { -3, -5, 6, -4, -3, -1, 2, -1, -2, 1, 0, -8, -1, 2, 0, -4, 6, 22, -1, -5, 8, 12, -1, -2, 28, 27, 20, -27, 14, 1, 2, -3 }, - { 1, -5, -2, -2, 6, -2, 9, 1, -2, -5, 3, 4, 11, 5, 2, 8, + { 1, -5, -2, -2, 6, -2, 9, 1, -2, -5, 3, 4, 11, 5, 2, 8, -3, -1, 1, -2, -3, -5, 5, 8, 49, 12, 8, -3, 9, 20, 12, 17 }, - { -6, 0, 1, 7, 0, 9, -2, -4, 8, 0, -2, -10, 0, 7, 21, -1, + { -6, 0, 1, 7, 0, 9, -2, -4, 8, 0, -2, -10, 0, 7, 21, -1, 0, 1, 17, -7, -5, 2, 4, 16, -2, 17, 14, -20, 15, 14, 4, 15 }, - { 0, 3, -4, 9, -4, 0, 6, 4, -6, -6, -5, -7, 2, -9, -10, -2, + { 0, 3, -4, 9, -4, 0, 6, 4, -6, -6, -5, -7, 2, -9, -10, -2, -5, 0, -3, -21, 9, 14, -11, 13, 29, 2, 25, 4, 22, -1, 2, -3 }, - { 2, 12, -11, 2, 16, 9, -4, 7, 1, -10, -15, 11, -4, 3, -2, 4, + { 2, 12, -11, 2, 16, 9, -4, 7, 1, -10, -15, 11, -4, 3, -2, 4, 4, -5, -10, 1, 4, 19, -15, 6, -4, -2, 30, -7, 11, 21, -12, 5 }, - { -2, -3, -2, 4, -1, -5, -3, -7, -5, 1, 0, -6, 1, -6, 7, 0, + { -2, -3, -2, 4, -1, -5, -3, -7, -5, 1, 0, -6, 1, -6, 7, 0, 8, -7, -3, -2, 2, 14, 2, -3, -26, -1, 26, 22, 32, 1, -2, 6 }, - { 1, -38, -1, -20, -2, -3, -6, -4, 2, 2, 7, 0, 3, 5, 3, 10, + { 1, -38, -1, -20, -2, -3, -6, -4, 2, 2, 7, 0, 3, 5, 3, 10, 6, 1, -3, -5, 7, 5, -5, -4, 8, 3, 1, -14, -1, -9, -5, -4 }, - { -5, -26, -7, -19, -10, -5, -11, 5, -11, -25, -8, -14, -9, -16, -8, -6, + { -5, -26, -7, -19, -10, -5, -11, 5, -11, -25, -8, -14, -9, -16, -8, -6, -17, -14, -1, -1, 6, 2, 2, 2, 3, 0, 2, 8, -8, 3, 0, -3 }, - { 17, -49, -3, -23, -1, 11, 7, 3, 4, -4, 0, 0, -1, 4, 2, 4, + { 17, -49, -3, -23, -1, 11, 7, 3, 4, -4, 0, 0, -1, 4, 2, 4, -2, -4, 2, -2, -1, -2, 2, 0, 0, -1, 0, 0, 1, 2, 0, 0 }, - { 4, -34, -6, -9, 1, 21, -7, 3, -2, -1, -3, 18, 2, -16, 7, -3, + { 4, -34, -6, -9, 1, 21, -7, 3, -2, -1, -3, 18, 2, -16, 7, -3, 8, 7, -5, 7, 2, 4, 8, -6, -7, -2, -5, -1, 4, 1, 2, -4 }, - { 5, -29, 13, -2, -14, 3, 1, 18, -15, 4, -8, 8, -10, 8, 2, 1, + { 5, -29, 13, -2, -14, 3, 1, 18, -15, 4, -8, 8, -10, 8, 2, 1, -8, 15, 3, -10, -4, -4, -2, 0, -3, -4, 2, -3, -4, -3, 12, -6 }, - { 13, -20, 3, -18, -17, 4, -14, 13, 28, 11, -8, -6, 16, 6, 0, 10, + { 13, -20, 3, -18, -17, 4, -14, 13, 28, 11, -8, -6, 16, 6, 0, 10, 3, 4, -9, 13, 5, -7, 12, -5, 0, -7, 5, 1, 3, 3, 2, 1 }, - { 3, -27, -5, -11, -21, -11, -12, 0, -5, 7, -22, 1, 3, 5, 0, -5, + { 3, -27, -5, -11, -21, -11, -12, 0, -5, 7, -22, 1, 3, 5, 0, -5, 8, 7, 1, -5, -7, 2, -5, 4, 1, 3, -8, -2, 0, 4, -2, 6 }, - { 31, -45, 0, -1, -12, 1, 2, -6, 4, 3, -1, 3, 3, 0, 5, 3, + { 31, -45, 0, -1, -12, 1, 2, -6, 4, 3, -1, 3, 3, 0, 5, 3, -5, 12, 4, 6, 2, 1, -2, 1, 3, 2, 5, 2, 2, 2, 3, -1 }, - { 9, -45, 6, 5, -1, -17, -2, 18, -3, 2, 0, 1, 0, -1, 10, 8, + { 9, -45, 6, 5, -1, -17, -2, 18, -3, 2, 0, 1, 0, -1, 10, 8, -7, -2, -5, -8, 6, -1, 0, 4, 6, -3, 12, -1, -2, 0, 5, -7 }, - { 3, -26, -2, -12, -12, 2, -10, 16, -3, 12, 4, 5, 11, 8, -16, -17, + { 3, -26, -2, -12, -12, 2, -10, 16, -3, 12, 4, 5, 11, 8, -16, -17, -2, -3, -3, 2, 5, -9, 13, 1, 10, 11, 3, 5, -2, 2, 2, -7 }, - { 8, -26, 32, -7, -5, 22, 2, 14, -10, -8, -7, 3, 3, 7, 0, -5, + { 8, -26, 32, -7, -5, 22, 2, 14, -10, -8, -7, 3, 3, 7, 0, -5, 0, -1, -3, 0, 8, 4, -5, -7, 6, -1, 4, 8, 1, 1, 7, -6 }, - { 4, -31, 2, -14, 2, 0, 1, 8, -6, -1, 17, -3, 13, -6, 5, -10, + { 4, -31, 2, -14, 2, 0, 1, 8, -6, -1, 17, -3, 13, -6, 5, -10, -2, -10, -2, -10, -3, 7, 1, 5, -8, 8, -14, -3, -15, 7, -10, -6 }, - { 16, -27, 13, -4, -23, 7, -9, 6, -7, 5, 4, 2, -1, -3, 23, -18, + { 16, -27, 13, -4, -23, 7, -9, 6, -7, 5, 4, 2, -1, -3, 23, -18, 7, 0, -3, 4, -3, 9, -6, -2, -1, 8, -6, 2, 6, -3, 2, -2 }, - { -1, -35, -2, -8, 11, -1, -7, -3, -2, 11, 7, 6, -6, -10, 9, 6, + { -1, -35, -2, -8, 11, -1, -7, -3, -2, 11, 7, 6, -6, -10, 9, 6, -3, -5, -6, -3, 9, 16, -16, -9, -20, 12, 3, 5, -3, 1, -9, 4 }, - { 2, -24, 1, -12, -16, 5, -4, 3, -4, -1, -11, -11, -8, -14, 14, 10, + { 2, -24, 1, -12, -16, 5, -4, 3, -4, -1, -11, -11, -8, -14, 14, 10, -8, 20, 8, -3, -11, 1, 1, -4, -4, -7, -3, 15, 2, -6, -2, 7 }, - { 9, -21, 2, -19, -7, -5, -8, 25, 3, 17, 5, -3, 9, -12, 8, 2, + { 9, -21, 2, -19, -7, -5, -8, 25, 3, 17, 5, -3, 9, -12, 8, 2, -4, 3, 3, 1, 11, -9, -4, -3, 4, 3, -22, 6, 4, 6, 11, -5 }, - { 16, -23, 13, -17, -21, -12, 5, 9, -20, 7, 6, -6, 0, 2, -9, 6, + { 16, -23, 13, -17, -21, -12, 5, 9, -20, 7, 6, -6, 0, 2, -9, 6, -6, -13, -7, -1, 5, -3, 5, -7, -10, 1, 0, 8, -9, 11, 0, -8 }, - { 10, -26, -9, -7, -19, -4, 6, 16, -7, 5, -4, 4, 8, 0, 4, -1, + { 10, -26, -9, -7, -19, -4, 6, 16, -7, 5, -4, 4, 8, 0, 4, -1, 6, -7, 1, -8, -11, 10, -14, 0, -16, 6, -3, 5, -1, 14, 12, 1 }, - { 8, -27, 12, -14, -1, -1, -19, 10, -11, 21, -14, 9, -8, -3, 8, -1, + { 8, -27, 12, -14, -1, -1, -19, 10, -11, 21, -14, 9, -8, -3, 8, -1, 12, -13, 3, -4, -2, 0, -9, 0, -7, 2, -3, 12, 1, -3, 3, 1 }, - { 18, -20, -14, -14, -16, -3, -24, 6, -17, 2, -3, -11, 2, -3, 12, 10, + { 18, -20, -14, -14, -16, -3, -24, 6, -17, 2, -3, -11, 2, -3, 12, 10, 10, 1, 10, 7, 8, 5, 5, 4, -1, 7, 2, 2, 0, 4, 7, 0 }, - { 0, -30, 9, -16, -18, 15, 12, -3, 4, -4, -5, -11, -4, -12, -10, 0, + { 0, -30, 9, -16, -18, 15, 12, -3, 4, -4, -5, -11, -4, -12, -10, 0, 2, -2, -4, -1, 2, 0, -1, -6, 2, -3, 4, -5, 7, 3, 5, 7 }, - { 25, -24, -1, -6, -9, 6, -13, -2, 3, 15, -3, 11, 4, -8, -11, 2, + { 25, -24, -1, -6, -9, 6, -13, -2, 3, 15, -3, 11, 4, -8, -11, 2, 0, -9, -2, 7, 4, 8, 5, -8, 5, 6, -1, -11, -15, -5, 0, 11 }, - { 0, -34, -7, -11, -7, 9, -3, 19, 4, -8, 3, -11, 11, -3, -9, 12, + { 0, -34, -7, -11, -7, 9, -3, 19, 4, -8, 3, -11, 11, -3, -9, 12, 9, 9, 2, 1, -7, 1, -3, 0, -6, -2, -1, 3, 0, -7, -2, -5 }, - { 6, -34, -4, -5, -3, -9, 2, 9, -1, 9, -5, -3, -26, -12, 8, -6, + { 6, -34, -4, -5, -3, -9, 2, 9, -1, 9, -5, -3, -26, -12, 8, -6, -7, 11, -8, 4, 4, 1, -1, 0, 8, 9, -4, 7, -1, 1, -3, -1 }, - { 3, -30, 5, 6, -10, 3, -7, 6, 3, 3, -26, -19, -3, 1, 7, 5, + { 3, -30, 5, 6, -10, 3, -7, 6, 3, 3, -26, -19, -3, 1, 7, 5, -4, -5, 6, 10, 13, -10, 4, -7, -4, 5, -3, 9, -6, 3, 9, 5 }, - { 4, -24, 9, -19, 2, -4, -5, 8, -3, 2, 0, -15, -1, 9, -4, 22, + { 4, -24, 9, -19, 2, -4, -5, 8, -3, 2, 0, -15, -1, 9, -4, 22, 6, 9, 3, 7, 11, -9, 0, -3, 4, 5, -5, 10, -8, 5, -7, -3 }, - { 8, -27, 7, -3, -1, 2, -9, 13, 7, 12, -4, -6, -6, 5, 0, 7, + { 8, -27, 7, -3, -1, 2, -9, 13, 7, 12, -4, -6, -6, 5, 0, 7, 5, 1, 15, -3, -4, 0, -5, -2, 7, -5, -7, 1, -2, 13, -8, 13 }, - { 17, -22, -15, -11, -8, 16, -14, 18, 2, -1, 14, -7, 14, -6, -6, -7, + { 17, -22, -15, -11, -8, 16, -14, 18, 2, -1, 14, -7, 14, -6, -6, -7, -8, 17, 6, 4, 4, -7, -5, -9, -14, -6, -1, 9, -3, 1, 6, -5 }, - { 25, -30, 2, -12, -13, 18, -18, 16, 8, -3, 10, -8, -3, -1, -6, 3, + { 25, -30, 2, -12, -13, 18, -18, 16, 8, -3, 10, -8, -3, -1, -6, 3, -5, -7, 4, 6, 7, 1, 1, -11, -5, 6, 2, -4, 9, -1, -5, -2 }, - { 7, -23, 7, -15, -1, -3, -1, 0, -10, 12, 2, 5, -4, 0, 4, 6, + { 7, -23, 7, -15, -1, -3, -1, 0, -10, 12, 2, 5, -4, 0, 4, 6, -1, 5, -9, -1, -1, -7, 1, 17, 9, -17, -16, 8, 4, -14, 11, 14 }, - { 0, -31, 7, -13, 3, -11, -7, 6, 1, -11, 8, -7, 15, -3, 16, -11, + { 0, -31, 7, -13, 3, -11, -7, 6, 1, -11, 8, -7, 15, -3, 16, -11, -1, -15, 16, -3, 5, 0, -2, -2, -6, 11, 5, 6, 5, -5, 6, 3 }, - { 13, -24, -2, -20, -10, 7, -3, -1, 15, 2, 6, -5, -7, -10, -20, 1, + { 13, -24, -2, -20, -10, 7, -3, -1, 15, 2, 6, -5, -7, -10, -20, 1, -4, 14, 8, -2, 3, -13, -3, 1, -4, 1, -3, 2, 8, -7, 16, -4 }, - { 1, -2, -2, -3, -4, -7, 0, 3, 6, 7, 3, 2, 1, -2, -1, 0, + { 1, -2, -2, -3, -4, -7, 0, 3, 6, 7, 3, 2, 1, -2, -1, 0, -6, 4, 2, -4, -3, -4, 5, 9, 5, 0, -3, -3, -4, -7, -31, -50 }, - { -1, -3, 7, 2, -1, 2, 4, 6, 0, 10, -2, 0, -20, -6, -3, 9, + { -1, -3, 7, 2, -1, 2, 4, 6, 0, 10, -2, 0, -20, -6, -3, 9, -20, -22, -1, -1, 15, 9, -12, 10, -13, -20, 12, 3, 5, 6, -7, -26 }, - { 0, 4, -2, -14, -12, 6, -13, 11, -10, 3, 22, 6, 16, -2, -5, 1, + { 0, 4, -2, -14, -12, 6, -13, 11, -10, 3, 22, 6, 16, -2, -5, 1, -3, -11, 0, -7, 5, -5, 0, 1, -1, -6, 8, 8, 10, 9, -5, -27 }, - { -5, 10, -2, 7, 9, -9, 5, -9, 5, 4, -15, 14, 1, 3, -10, 5, + { -5, 10, -2, 7, 9, -9, 5, -9, 5, 4, -15, 14, 1, 3, -10, 5, 0, -2, 7, 3, -13, 6, 9, -6, 5, -14, -17, -1, 11, 14, -2, -26 }, - { 0, 6, -3, 0, -8, 6, 0, 1, 4, -8, 2, -5, 4, 7, 15, 11, + { 0, 6, -3, 0, -8, 6, 0, 1, 4, -8, 2, -5, 4, 7, 15, 11, 9, 19, -2, 14, -8, 7, -1, 3, -3, -3, -10, -2, 12, -2, -12, -29 }, - { -12, -5, 0, -3, -2, 6, 3, -3, 2, -2, 1, 11, 2, -7, 5, 1, + { -12, -5, 0, -3, -2, 6, 3, -3, 2, -2, 1, 11, 2, -7, 5, 1, 2, -2, -14, 0, -1, -5, 3, 8, -28, -26, 6, -6, 3, 8, -10, -27 }, - { -1, -3, 6, 2, 4, 15, 1, 0, 2, -2, -2, 13, 3, 6, 0, 6, + { -1, -3, 6, 2, 4, 15, 1, 0, 2, -2, -2, 13, 3, 6, 0, 6, -1, -4, -1, -5, 8, -1, 5, -5, -15, 11, -8, -5, 14, -6, -14, -29 }, - { -5, -6, 0, 1, 0, 6, -3, 2, -5, -1, 5, -3, 2, -10, 3, 4, + { -5, -6, 0, 1, 0, 6, -3, 2, -5, -1, 5, -3, 2, -10, 3, 4, 3, 0, 13, -3, -1, 4, -4, -6, 2, 9, 8, 2, -3, 28, -11, -31 }, - { 1, -4, -10, -9, -4, -3, -15, -6, 1, 5, -3, -6, 5, -6, -22, 27, + { 1, -4, -10, -9, -4, -3, -15, -6, 1, 5, -3, -6, 5, -6, -22, 27, -13, 5, 3, -7, -4, 20, -7, -12, -1, -24, -4, -13, -8, -11, -15, -21 }, - { -6, -4, 19, -6, 2, 11, -6, 1, -3, -10, 9, -9, 12, -10, 2, 1, + { -6, -4, 19, -6, 2, 11, -6, 1, -3, -10, 9, -9, 12, -10, 2, 1, -9, 1, 15, 7, -5, 5, -29, -35, 4, -30, 9, 9, 19, 17, 2, -17 }, - { -3, 3, -3, 1, 2, 5, -1, 5, -2, -3, 1, -3, -8, 3, -4, -2, + { -3, 3, -3, 1, 2, 5, -1, 5, -2, -3, 1, -3, -8, 3, -4, -2, -4, -1, 12, 0, 2, -8, -6, -4, 16, -1, -14, -2, 25, -6, -15, -36 }, - { 0, -1, 3, -4, -4, -1, 7, -4, 8, 0, 10, 9, -4, 1, 10, -1, + { 0, -1, 3, -4, -4, -1, 7, -4, 8, 0, 10, 9, -4, 1, 10, -1, -3, -13, -5, -4, -1, -4, 8, 11, 14, -7, -5, 16, 12, 13, -1, -28 }, - { 1, -2, 2, -3, -8, 10, 4, 9, 12, 3, 5, 0, 8, -3, -6, 2, + { 1, -2, 2, -3, -8, 10, 4, 9, 12, 3, 5, 0, 8, -3, -6, 2, 16, -11, 11, 0, 1, 6, 1, 18, -10, -16, -1, -4, 5, -14, -15, -20 }, - { 1, -12, 5, 4, -7, 8, -1, -17, -2, -9, -14, -11, 6, -9, 5, -4, + { 1, -12, 5, 4, -7, 8, -1, -17, -2, -9, -14, -11, 6, -9, 5, -4, 3, -2, 7, 18, -5, 5, 6, -1, -11, -2, -10, -3, 8, -3, -2, -32 }, - { -12, 5, 20, -5, -6, -11, -6, -6, -13, 4, -6, 19, -8, 2, 3, -9, + { -12, 5, 20, -5, -6, -11, -6, -6, -13, 4, -6, 19, -8, 2, 3, -9, -4, -4, -1, 9, -1, 21, -1, 7, 15, -10, -1, -3, 9, -3, 2, -24 }, - { 0, -3, 2, -6, 4, -1, -9, -2, -1, -3, 6, -1, -5, -6, -5, -8, + { 0, -3, 2, -6, 4, -1, -9, -2, -1, -3, 6, -1, -5, -6, -5, -8, 0, -2, -6, 9, -4, 3, 2, -13, 1, -7, 23, -13, 4, -3, -15, -33 }, - { -7, 2, -15, 11, -10, 14, 0, -11, 3, -1, 12, -4, -4, 9, 11, -13, + { -7, 2, -15, 11, -10, 14, 0, -11, 3, -1, 12, -4, -4, 9, 11, -13, -13, -3, -14, 1, 3, 6, -5, 8, 0, 5, 5, -10, 4, 5, -6, -30 }, - { -6, 4, 0, -5, 4, 1, -1, -1, 3, 6, 5, -2, -5, 0, -2, 5, + { -6, 4, 0, -5, 4, 1, -1, -1, 3, 6, 5, -2, -5, 0, -2, 5, -4, -2, -4, -2, 4, 7, -7, -1, 1, -4, -3, -19, 37, 12, 10, -40 }, - { -7, 2, -7, -12, 17, 11, -7, 2, 2, 3, 1, -1, 3, 4, -2, -5, + { -7, 2, -7, -12, 17, 11, -7, 2, 2, 3, 1, -1, 3, 4, -2, -5, 9, -9, 6, 4, 9, 12, 11, -5, 2, -1, 0, 9, 5, -7, -2, -24 }, - { -7, 6, 1, 3, 1, 0, 6, 0, 4, -12, -2, -2, 1, -9, 10, -2, + { -7, 6, 1, 3, 1, 0, 6, 0, 4, -12, -2, -2, 1, -9, 10, -2, 11, -1, 21, -12, 15, -5, 10, -5, 5, -5, 14, -6, 5, -7, -3, -29 }, - { -2, 0, -5, -2, -3, 1, -3, 0, 4, 2, 3, 0, 2, -2, 7, -2, + { -2, 0, -5, -2, -3, 1, -3, 0, 4, 2, 3, 0, 2, -2, 7, -2, 3, -5, 2, -1, 6, -4, 0, -3, 8, -11, 19, -8, 22, -34, 13, -35 }, - { -1, -3, -1, 9, 11, -3, -3, -1, 7, 18, 11, -5, 2, -12, -11, 18, + { -1, -3, -1, 9, 11, -3, -3, -1, 7, 18, 11, -5, 2, -12, -11, 18, 9, -5, 1, -6, -9, 12, 1, -3, -3, -9, -14, 9, 9, 8, -6, -26 }, - { 0, 5, -5, -1, -1, -2, 4, 6, 8, 2, -1, -2, 5, 1, -5, -4, + { 0, 5, -5, -1, -1, -2, 4, 6, 8, 2, -1, -2, 5, 1, -5, -4, 1, 1, 18, 1, 7, -10, 3, -2, 12, -1, -15, 9, 12, -14, 13, -38 }, - { 3, 0, -8, -1, 0, 8, -9, -3, -8, 16, 3, 16, -5, -9, 0, -1, + { 3, 0, -8, -1, 0, 8, -9, -3, -8, 16, 3, 16, -5, -9, 0, -1, -7, -1, -4, 13, 7, 0, 1, 2, -1, -16, 0, -2, 1, 8, -8, -28 }, - { 7, 9, -5, -3, -2, 2, 0, 3, 11, -6, -4, -2, -2, -5, 28, -18, + { 7, 9, -5, -3, -2, 2, 0, 3, 11, -6, -4, -2, -2, -5, 28, -18, -6, 2, 15, -10, -15, -10, -2, 0, -2, -2, 4, -3, 7, 11, 5, -30 }, - { 9, 0, -7, -1, -4, -7, 2, 2, 9, -2, 2, 3, -8, -6, -6, 3, + { 9, 0, -7, -1, -4, -7, 2, 2, 9, -2, 2, 3, -8, -6, -6, 3, -10, 4, 10, 5, 21, -4, 14, -18, 1, 3, -10, -2, 6, 14, -8, -26 }, - { -14, -1, 2, 3, -3, 7, 1, -22, -1, -1, 0, 1, 12, -14, 3, -5, + { -14, -1, 2, 3, -3, 7, 1, -22, -1, -1, 0, 1, 12, -14, 3, -5, 0, 10, -3, 1, -5, 12, -3, 10, -8, -22, -11, -13, -7, -10, -13, -25 }, - { -2, -5, -4, -4, -9, -18, 9, -3, -5, 17, 13, 5, 6, 11, 3, 8, + { -2, -5, -4, -4, -9, -18, 9, -3, -5, 17, 13, 5, 6, 11, 3, 8, 20, 4, 2, 9, 8, 5, 6, 1, 7, -7, -6, -2, -7, 0, -17, -23 }, - { -5, -5, 2, 0, 6, 2, -2, 2, -3, 4, 4, 0, -5, -2, -4, 6, + { -5, -5, 2, 0, 6, 2, -2, 2, -3, 4, 4, 0, -5, -2, -4, 6, 8, 10, -1, 1, -5, 5, -14, -2, -11, 8, 6, 25, 7, -1, 0, -43 }, - { -4, 0, 4, -2, 7, 0, 3, 17, 5, 2, -5, 1, 21, 3, -2, -10, + { -4, 0, 4, -2, 7, 0, 3, 17, 5, 2, -5, 1, 21, 3, -2, -10, -16, -9, 7, -12, 9, -8, 2, 5, -5, -10, -2, -11, -5, -1, -9, -30 }, - { -2, 3, 1, -4, -1, 0, 8, 1, 12, 4, -1, -1, 3, -17, 13, 9, + { -2, 3, 1, -4, -1, 0, 8, 1, 12, 4, -1, -1, 3, -17, 13, 9, 0, 7, -6, -5, 9, 1, 5, 4, -10, -18, 0, 14, 11, -4, -16, -28 }, - { -1, 0, 2, -1, 4, 1, -1, 1, -1, -2, -1, -2, 3, 0, 0, -1, + { -1, 0, 2, -1, 4, 1, -1, 1, -1, -2, -1, -2, 3, 0, 0, -1, -1, 1, 2, -2, 3, 3, -2, 4, -2, -1, -6, 1, -1, -1, 6, -70 }, - { 7, 3, -11, -1, 12, -4, -14, 4, 4, -4, 4, -2, 2, -12, -4, 15, + { 7, 3, -11, -1, 12, -4, -14, 4, 4, -4, 4, -2, 2, -12, -4, 15, -17, -4, -3, 6, 8, -5, 22, -22, 5, -11, 15, -4, 4, -1, -21, -1 }, - { 10, -2, -13, 11, 4, 14, 4, 9, 8, 8, 19, 15, 14, 15, 5, 10, + { 10, -2, -13, 11, 4, 14, 4, 9, 8, 8, 19, 15, 14, 15, 5, 10, 8, 15, -5, 4, 14, -8, 1, 1, 2, 1, -1, -3, 21, 8, -29, 13 }, - { -6, 0, -6, 6, -1, 2, 8, -4, -5, 4, -4, -5, 0, -2, -4, 0, + { -6, 0, -6, 6, -1, 2, 8, -4, -5, 4, -4, -5, 0, -2, -4, 0, 9, -2, 1, -2, 26, -19, 21, -10, 4, 1, -8, 5, 22, -10, -13, 15 }, - { 11, -5, 1, 0, 6, 3, 7, -2, -2, -3, -5, -1, -2, -6, 1, 1, + { 11, -5, 1, 0, 6, 3, 7, -2, -2, -3, -5, -1, -2, -6, 1, 1, -8, -5, -13, 13, -2, -3, -1, -9, -28, 4, 2, -11, 18, -20, -24, 9 }, - { 7, 4, -3, 6, 6, -6, -7, -5, -7, -4, -4, 0, -7, -5, -6, -5, + { 7, 4, -3, 6, 6, -6, -7, -5, -7, -4, -4, 0, -7, -5, -6, -5, 2, -13, -12, 2, 0, 5, 18, 15, -13, -7, 13, -20, 16, -10, -19, 6 }, - { 5, -8, -1, 5, 10, 2, -1, -10, -11, 23, 8, -5, -8, 4, -5, -4, + { 5, -8, -1, 5, 10, 2, -1, -10, -11, 23, 8, -5, -8, 4, -5, -4, -5, -5, -11, -8, 5, 1, 7, -9, -9, -6, 12, 14, 17, -12, -22, 3 }, - { -5, -8, -3, 3, 12, -1, 0, -4, -5, 1, 1, 6, 1, 5, -5, 7, + { -5, -8, -3, 3, 12, -1, 0, -4, -5, 1, 1, 6, 1, 5, -5, 7, -2, 7, 1, 6, 6, 2, 0, -5, 17, -4, -5, -24, 13, -20, -27, 14 }, - { -1, 2, -3, 1, -3, 1, -3, 0, -2, 3, -2, 1, 2, -1, -2, -1, + { -1, 2, -3, 1, -3, 1, -3, 0, -2, 3, -2, 1, 2, -1, -2, -1, -2, -5, 5, -2, 0, -7, 1, -6, 8, 8, 11, -5, 24, -43, -13, 2 }, - { -2, 4, 7, -3, -4, 4, 13, -4, 0, 0, -2, 9, 0, -3, -6, 1, + { -2, 4, 7, -3, -4, 4, 13, -4, 0, 0, -2, 9, 0, -3, -6, 1, -7, 1, -1, 10, 0, 5, -1, -24, 25, -15, 7, 2, 22, -10, -21, 0 }, - { -5, 2, 6, -2, 13, 3, 5, -12, -11, 16, 6, 10, -5, 0, -3, 6, + { -5, 2, 6, -2, 13, 3, 5, -12, -11, 16, 6, 10, -5, 0, -3, 6, 5, -5, -5, 10, 12, 10, 11, -7, 8, -14, 2, -15, 13, -14, -8, -3 }, - { 5, 6, -7, -5, 5, 2, 9, 5, 0, -1, -4, 2, 8, 0, 3, 5, + { 5, 6, -7, -5, 5, 2, 9, 5, 0, -1, -4, 2, 8, 0, 3, 5, -12, 3, -3, -6, 2, -1, -5, 14, 11, -20, -21, -25, 24, -1, -10, 6 }, - { -5, 5, -2, 9, 4, -4, -1, -6, 11, -6, 5, 0, 2, -3, 6, -1, + { -5, 5, -2, 9, 4, -4, -1, -6, 11, -6, 5, 0, 2, -3, 6, -1, -17, -18, -4, -13, 9, -1, 9, -7, -4, -8, 2, -3, 12, -31, -18, 5 }, - { -7, -11, 6, -8, 4, -3, -12, 0, -1, -6, -3, 0, 5, 9, 7, 2, + { -7, -11, 6, -8, 4, -3, -12, 0, -1, -6, -3, 0, 5, 9, 7, 2, 1, -8, -6, 8, 2, -5, 7, -1, 16, -10, 16, -12, 18, -1, -25, -12 }, - { 3, -12, 1, 2, -2, -18, -8, -15, -10, -9, 2, -7, 11, -11, 2, -1, + { 3, -12, 1, 2, -2, -18, -8, -15, -10, -9, 2, -7, 11, -11, 2, -1, -1, -1, -9, -6, 3, -14, -2, -1, 2, -13, -7, -9, 19, -5, -17, 2 }, - { 7, 1, -8, 7, 17, -13, -10, 5, 7, 1, -6, 4, 9, -4, 0, 3, + { 7, 1, -8, 7, 17, -13, -10, 5, 7, 1, -6, 4, 9, -4, 0, 3, 8, 1, -14, -9, 4, 7, -9, 0, 6, -5, -12, -2, 25, -2, -19, 1 }, - { 7, -3, 6, -3, 1, 6, -7, 0, 10, 0, 4, -5, -17, -4, 4, -1, + { 7, -3, 6, -3, 1, 6, -7, 0, 10, 0, 4, -5, -17, -4, 4, -1, 0, -3, -7, 19, 24, -1, 21, 8, 10, 9, 8, -1, 23, -2, -18, -2 }, - { 3, -3, 0, 5, 8, -2, -9, 2, 9, 6, 19, 8, 2, 6, -9, -2, + { 3, -3, 0, 5, 8, -2, -9, 2, 9, 6, 19, 8, 2, 6, -9, -2, -4, -3, -8, 7, -7, -8, 5, 4, 26, -6, 7, 18, 24, 0, -13, 4 }, - { 0, -13, -11, -1, 3, -9, 5, 4, -7, 3, 0, 2, -1, 4, -5, 2, + { 0, -13, -11, -1, 3, -9, 5, 4, -7, 3, 0, 2, -1, 4, -5, 2, 9, -2, -11, 15, 1, -21, 1, -1, 0, 4, -14, -4, 24, -16, -13, 1 }, - { 1, -9, -8, 0, 0, -4, 11, -1, 14, 16, 0, 17, -2, -9, -12, 0, + { 1, -9, -8, 0, 0, -4, 11, -1, 14, 16, 0, 17, -2, -9, -12, 0, -1, -14, -9, -14, 0, -2, 19, 4, 6, 4, 4, -11, 8, -17, -19, -5 }, - { -3, 1, 2, 12, -4, -18, -1, -4, -7, 14, -3, 2, 0, -7, -8, 12, + { -3, 1, 2, 12, -4, -18, -1, -4, -7, 14, -3, 2, 0, -7, -8, 12, -5, -9, 14, 12, -9, -2, 4, -6, 4, 18, -1, -25, 22, 2, -23, -5 }, - { -2, 0, 0, 0, 1, 3, 5, -1, 5, -2, -2, 2, -3, 0, 1, 2, + { -2, 0, 0, 0, 1, 3, 5, -1, 5, -2, -2, 2, -3, 0, 1, 2, 0, -1, 2, -1, -9, -6, -7, -4, -2, 4, -7, -5, 64, -3, -25, 4 }, - { 12, -2, -3, 0, 8, -9, 13, -7, 6, -3, -12, 12, 15, -9, -4, 2, + { 12, -2, -3, 0, 8, -9, 13, -7, 6, -3, -12, 12, 15, -9, -4, 2, 9, -4, -12, 3, 14, 1, 7, -15, 15, 0, -6, -12, 0, -3, -20, 6 }, - { 2, -1, -4, 5, 9, 6, -7, 2, -2, -7, -2, 0, -1, -18, -4, -6, + { 2, -1, -4, 5, 9, 6, -7, 2, -2, -7, -2, 0, -1, -18, -4, -6, -15, -5, 11, 5, -10, -1, 2, 7, 12, -19, -7, 8, 21, -4, -15, 4 }, - { 4, 2, 5, 5, -5, 1, 3, 2, -8, 13, 0, -5, -2, -14, -11, 6, + { 4, 2, 5, 5, -5, 1, 3, 2, -8, 13, 0, -5, -2, -14, -11, 6, 2, 17, 8, -13, 26, -2, 5, -15, -4, -14, 12, -9, 13, -21, -23, -4 }, - { 2, -3, -2, -3, 3, -2, 6, 9, -9, 13, 4, 2, 12, -3, -3, 1, + { 2, -3, -2, -3, 3, -2, 6, 9, -9, 13, 4, 2, 12, -3, -3, 1, -17, -22, -3, 4, 3, -2, 1, -9, 1, -6, 11, -13, 14, 0, -15, 6 }, - { -16, -4, 17, -2, -20, -11, 11, 10, 5, -8, 16, 2, -17, -14, 11, 11, + { -16, -4, 17, -2, -20, -11, 11, 10, 5, -8, 16, 2, -17, -14, 11, 11, -6, -11, -7, 12, 12, -10, -6, 5, 8, -4, -2, -5, 28, 3, -13, 4 }, - { 0, -3, 3, -7, 6, 8, -12, 20, -19, 18, -11, 10, -5, 0, -9, 11, + { 0, -3, 3, -7, 6, 8, -12, 20, -19, 18, -11, 10, -5, 0, -9, 11, 3, 0, -2, 9, -7, -5, 18, 3, -2, -16, 1, 6, 12, -7, -16, 1 }, - { 4, 1, 5, -5, 15, 2, -8, 3, 5, -11, 15, -3, 8, -8, -1, 7, + { 4, 1, 5, -5, 15, 2, -8, 3, 5, -11, 15, -3, 8, -8, -1, 7, 4, 7, -2, 6, -9, 5, 12, 2, 33, -2, -6, -18, 4, 0, -18, 11 }, - { 3, -1, 1, -1, 0, 1, 4, -1, -5, 0, 1, 0, 4, 2, -1, 4, + { 3, -1, 1, -1, 0, 1, 4, -1, -5, 0, 1, 0, 4, 2, -1, 4, -3, 2, 0, -2, 4, 6, -1, 6, 42, 19, -4, -37, 19, 1, -15, -4 }, - { 2, 0, -5, 0, 10, 0, 0, -5, 3, 0, 0, -3, -3, 0, 2, -4, + { 2, 0, -5, 0, 10, 0, 0, -5, 3, 0, 0, -3, -3, 0, 2, -4, -10, 2, -6, 4, 4, 1, 27, -7, 17, -34, 5, -9, 15, -16, -7, -5 }, - { -2, 7, 7, -2, 9, -2, -15, 11, 11, 7, 5, 1, 15, 1, -9, 31, + { -2, 7, 7, -2, 9, -2, -15, 11, 11, 7, 5, 1, 15, 1, -9, 31, 2, -15, 2, 4, 3, 4, -1, -8, 2, -7, 6, -17, 11, -14, -11, 2 }, - { 1, 1, -11, 9, 9, -6, -14, -11, -10, 8, -3, 11, 16, -9, -8, -13, + { 1, 1, -11, 9, 9, -6, -14, -11, -10, 8, -3, 11, 16, -9, -8, -13, -8, 9, 0, 6, 6, -2, 13, -8, -2, 3, 13, -3, 10, -6, -17, 4 }, - { 14, 5, 4, -6, -12, 10, -7, 8, 21, -8, -30, 15, -2, 1, 11, -9, + { 14, 5, 4, -6, -12, 10, -7, 8, 21, -8, -30, 15, -2, 1, 11, -9, -5, 1, 0, -1, -1, -6, -2, 3, -5, 7, 9, 5, -5, 2, 0, 1 }, - { -1, 2, 20, -17, -15, 3, 3, 7, 11, -17, -13, -6, -3, 18, 17, -15, + { -1, 2, 20, -17, -15, 3, 3, 7, 11, -17, -13, -6, -3, 18, 17, -15, -4, -4, -5, 22, 14, -14, -2, -10, -7, 11, 8, -7, -3, 0, -7, 11 }, - { 7, -11, -7, -8, -14, 22, 5, 2, 6, 13, -12, -2, 10, 3, 0, -21, + { 7, -11, -7, -8, -14, 22, 5, 2, 6, 13, -12, -2, 10, 3, 0, -21, -4, 20, 3, 10, 21, -10, -12, 8, 11, 2, -5, 2, 1, 3, -1, 15 }, - { -1, -2, -1, -2, -13, 8, -4, 0, 7, -2, -17, 8, 18, 5, 3, 8, + { -1, -2, -1, -2, -13, 8, -4, 0, 7, -2, -17, 8, 18, 5, 3, 8, -8, -2, 3, -4, 14, -18, -13, 14, 15, -13, -1, -2, 4, 11, 1, 12 }, - { 13, -6, -4, -16, -17, 16, 21, -2, 5, -11, -9, 19, 21, -17, -3, -17, + { 13, -6, -4, -16, -17, 16, 21, -2, 5, -11, -9, 19, 21, -17, -3, -17, 3, 12, 8, -12, -6, 1, -7, 9, 9, -7, -5, -1, -3, 5, -6, -4 }, - { 11, 5, 12, -20, -6, 10, 4, 12, 8, -5, -10, 15, 13, 14, 10, -15, + { 11, 5, 12, -20, -6, 10, 4, 12, 8, -5, -10, 15, 13, 14, 10, -15, -13, 1, 6, 14, 15, -17, -13, 4, -5, 10, 7, -6, -8, -3, -4, 12 }, - { 25, -1, 7, -5, -7, 11, 1, 17, 13, -15, -14, -4, 5, 3, 8, -3, + { 25, -1, 7, -5, -7, 11, 1, 17, 13, -15, -14, -4, 5, 3, 8, -3, -2, 2, 0, 6, 16, -12, -6, -4, 4, -3, 7, -10, -3, -7, -13, 7 }, - { -8, 10, -3, -13, 5, 2, 4, 9, 9, -17, -13, 2, 11, 1, 6, -4, + { -8, 10, -3, -13, 5, 2, 4, 9, 9, -17, -13, 2, 11, 1, 6, -4, 8, -10, 4, 1, 19, -15, -4, 12, 31, 7, -5, -17, -4, 9, -2, 7 }, - { 14, -6, -6, -6, -14, 13, 17, -5, 4, -14, -9, 7, 7, -9, 3, -16, + { 14, -6, -6, -6, -14, 13, 17, -5, 4, -14, -9, 7, 7, -9, 3, -16, -15, 11, 11, 6, 4, -11, -19, 3, 5, 8, 13, -14, -14, 3, -4, 12 }, - { -2, -4, 10, -4, -7, -1, 27, 5, 2, -16, -18, 4, 12, -2, -3, -2, + { -2, -4, 10, -4, -7, -1, 27, 5, 2, -16, -18, 4, 12, -2, -3, -2, -1, 1, -8, -12, 3, -4, 8, 15, 2, 4, 9, -13, -14, 9, -7, 5 }, - { 4, 2, -10, -5, -7, 2, 1, 4, -1, -6, -15, 6, 1, 10, 5, -10, + { 4, 2, -10, -5, -7, 2, 1, 4, -1, -6, -15, 6, 1, 10, 5, -10, -9, -1, 13, -3, 5, -21, -11, 8, 8, 5, 27, -21, -18, -5, -1, 15 }, - { 11, 1, -16, -8, -11, 0, 5, -8, -12, -13, -17, 22, 4, -6, -1, -18, + { 11, 1, -16, -8, -11, 0, 5, -8, -12, -13, -17, 22, 4, -6, -1, -18, -10, 0, 19, 2, -2, -8, -7, -3, 2, -2, -9, -17, -5, 4, 4, 10 }, - { 8, -6, -19, -5, -4, 12, 14, 15, 10, -9, -1, -9, 19, 12, 0, -1, + { 8, -6, -19, -5, -4, 12, 14, 15, 10, -9, -1, -9, 19, 12, 0, -1, 2, 4, 7, 9, 16, -16, -14, 9, -4, 3, 1, 0, -2, 10, -1, -1 }, - { 12, -8, 12, -9, 0, 25, 7, 9, 2, -31, -9, -4, 15, 4, -5, 1, + { 12, -8, 12, -9, 0, 25, 7, 9, 2, -31, -9, -4, 15, 4, -5, 1, -10, 11, 8, 10, 0, -6, 5, 11, -1, -6, 4, -10, -9, 6, 4, 5 }, - { 14, 6, -17, -2, 17, 12, -9, 2, 0, -25, -14, 5, 20, 14, 8, -20, + { 14, 6, -17, -2, 17, 12, -9, 2, 0, -25, -14, 5, 20, 14, 8, -20, 5, 2, -2, -3, 9, -13, -3, -1, -6, 3, 7, -6, 0, 2, 3, 1 }, - { 8, 4, -15, -3, 10, 18, -4, 13, 8, -22, -10, 9, 19, -15, 7, -5, + { 8, 4, -15, -3, 10, 18, -4, 13, 8, -22, -10, 9, 19, -15, 7, -5, -13, 12, -4, 9, 2, -9, -6, 0, 2, 1, -9, -6, 6, 1, -1, 11 }, - { 4, 1, 4, -5, -10, 18, 7, 2, -4, -9, -11, 0, 32, -7, 4, -16, + { 4, 1, 4, -5, -10, 18, 7, 2, -4, -9, -11, 0, 32, -7, 4, -16, -1, 0, 6, 3, 6, -3, -14, 16, 9, -2, 7, -1, 0, -5, 5, -3 }, - { -3, 2, 3, -8, -6, 4, 6, 2, 4, -12, -15, 2, 8, 8, 9, -3, + { -3, 2, 3, -8, -6, 4, 6, 2, 4, -12, -15, 2, 8, 8, 9, -3, -18, 6, 34, 11, 12, -15, -1, 2, 9, 2, -4, -4, 2, 4, 2, -3 }, - { 18, -6, -12, -8, -1, 15, 20, -4, -1, -11, -5, 6, 6, -11, -15, -7, + { 18, -6, -12, -8, -1, 15, 20, -4, -1, -11, -5, 6, 6, -11, -15, -7, 3, 7, 10, 2, 8, -10, -5, 8, 15, -5, 5, -17, -13, 13, 11, 7 }, - { 8, -4, -6, -1, -14, -3, 6, -2, 1, -5, -1, 10, 10, -15, 5, 0, + { 8, -4, -6, -1, -14, -3, 6, -2, 1, -5, -1, 10, 10, -15, 5, 0, -10, -4, -3, 7, -4, -19, -15, 27, 11, 18, 3, -19, -2, 6, 0, 12 }, - { 12, 0, -5, 0, 4, -5, 1, 5, 10, -7, -11, 21, 29, 1, -2, 1, + { 12, 0, -5, 0, 4, -5, 1, 5, 10, -7, -11, 21, 29, 1, -2, 1, -4, -11, -1, 13, 11, -20, -1, 4, 4, 4, -5, 6, -13, -2, 11, 9 }, - { 2, -7, -7, -3, -10, -1, 20, 12, 1, -19, -19, -1, 5, 4, -7, -25, + { 2, -7, -7, -3, -10, -1, 20, 12, 1, -19, -19, -1, 5, 4, -7, -25, 14, 1, -3, 2, 12, -4, -3, -3, -2, 6, 1, 0, 3, 2, 5, -1 }, - { 12, -8, 3, -12, -10, 10, 13, 0, 23, -14, -18, 10, 0, 15, 3, -12, + { 12, -8, 3, -12, -10, 10, 13, 0, 23, -14, -18, 10, 0, 15, 3, -12, -3, -5, 5, -4, 2, -14, -10, 8, 2, 9, -1, -11, -3, 5, 13, 2 }, - { 9, -6, 7, -7, -30, 17, 6, 13, 1, -14, 0, -1, 6, -9, 8, 3, + { 9, -6, 7, -7, -30, 17, 6, 13, 1, -14, 0, -1, 6, -9, 8, 3, -4, 0, -1, -7, -5, -13, -19, -3, -4, 4, -6, -2, -13, 1, -2, 3 }, - { 10, 1, 3, -18, -26, 17, 4, -16, 4, -3, -13, -4, -6, -11, -4, -21, + { 10, 1, 3, -18, -26, 17, 4, -16, 4, -3, -13, -4, -6, -11, -4, -21, 7, 8, 2, 5, 13, -6, 1, 5, 8, 7, 9, -6, -6, 1, -1, 2 }, - { -3, -1, 0, -2, -2, 0, -1, 3, 4, -14, -8, -9, 13, 2, 50, -23, + { -3, -1, 0, -2, -2, 0, -1, 3, 4, -14, -8, -9, 13, 2, 50, -23, -8, 8, 7, 11, 16, 3, -7, 0, -2, 6, 5, -1, 1, -2, 4, 3 }, - { 1, 3, 1, 1, -6, 3, 6, 6, 2, -2, -3, 10, 2, -8, -5, -5, + { 1, 3, 1, 1, -6, 3, 6, 6, 2, -2, -3, 10, 2, -8, -5, -5, 5, 4, 4, -2, 10, -8, -40, -1, 21, 8, 3, -4, -1, 13, 4, 7 }, - { 2, 0, -4, -8, 5, 2, 7, -5, 5, -8, -4, -1, 12, 2, 12, -13, + { 2, 0, -4, -8, 5, 2, 7, -5, 5, -8, -4, -1, 12, 2, 12, -13, -9, 0, 1, -12, 9, -43, 1, -5, 12, 1, 3, 6, 1, -1, 3, -2 }, - { 6, -2, -1, 1, 0, 4, 8, 14, 4, -7, -23, -5, 23, -17, -6, -15, + { 6, -2, -1, 1, 0, 4, 8, 14, 4, -7, -23, -5, 23, -17, -6, -15, -8, 7, 10, -1, 7, -16, 4, -6, 2, 3, -3, -3, -1, 8, -1, 4 }, - { 10, 4, -4, 1, 7, -3, 2, 11, 4, -6, -3, 8, 5, 4, 1, -45, + { 10, 4, -4, 1, 7, -3, 2, 11, 4, -6, -3, 8, 5, 4, 1, -45, -6, -4, 4, 2, 1, -14, -10, 1, 1, 6, 2, -8, -1, -3, 3, 3 }, - { 1, -1, 2, -3, -8, 9, 3, 3, -2, -5, -8, 8, 7, -7, -4, -6, + { 1, -1, 2, -3, -8, 9, 3, 3, -2, -5, -8, 8, 7, -7, -4, -6, 5, -9, 11, -2, 46, -5, -1, 9, -2, 0, 3, -5, -3, -5, 7, 0 }, - { -4, 1, -2, -1, -11, 11, 8, -3, -2, -10, 0, 4, 9, 9, -17, -17, + { -4, 1, -2, -1, -11, 11, 8, -3, -2, -10, 0, 4, 9, 9, -17, -17, -34, -4, -5, -7, -3, -12, -3, 11, 18, 3, -2, -5, -18, -5, -3, 6 }, - { 7, -5, -3, 1, -4, -3, -5, -1, 2, 5, -2, 3, -10, 12, -18, -5, + { 7, -5, -3, 1, -4, -3, -5, -1, 2, 5, -2, 3, -10, 12, -18, -5, -10, 12, -9, 4, -6, 2, 0, 16, -17, 15, 14, -12, -10, -2, -9, -1 }, - { 4, -5, -3, -5, -3, -1, 7, 18, -7, 12, 3, 5, -8, -4, -20, 1, + { 4, -5, -3, -5, -3, -1, 7, 18, -7, 12, 3, 5, -8, -4, -20, 1, -25, 1, -8, 13, -10, 8, -19, -1, -8, 10, 6, -9, -1, 0, 12, 4 }, - { -4, 5, 0, -1, 2, 5, -8, -2, -6, 4, -8, 9, 3, 2, -7, 4, + { -4, 5, 0, -1, 2, 5, -8, -2, -6, 4, -8, 9, 3, 2, -7, 4, -25, 13, -23, 10, 14, 15, -11, 3, -18, 4, 16, -4, 1, -10, -10, 3 }, - { 5, -3, -1, -3, 4, 1, -3, -4, -5, 1, -12, 14, -7, 11, -15, 6, + { 5, -3, -1, -3, 4, 1, -3, -4, -5, 1, -12, 14, -7, 11, -15, 6, -6, 24, -4, 13, -1, 15, -13, 8, 3, 7, -5, 2, 2, 0, 3, -7 }, - { -3, 1, 0, 8, 6, -1, 6, 5, -5, -2, -12, 4, 0, -2, -3, 5, + { -3, 1, 0, 8, 6, -1, 6, 5, -5, -2, -12, 4, 0, -2, -3, 5, -6, 0, -8, 9, -10, 4, -28, 12, -20, 11, -13, 7, -18, 1, -11, 1 }, - { 1, -4, -15, 5, 0, -13, -5, 13, -11, 4, -4, -5, 5, -14, -16, 0, + { 1, -4, -15, 5, 0, -13, -5, 13, -11, 4, -4, -5, 5, -14, -16, 0, -14, 5, -20, 12, 10, -7, -5, 6, 6, 22, 6, -4, -2, 3, 8, 11 }, - { 13, -11, -2, 16, 16, -7, 0, 20, -7, -1, 0, 5, -9, 12, -2, -5, + { 13, -11, -2, 16, 16, -7, 0, 20, -7, -1, 0, 5, -9, 12, -2, -5, -22, 5, -10, 12, -6, 11, 9, 21, -8, 15, 4, 0, -8, -4, -4, 10 }, - { 18, -4, -13, 0, 1, -15, -1, -3, 2, 10, -1, 6, 1, -4, -20, -5, + { 18, -4, -13, 0, 1, -15, -1, -3, 2, 10, -1, 6, 1, -4, -20, -5, -8, 6, -8, 17, -5, 5, -10, 8, -22, 6, -5, -2, 8, -17, 8, 2 }, - { 1, -2, -9, 6, -31, -8, -8, 8, 0, 5, -9, -4, 2, 3, -12, 11, + { 1, -2, -9, 6, -31, -8, -8, 8, 0, 5, -9, -4, 2, 3, -12, 11, -18, 10, -5, 3, -11, 13, -6, 11, -3, 12, -7, 3, -9, -1, 2, 11 }, - { -9, -6, 21, -8, -15, 4, -11, 12, -11, 17, -1, 2, -6, 0, -15, 13, + { -9, -6, 21, -8, -15, 4, -11, 12, -11, 17, -1, 2, -6, 0, -15, 13, -12, 19, 0, 2, -6, -3, -9, 10, 3, 17, -2, 5, -10, -3, 0, 1 }, - { 4, -6, 5, -10, 1, -5, 1, 0, 0, 0, 2, 7, -2, 2, -2, 0, + { 4, -6, 5, -10, 1, -5, 1, 0, 0, 0, 2, 7, -2, 2, -2, 0, -4, 3, -4, 1, -12, 6, -49, 16, -10, 13, 0, -2, 8, 6, 1, 8 }, - { 5, -8, -7, 9, 13, -5, 7, 0, 10, 11, -4, -3, -1, 13, -14, 6, + { 5, -8, -7, 9, 13, -5, 7, 0, 10, 11, -4, -3, -1, 13, -14, 6, -15, -6, -14, 16, 15, 1, -18, -4, -20, 20, -7, -1, -9, -2, -10, 10 }, - { -12, 4, 0, 10, 0, 3, 8, 4, -27, -1, -2, 19, -4, 2, -13, 3, + { -12, 4, 0, 10, 0, 3, 8, 4, -27, -1, -2, 19, -4, 2, -13, 3, 1, 9, -12, 1, -22, 19, -5, 4, -9, 12, 2, -9, -8, 11, -3, 7 }, - { 4, -5, 11, -6, 17, -17, 5, -4, -2, -6, 1, -5, 2, 4, -14, 6, + { 4, -5, 11, -6, 17, -17, 5, -4, -2, -6, 1, -5, 2, 4, -14, 6, -20, 19, -20, 12, -21, 5, -14, 13, -2, 11, 4, -3, 0, -10, -4, -2 }, - { -2, -1, -3, 8, -9, -7, -22, -3, -24, 13, -2, 10, -15, 5, -9, 4, + { -2, -1, -3, 8, -9, -7, -22, -3, -24, 13, -2, 10, -15, 5, -9, 4, -7, 0, -5, 15, -8, 11, -13, 6, -4, 19, -8, 12, -4, 6, 9, 7 }, - { 2, -3, 2, -1, 0, 3, 1, 2, 1, -4, -2, -3, 1, 5, -12, 6, + { 2, -3, 2, -1, 0, 3, 1, 2, 1, -4, -2, -3, 1, 5, -12, 6, -16, 14, -23, 10, -14, 17, -15, 16, -2, 9, -25, 9, -10, 16, 4, 9 }, - { -3, 7, -8, -3, 2, 2, -4, -8, -9, 10, 3, -11, 25, -10, -28, 27, + { -3, 7, -8, -3, 2, 2, -4, -8, -9, 10, 3, -11, 25, -10, -28, 27, -9, 7, -13, 9, -2, 4, -12, -8, -14, 6, 7, -10, 3, 3, -3, 5 }, - { -8, -3, 1, -10, 8, -3, -9, -4, 13, 7, 2, 4, -10, 4, 3, 7, + { -8, -3, 1, -10, 8, -3, -9, -4, 13, 7, 2, 4, -10, 4, 3, 7, -18, 2, -22, 15, 4, 20, -7, 5, -6, 13, -1, 4, -7, -6, 6, 13 }, - { -2, 3, 0, 2, -4, -2, 0, 0, 1, 2, -2, -5, 0, 1, -4, 0, + { -2, 3, 0, 2, -4, -2, 0, 0, 1, 2, -2, -5, 0, 1, -4, 0, -2, -3, 1, 2, -1, 2, -8, -1, -24, 68, -3, 8, 3, 3, -1, -1 }, - { -15, -2, -9, -7, -1, 8, -14, 8, 3, 6, 0, -1, -8, 8, -23, 2, + { -15, -2, -9, -7, -1, 8, -14, 8, 3, 6, 0, -1, -8, 8, -23, 2, -14, 17, -15, 8, -4, 7, -18, 0, -8, -3, -1, -4, -10, 4, -1, 4 }, - { 8, 0, 2, -7, 0, 5, 1, 3, -11, 4, -8, 14, 3, 20, 1, 26, + { 8, 0, 2, -7, 0, 5, 1, 3, -11, 4, -8, 14, 3, 20, 1, 26, -11, 13, -13, 20, -2, 0, -8, 2, -6, 6, -1, 9, 3, -6, -3, 10 }, - { 5, 0, -1, -7, 10, 1, -3, 5, 4, 7, -5, -1, -3, -1, 12, -3, + { 5, 0, -1, -7, 10, 1, -3, 5, 4, 7, -5, -1, -3, -1, 12, -3, -15, 7, -9, 22, -19, 8, -9, 4, -23, 13, -14, 6, -6, -14, -4, 7 }, - { 14, -5, -8, -10, 25, 3, -23, -7, -28, 0, -1, -9, 4, 1, -13, 20, + { 14, -5, -8, -10, 25, 3, -23, -7, -28, 0, -1, -9, 4, 1, -13, 20, -8, 10, -16, 8, 12, -13, -21, 5, -13, 11, -2, 1, 12, -7, 2, -10 }, - { -5, -4, 9, 5, -6, 35, -7, 8, 15, 2, -1, -9, -6, 2, -18, 7, + { -5, -4, 9, 5, -6, 35, -7, 8, 15, 2, -1, -9, -6, 2, -18, 7, -15, 6, -3, 2, 8, 12, -30, 7, -4, 20, 2, 6, 13, -6, -4, 0 }, - { 1, 8, -9, 9, -5, 12, -9, 16, -9, 16, -17, 14, -13, 15, -18, 14, + { 1, 8, -9, 9, -5, 12, -9, 16, -9, 16, -17, 14, -13, 15, -18, 14, -15, 17, -12, 14, -13, 7, -16, 13, -9, 5, -11, 10, -9, 6, -12, 13 }, - { -10, -4, 5, 3, 1, 6, 8, -14, -5, 15, 7, 4, 8, 7, -22, 8, + { -10, -4, 5, 3, 1, 6, 8, -14, -5, 15, 7, 4, 8, 7, -22, 8, -7, -8, -15, 26, 1, 13, -3, 17, -5, 9, -2, 4, -6, 3, -8, 9 }, - { 8, -3, 2, 3, 3, 1, -2, -1, -11, 8, -4, 0, -6, -5, -1, 13, + { 8, -3, 2, 3, 3, 1, -2, -1, -11, 8, -4, 0, -6, -5, -1, 13, -37, 9, 1, -6, -10, -2, -10, 11, 8, 13, -3, -2, -6, 8, -4, 13 }, - { 3, 2, -3, -4, -4, 7, -8, 9, -8, 9, -20, 12, -19, 15, -18, 17, + { 3, 2, -3, -4, -4, 7, -8, 9, -8, 9, -20, 12, -19, 15, -18, 17, -15, 7, -1, 20, -11, 6, -6, 3, 1, 9, 2, -14, -2, -2, 2, 1 }, - { -7, 1, -1, -3, -6, 4, 4, -3, 3, -1, 5, -4, 3, 2, -1, 9, + { -7, 1, -1, -3, -6, 4, 4, -3, 3, -1, 5, -4, 3, 2, -1, 9, -59, 5, -4, 30, 3, 3, -2, -3, -1, 2, 2, 1, -1, -1, -2, 1 }, - { 0, -3, 2, 0, -1, -8, 0, 2, -3, 4, -4, 1, 10, 6, -6, 8, + { 0, -3, 2, 0, -1, -8, 0, 2, -3, 4, -4, 1, 10, 6, -6, 8, -7, 4, 10, 11, -41, 27, -20, 3, -3, 8, 1, 11, -5, -8, 0, 4 }, - { 5, 1, 4, -2, 1, 2, -1, 6, -7, 2, 11, 4, 0, 0, -8, 7, + { 5, 1, 4, -2, 1, 2, -1, 6, -7, 2, 11, 4, 0, 0, -8, 7, -10, 0, 0, 8, 2, 10, -1, 1, -2, 44, -2, -21, -12, -3, -1, 2 }, - { -4, 4, -2, -2, 6, -8, 2, 1, -10, 14, 8, 6, 5, 1, -2, 4, + { -4, 4, -2, -2, 6, -8, 2, 1, -10, 14, 8, 6, 5, 1, -2, 4, -13, 4, 2, 5, 10, -2, -21, 32, -3, 18, 9, -6, -9, -9, 10, 2 }, - { 9, -16, -6, -2, 1, 4, 22, 2, -2, 1, -3, -2, -9, 3, 16, 19, + { 9, -16, -6, -2, 1, 4, 22, 2, -2, 1, -3, -2, -9, 3, 16, 19, -24, -6, -6, -5, -8, -7, 8, -7, -1, -12, 5, -3, 0, 4, 2, -3 }, - { 10, 3, -16, -4, -1, 13, 4, 4, 1, -3, 1, -6, -14, 18, 3, 8, + { 10, 3, -16, -4, -1, 13, 4, 4, 1, -3, 1, -6, -14, 18, 3, 8, -8, -28, -16, 4, 4, 2, 12, 7, 9, -4, -4, 5, -1, -1, 2, 2 }, - { -5, -13, -22, -3, -8, 21, -2, -9, 21, -4, -9, 5, -8, 15, 5, 1, + { -5, -13, -22, -3, -8, 21, -2, -9, 21, -4, -9, 5, -8, 15, 5, 1, -5, -9, -7, -2, -5, -5, -1, -5, -5, -5, 3, 10, -4, 0, -7, -2 }, - { 5, -10, -18, 2, 20, 4, 13, -10, 8, -15, -11, -3, -1, 16, 10, 9, + { 5, -10, -18, 2, 20, 4, 13, -10, 8, -15, -11, -3, -1, 16, 10, 9, -8, 6, 7, -5, 6, 11, 5, 17, -4, 7, -11, 5, -3, -6, 2, 1 }, - { 3, -5, -19, 1, 1, -3, -2, -25, -11, -17, 0, -13, -4, 10, 10, 2, + { 3, -5, -19, 1, 1, -3, -2, -25, -11, -17, 0, -13, -4, 10, 10, 2, -5, 4, 0, 3, -3, -5, -10, -2, 13, -22, 0, 3, -11, -5, 7, -1 }, - { 12, -14, -29, 6, -1, 10, 7, -17, -12, 14, 3, 9, -9, 9, 7, 6, + { 12, -14, -29, 6, -1, 10, 7, -17, -12, 14, 3, 9, -9, 9, 7, 6, -3, -13, 0, 5, 3, -1, -6, -1, 0, 2, 4, -12, -5, -1, 2, 11 }, - { 12, -15, -7, -2, -12, 17, 20, -16, -2, -12, -6, 15, -6, 12, 11, 9, + { 12, -15, -7, -2, -12, 17, 20, -16, -2, -12, -6, 15, -6, 12, 11, 9, 7, -6, 7, -4, -19, 6, 2, 2, 3, -11, -10, -4, -5, -3, 3, 2 }, - { 11, -22, -6, 0, 8, 18, 3, -11, -4, -7, -15, -17, -12, 6, 16, 4, + { 11, -22, -6, 0, 8, 18, 3, -11, -4, -7, -15, -17, -12, 6, 16, 4, -9, 4, -5, 3, 6, -16, 10, -7, -7, -3, 5, 0, 1, -15, -4, 5 }, - { 12, -22, -16, 5, -6, 8, 12, -4, -9, -17, -11, 3, 5, 8, -17, 0, + { 12, -22, -16, 5, -6, 8, 12, -4, -9, -17, -11, 3, 5, 8, -17, 0, 11, -4, -13, -6, 2, -1, -1, 3, 3, -11, -12, -1, 1, 1, 12, -2 }, - { 8, -10, -33, -5, -3, -6, 1, -7, -8, -4, -6, -1, 5, -4, -6, -12, + { 8, -10, -33, -5, -3, -6, 1, -7, -8, -4, -6, -1, 5, -4, -6, -12, -16, -8, 11, 8, -14, 7, 12, 11, 4, -14, -3, 6, -7, -5, -3, 3 }, - { 0, -8, -7, 2, -4, 24, 2, -9, -11, -3, -7, 11, -12, 17, 1, -1, + { 0, -8, -7, 2, -4, 24, 2, -9, -11, -3, -7, 11, -12, 17, 1, -1, 3, -5, -7, 12, 4, 11, 0, 3, 2, -18, -3, 4, 7, -6, 3, 15 }, - { 10, -15, -16, -2, -4, -9, 7, -15, -6, 2, -16, 13, -8, 7, 19, -21, + { 10, -15, -16, -2, -4, -9, 7, -15, -6, 2, -16, 13, -8, 7, 19, -21, -4, -12, -9, -3, -3, 6, 11, -3, -1, -19, 3, -7, -9, -4, 3, -6 }, - { -5, -10, -21, 0, -3, -7, 18, -21, 15, -5, -12, -4, -13, 2, 6, -9, + { -5, -10, -21, 0, -3, -7, 18, -21, 15, -5, -12, -4, -13, 2, 6, -9, -9, -11, -4, 13, -3, 6, 4, -1, 7, -9, -4, 9, 5, 2, 6, 3 }, - { 15, -1, -27, -2, 10, 3, 7, -8, 9, -2, 7, 1, -2, -5, 18, 9, + { 15, -1, -27, -2, 10, 3, 7, -8, 9, -2, 7, 1, -2, -5, 18, 9, -11, -17, -2, 7, -9, 11, 10, 0, -8, 6, -16, -3, 2, -7, 3, 11 }, - { 4, -9, -39, 19, 6, -13, 13, -5, -5, -15, -2, 9, 0, 4, 14, 6, + { 4, -9, -39, 19, 6, -13, 13, -5, -5, -15, -2, 9, 0, 4, 14, 6, -10, -4, -5, 2, -4, -2, 5, -11, 3, 3, -2, -2, -7, 9, 7, -10 }, - { 5, -11, -8, 10, -2, 12, 16, 0, 12, -2, -6, 8, 14, 8, 7, 1, + { 5, -11, -8, 10, -2, 12, 16, 0, 12, -2, -6, 8, 14, 8, 7, 1, 18, -30, 4, 10, -4, -6, 2, -11, 9, -10, -8, 5, 0, 0, -7, 6 }, - { -1, -16, -10, 11, 0, 13, 12, -4, -4, -5, -21, 12, 4, 13, 14, -7, + { -1, -16, -10, 11, 0, 13, 12, -4, -4, -5, -21, 12, 4, 13, 14, -7, 6, -16, -13, 8, 2, 9, 15, -12, 1, -9, -22, 10, -9, 9, 9, -7 }, - { 4, -12, -27, 1, -2, 11, 15, 3, 14, -14, -9, 0, -9, 16, 22, 10, + { 4, -12, -27, 1, -2, 11, 15, 3, 14, -14, -9, 0, -9, 16, 22, 10, 16, -10, 5, -5, -9, 1, 1, 6, 6, -4, 2, -17, -5, -6, -15, -1 }, - { 7, -12, -17, 1, -9, 5, 20, -7, 3, 23, -8, -8, -8, -1, 13, 17, + { 7, -12, -17, 1, -9, 5, 20, -7, 3, 23, -8, -8, -8, -1, 13, 17, -7, -13, 4, -4, 7, 14, 8, 11, -3, -3, 4, 0, 4, 6, -1, -9 }, - { 7, -15, -15, -4, 10, 12, 3, -13, 6, 14, 9, -8, -15, 14, 23, -5, + { 7, -15, -15, -4, 10, 12, 3, -13, 6, 14, 9, -8, -15, 14, 23, -5, -10, -5, 1, 15, -10, -7, 1, 9, 4, -13, -10, 10, 7, -3, 2, 3 }, - { 4, -10, -14, 0, 3, 4, 0, -9, -3, -4, -11, 2, -17, 8, 2, 15, + { 4, -10, -14, 0, 3, 4, 0, -9, -3, -4, -11, 2, -17, 8, 2, 15, 6, -12, -12, 15, -5, 17, 18, 3, -3, -3, -4, -6, -8, 13, 4, 10 }, - { -2, -18, -26, 10, -4, 10, 13, 4, -4, -16, -7, -17, -3, 5, -4, 2, + { -2, -18, -26, 10, -4, 10, 13, 4, -4, -16, -7, -17, -3, 5, -4, 2, -15, -10, -1, -8, -7, -3, 2, 2, 8, -10, -7, 2, 2, -4, 4, -1 }, - { 4, -19, -5, -1, -1, -6, 2, -8, 10, -16, -28, -6, 8, -1, 11, 28, + { 4, -19, -5, -1, -1, -6, 2, -8, 10, -16, -28, -6, 8, -1, 11, 28, 2, -10, -4, 6, -6, 6, 11, 15, -4, -2, 7, 3, 7, -7, 4, 1 }, - { -3, -6, -10, -5, 13, 18, 10, -15, -5, -3, -13, 5, 1, 2, 18, -5, + { -3, -6, -10, -5, 13, 18, 10, -15, -5, -3, -13, 5, 1, 2, 18, -5, -10, -10, -7, 4, 2, 1, 5, 4, 2, 5, 4, 8, -9, -17, 7, 7 }, - { 20, -12, -2, -4, 5, 14, 7, -11, -1, -16, -6, -4, -11, 17, 14, 0, + { 20, -12, -2, -4, 5, 14, 7, -11, -1, -16, -6, -4, -11, 17, 14, 0, -8, -10, -8, 10, 3, 5, 10, -16, 3, -8, -14, 10, 3, 9, 0, 3 }, - { 12, -10, -36, 0, 7, 15, 2, -16, 2, -1, 0, -1, 5, 4, 5, -3, + { 12, -10, -36, 0, 7, 15, 2, -16, 2, -1, 0, -1, 5, 4, 5, -3, 1, -10, 5, -1, -15, -3, -12, 12, 2, 5, -1, 5, 6, -3, -2, 2 }, - { 17, -15, -31, 23, -4, 15, -2, -3, 6, -7, -5, 1, -12, 4, 6, 8, + { 17, -15, -31, 23, -4, 15, -2, -3, 6, -7, -5, 1, -12, 4, 6, 8, -10, 8, 3, 5, -4, 1, 5, 3, -1, -4, -3, 1, 10, -4, -2, -2 }, - { 6, -18, -5, 12, 10, 12, 14, -11, 15, 2, -9, -6, -5, -2, -9, 4, + { 6, -18, -5, 12, 10, 12, 14, -11, 15, 2, -9, -6, -5, -2, -9, 4, -5, -28, -4, 14, 0, -16, 9, 14, -1, 3, -4, -4, 2, 1, 0, 4 }, - { -5, -14, -31, 8, 16, 7, 13, -13, 5, 6, -16, 10, -5, 2, -2, 2, + { -5, -14, -31, 8, 16, 7, 13, -13, 5, 6, -16, 10, -5, 2, -2, 2, 14, -5, 8, -5, 7, -16, 6, -13, -5, 0, -5, 8, -3, -1, 4, 3 }, - { 1, -2, -1, 0, 6, 5, 2, -4, -3, -1, 0, 1, 4, 2, 43, 28, + { 1, -2, -1, 0, 6, 5, 2, -4, -3, -1, 0, 1, 4, 2, 43, 28, -12, -35, -2, -2, -7, -1, 0, 2, -1, -2, -2, 1, -4, 0, -2, 3 }, - { 2, -9, -22, 12, 3, 3, -7, -4, -19, -22, -14, -4, -1, 21, 9, -3, + { 2, -9, -22, 12, 3, 3, -7, -4, -19, -22, -14, -4, -1, 21, 9, -3, -15, -16, -13, 1, -11, 4, -9, 1, -7, -1, -1, 0, -2, 9, -13, -3 }, - { -1, -3, -23, 0, 2, 12, 3, -9, -4, 7, 3, 9, -10, 1, 27, 28, + { -1, -3, -23, 0, 2, 12, 3, -9, -4, 7, 3, 9, -10, 1, 27, 28, 0, 9, -15, -2, -2, 1, 6, 8, -8, 7, -3, 20, 0, 0, -1, -6 }, - { -1, 11, 8, -2, 1, 5, -6, -1, 4, 2, -4, 0, -1, -5, 4, -6, + { -1, 11, 8, -2, 1, 5, -6, -1, 4, 2, -4, 0, -1, -5, 4, -6, -10, -12, 19, 1, -7, 9, -8, -9, -16, -11, -2, 12, 14, 4, 4, 34 }, - { 17, 7, -6, 1, 4, -10, -5, 4, -11, 3, -18, 4, 14, -13, -3, 1, + { 17, 7, -6, 1, 4, -10, -5, 4, -11, 3, -18, 4, 14, -13, -3, 1, 0, 0, -11, 0, 7, -17, -4, 4, -11, -6, -8, 18, 0, 0, 0, 26 }, - { -6, -7, -1, -1, 11, -8, 1, 3, 2, 11, -6, -6, 10, -3, 1, -3, + { -6, -7, -1, -1, 11, -8, 1, 3, 2, 11, -6, -6, 10, -3, 1, -3, 7, 4, -12, -8, 0, -9, 8, -22, -5, 0, -6, 22, -2, 11, -13, 24 }, - { -3, 4, 0, 3, 9, 10, -1, 3, -9, -12, 1, -5, 18, 0, -3, 8, + { -3, 4, 0, 3, 9, 10, -1, 3, -9, -12, 1, -5, 18, 0, -3, 8, 25, 15, -8, 2, 2, -2, 4, 8, 9, -1, -5, 10, -3, 1, -1, 23 }, - { -5, 2, -9, -1, -3, 0, 3, -1, -10, -4, 0, -13, 16, 9, -1, -14, + { -5, 2, -9, -1, -3, 0, 3, -1, -10, -4, 0, -13, 16, 9, -1, -14, 2, 6, -2, -6, -5, -2, -7, 7, 5, 3, 11, -2, -14, 0, -9, 30 }, - { 4, 6, 6, 5, -3, -1, 4, 5, 10, 0, 5, -4, 7, -11, 14, 14, + { 4, 6, 6, 5, -3, -1, 4, 5, 10, 0, 5, -4, 7, -11, 14, 14, 7, 34, -9, 0, -10, 22, -7, -1, 7, -9, 2, -8, 0, -7, -5, 29 }, - { -4, 3, -1, -4, -3, 5, 1, -4, 0, 2, 4, 2, 1, -1, -10, 1, + { -4, 3, -1, -4, -3, 5, 1, -4, 0, 2, 4, 2, 1, -1, -10, 1, 6, -6, -4, 1, 4, -3, -3, -5, 0, 3, 7, -12, 0, -2, -10, 55 }, - { 5, 9, -1, 0, 4, 9, -21, -9, 4, 2, 6, -7, 11, -7, 1, -5, + { 5, 9, -1, 0, 4, 9, -21, -9, 4, 2, 6, -7, 11, -7, 1, -5, 0, -4, 2, -3, -13, -8, 0, -9, -4, 2, 16, -2, -15, -7, -11, 31 }, - { 8, 2, -1, 0, 3, -5, -5, 5, 1, -1, -9, 1, 0, -6, -2, -1, + { 8, 2, -1, 0, 3, -5, -5, 5, 1, -1, -9, 1, 0, -6, -2, -1, 5, 2, 0, 0, 12, 20, -19, 1, 8, -12, -11, 0, 6, -5, 2, 31 }, - { -1, -1, -2, 1, -1, 3, -9, -5, 8, -2, 5, -1, 0, -2, 4, -2, + { -1, -1, -2, 1, -1, 3, -9, -5, 8, -2, 5, -1, 0, -2, 4, -2, -3, -12, 0, -2, 3, 0, 9, 4, -1, 21, -8, 3, -4, 9, -6, 30 }, - { -4, 0, -7, 17, 10, -12, -2, -10, -12, -3, 10, 0, 11, -4, -13, -3, + { -4, 0, -7, 17, 10, -12, -2, -10, -12, -3, 10, 0, 11, -4, -13, -3, 5, 6, 10, 7, -8, 0, -7, -13, 1, 0, -2, 7, -12, 4, -3, 24 }, - { -13, 9, 4, -2, 2, -4, -14, -1, -3, -5, -10, 4, 13, -2, 5, 13, + { -13, 9, 4, -2, 2, -4, -14, -1, -3, -5, -10, 4, 13, -2, 5, 13, 8, 3, -2, 1, 5, -6, 7, -18, -10, 1, -1, 5, 4, 1, 0, 25 }, - { -5, -1, 18, 12, 8, 8, -16, -1, 1, 1, 1, -4, -5, 3, 3, 4, + { -5, -1, 18, 12, 8, 8, -16, -1, 1, 1, 1, -4, -5, 3, 3, 4, 4, -11, -12, -16, -6, 2, 12, -13, 0, 9, 7, 9, -9, 0, -10, 24 }, - { -4, 1, -3, 0, 2, -4, 4, 1, 5, 0, -3, 2, -3, -2, 2, -1, + { -4, 1, -3, 0, 2, -4, 4, 1, 5, 0, -3, 2, -3, -2, 2, -1, 1, 4, -1, -2, -2, 1, -1, -1, -4, -1, -4, -2, -6, 6, 12, 69 }, - { 8, 5, 11, 0, -15, -4, 13, 6, 0, -4, 9, 1, -5, -3, 15, 0, + { 8, 5, 11, 0, -15, -4, 13, 6, 0, -4, 9, 1, -5, -3, 15, 0, 1, 6, -5, 0, 1, 6, 5, 8, 0, 7, 1, -1, -4, -11, -9, 41 }, - { -4, -9, 32, -6, 0, 7, -4, 6, -6, 1, -6, -2, 4, -8, -5, -3, + { -4, -9, 32, -6, 0, 7, -4, 6, -6, 1, -6, -2, 4, -8, -5, -3, -16, -1, -2, -6, 1, 15, 0, 21, 3, -3, -4, 3, -12, 16, 2, 27 }, - { -6, -5, 1, -9, -5, 3, 7, -3, 5, 5, 14, 13, 20, -7, -1, 12, + { -6, -5, 1, -9, -5, 3, 7, -3, 5, 5, 14, 13, 20, -7, -1, 12, -1, 10, -11, -11, -7, -4, -14, 7, -14, 13, 22, 18, -1, 0, 14, 28 }, - { -8, 3, -2, 0, 5, 6, -1, -4, 1, 3, -7, 3, 1, -15, 4, -9, + { -8, 3, -2, 0, 5, 6, -1, -4, 1, 3, -7, 3, 1, -15, 4, -9, 22, -10, -9, -4, 1, 8, -4, 9, -15, 2, -6, -4, -16, 12, -10, 23 }, - { 0, 0, 2, 0, -1, 3, -3, -1, 3, -5, 7, 1, 5, -5, -8, 1, + { 0, 0, 2, 0, -1, 3, -3, -1, 3, -5, 7, 1, 5, -5, -8, 1, 13, -15, -5, -7, 12, -6, -2, 3, 10, -5, -8, 17, -5, -11, -14, 23 }, - { -7, -4, 6, -4, 5, -6, -5, 2, -4, 11, 9, -4, 2, -2, -4, 6, + { -7, -4, 6, -4, 5, -6, -5, 2, -4, 11, 9, -4, 2, -2, -4, 6, 15, 3, -3, 18, -15, -2, -6, 3, 3, -20, 17, 11, -4, 2, 3, 29 }, - { 6, 1, -6, 2, 3, 0, 0, -3, 3, 3, -1, 3, -4, -6, -6, -7, + { 6, 1, -6, 2, 3, 0, 0, -3, 3, 3, -1, 3, -4, -6, -6, -7, -3, -2, -7, -2, -4, 5, 3, -5, -20, -13, -4, 10, -14, -29, 14, 37 }, - { 3, 4, 3, -6, -4, 5, 0, 3, 2, 3, 0, -2, 4, 0, -3, -5, + { 3, 4, 3, -6, -4, 5, 0, 3, 2, 3, 0, -2, 4, 0, -3, -5, -4, 4, -4, 4, 4, 3, 1, -4, -4, -9, -14, 20, -30, 3, -18, 33 }, - { 0, 2, 5, -2, -4, -2, -1, 2, -6, -3, -2, -2, 2, -5, -1, 4, + { 0, 2, 5, -2, -4, -2, -1, 2, -6, -3, -2, -2, 2, -5, -1, 4, 3, 2, -3, 0, -1, -1, -10, -7, 2, -4, -18, 2, -37, -1, 12, 40 }, - { -7, 2, -1, 0, -2, 4, -8, 1, -4, 12, 7, 4, 15, -7, 1, -9, + { -7, 2, -1, 0, -2, 4, -8, 1, -4, 12, 7, 4, 15, -7, 1, -9, 18, 0, 12, -17, -3, -1, 0, 0, 0, 2, -6, 0, -4, -3, -1, 26 }, - { -6, 4, 8, -5, -6, -2, 2, -1, 1, -1, -15, 8, 7, -1, -17, -4, + { -6, 4, 8, -5, -6, -2, 2, -1, 1, -1, -15, 8, 7, -1, -17, -4, 1, 5, 6, -11, -6, 14, 17, -5, -15, 11, 8, 0, -3, -15, -6, 28 }, - { -1, 0, 0, 0, 1, 0, -1, 0, 1, 3, 2, -2, 3, -1, -1, 2, + { -1, 0, 0, 0, 1, 0, -1, 0, 1, 3, 2, -2, 3, -1, -1, 2, 2, -1, -1, -7, 1, 2, -9, 0, -1, -4, -18, 7, -10, 49, -13, 32 }, - { -1, -3, 4, 1, 2, -5, 1, -7, -1, 5, -9, 4, 4, 25, 1, -1, + { -1, -3, 4, 1, 2, -5, 1, -7, -1, 5, -9, 4, 4, 25, 1, -1, 2, -5, 2, -7, 17, -2, 10, -5, 0, 2, -15, 3, -9, 7, -9, 30 }, - { -5, -1, 0, 2, 1, -1, 2, 5, -33, 3, -5, 14, 11, 7, 5, -3, + { -5, -1, 0, 2, 1, -1, 2, 5, -33, 3, -5, 14, 11, 7, 5, -3, 2, -8, -4, -2, -7, -6, 4, -8, -1, -8, 2, -2, -8, -1, -4, 27 }, - { -1, 0, -1, -2, 1, -1, -2, -1, 2, 0, 1, 2, 2, 4, 1, 3, + { -1, 0, -1, -2, 1, -1, -2, -1, 2, 0, 1, 2, 2, 4, 1, 3, 4, 2, 1, -7, -4, 1, -3, -4, -35, -25, 17, 10, -3, -26, -7, 32 }, - { -5, 1, 6, -2, 6, 6, -9, 3, -1, -4, 5, -4, -2, -2, -9, 2, + { -5, 1, 6, -2, 6, 6, -9, 3, -1, -4, 5, -4, -2, -2, -9, 2, -5, 2, 2, 4, 3, 5, -5, -16, -31, -12, -11, 2, -19, 20, -2, 21 }, - { -5, 2, 7, -7, -7, 5, -7, 2, 0, 0, -4, 3, -1, 0, -1, -2, + { -5, 2, 7, -7, -7, 5, -7, 2, 0, 0, -4, 3, -1, 0, -1, -2, 0, -3, 5, -11, -8, -3, -7, -7, 28, -11, -7, 0, -16, -11, -4, 29 }, - { 2, 1, -3, -2, -1, 3, 4, 0, 1, 0, -1, -5, 4, -5, -12, 2, + { 2, 1, -3, -2, -1, 3, 4, 0, 1, 0, -1, -5, 4, -5, -12, 2, -2, -5, -22, -2, -1, 11, 8, -7, -12, 0, -34, 6, -5, 11, -8, 19 }, - { -1, -3, 5, 11, 18, -2, -2, -5, -2, 4, -1, 8, 5, -6, 1, -1, + { -1, -3, 5, 11, 18, -2, -2, -5, -2, 4, -1, 8, 5, -6, 1, -1, 2, 8, 4, -5, -8, -2, 5, -18, 7, 12, 7, 19, -18, 2, -6, -13 }, - { 9, 0, 0, 5, 4, 3, -6, 4, 1, -4, 5, -1, -4, 8, 8, 6, + { 9, 0, 0, 5, 4, 3, -6, 4, 1, -4, 5, -1, -4, 8, 8, 6, -8, -6, 0, 6, -3, 3, 5, -3, 17, 31, 16, 10, -13, 0, -9, -19 }, - { 12, -10, 2, -2, -2, -1, -3, 6, -12, -5, -2, 14, -16, 4, 12, 12, + { 12, -10, 2, -2, -2, -1, -3, 6, -12, -5, -2, 14, -16, 4, 12, 12, 17, 4, 7, -16, 7, -6, 11, 7, 7, 2, -25, 23, -24, 5, -7, -9 }, - { 10, 4, 13, 10, 10, 3, -6, 3, 3, 2, -1, -6, 8, 4, 10, 0, + { 10, 4, 13, 10, 10, 3, -6, 3, 3, 2, -1, -6, 8, 4, 10, 0, 1, 2, -4, 2, -3, -8, 0, -1, 9, 9, -10, -3, -29, 1, -1, -27 }, - { 2, 2, 0, 7, 9, -2, -10, -1, -1, 1, -9, -5, 8, 4, 1, 2, + { 2, 2, 0, 7, 9, -2, -10, -1, -1, 1, -9, -5, 8, 4, 1, 2, -10, 1, 13, 12, -3, 15, -9, 2, -7, 1, -10, 23, -20, -18, -9, -15 }, - { -3, -5, -1, 8, 0, -5, -1, 4, 7, -1, -7, 2, -8, -5, 11, 7, + { -3, -5, -1, 8, 0, -5, -1, 4, 7, -1, -7, 2, -8, -5, 11, 7, -6, 3, -3, -9, 7, 9, -22, 1, 6, -4, 14, 27, -25, -14, 3, -5 }, - { 1, 3, 8, 4, 7, 6, 12, -17, -15, 1, -8, -10, 7, -14, -8, 6, + { 1, 3, 8, 4, 7, 6, 12, -17, -15, 1, -8, -10, 7, -14, -8, 6, -2, -2, -11, -11, -7, 13, -2, -2, 4, 5, -5, 13, -23, -6, -17, -8 }, - { -5, 4, -14, -5, -4, -5, 6, 5, -8, -5, -2, -11, -7, -12, 3, -11, + { -5, 4, -14, -5, -4, -5, 6, 5, -8, -5, -2, -11, -7, -12, 3, -11, 2, -6, 4, -10, -5, -7, 14, 5, 23, 11, 7, 12, -16, -6, -4, -16 }, - { 5, 6, 2, 5, -2, -5, -5, -6, -5, -19, -13, -1, -3, -13, 5, 0, + { 5, 6, 2, 5, -2, -5, -5, -6, -5, -19, -13, -1, -3, -13, 5, 0, 6, -2, -2, -6, -7, -7, -1, -9, 4, 14, 17, -12, -27, 3, 0, -1 }, - { 7, -1, 9, -10, 8, 2, -7, -2, 5, 2, -3, -7, 3, 0, 6, 4, + { 7, -1, 9, -10, 8, 2, -7, -2, 5, 2, -3, -7, 3, 0, 6, 4, 12, 5, 11, 14, -13, -1, 8, 1, 13, 9, 12, 12, -18, -14, -11, -16 }, - { -7, -5, -6, -5, 0, -1, -3, 2, 2, 1, 4, 9, 2, 3, 5, -2, + { -7, -5, -6, -5, 0, -1, -3, 2, 2, 1, 4, 9, 2, 3, 5, -2, 2, 1, 8, 0, 3, 0, -2, 2, 1, 7, 29, 0, -36, -5, -9, -21 }, - { 14, -6, -9, 0, -1, -8, -8, -11, 2, 2, -9, -12, 12, -4, 5, 3, + { 14, -6, -9, 0, -1, -8, -8, -11, 2, 2, -9, -12, 12, -4, 5, 3, -5, -9, 11, -1, -3, 12, -21, -3, 12, 5, 3, 11, -18, -15, 1, -2 }, - { -1, 3, -9, -3, 7, -7, -18, 2, 4, 12, -10, 2, 8, -3, -14, 13, + { -1, 3, -9, -3, 7, -7, -18, 2, 4, 12, -10, 2, 8, -3, -14, 13, 17, -5, 5, -9, 13, -3, -7, -18, 17, -2, 5, 7, -20, -3, -6, -11 }, - { -3, 3, 3, -1, 1, -6, -5, 1, 5, -3, -14, -6, -5, -8, 14, -6, + { -3, 3, 3, -1, 1, -6, -5, 1, 5, -3, -14, -6, -5, -8, 14, -6, 7, -1, 5, 1, 15, -1, -7, -4, 6, -11, 9, -2, -37, 16, -7, -3 }, - { -1, 0, 6, 1, -3, -9, 0, 11, -8, 2, -2, 0, 5, 2, 12, -10, + { -1, 0, 6, 1, -3, -9, 0, 11, -8, 2, -2, 0, 5, 2, 12, -10, 10, 13, 2, 7, -6, 2, -10, -10, 21, -5, 5, 5, -12, -23, 3, -14 }, - { 6, 0, -2, 1, 0, 1, 0, -4, 1, 1, 8, -2, 2, -5, -2, 1, + { 6, 0, -2, 1, 0, 1, 0, -4, 1, 1, 8, -2, 2, -5, -2, 1, 8, -4, -1, -1, 4, -1, 2, 6, 32, 1, -5, -20, -40, -4, -18, -14 }, - { 2, 2, -7, -2, 4, 4, -1, 2, 0, -2, -4, -7, 3, 5, 0, -5, + { 2, 2, -7, -2, 4, 4, -1, 2, 0, -2, -4, -7, 3, 5, 0, -5, 1, 2, -6, 4, -1, -2, -1, -15, 8, 3, 9, 46, -7, -18, 6, -11 }, - { 5, 5, 16, 21, 3, -11, -4, 11, -12, 2, 4, -12, -1, 11, 8, 1, + { 5, 5, 16, 21, 3, -11, -4, 11, -12, 2, 4, -12, -1, 11, 8, 1, -4, 11, -11, -21, 1, 1, -11, 3, 13, 1, 5, 12, -25, 1, -3, -2 }, - { 1, 6, -7, 4, 2, 3, 1, -5, 8, 9, -15, 3, -3, -14, 17, 4, + { 1, 6, -7, 4, 2, 3, 1, -5, 8, 9, -15, 3, -3, -14, 17, 4, -8, 14, -2, -8, -4, 5, 8, -7, 8, 9, 7, 6, -29, -17, 8, 4 }, - { -7, -7, 4, 0, 13, 1, 0, 4, 4, -16, -10, -7, 5, 9, -15, -10, + { -7, -7, 4, 0, 13, 1, 0, 4, 4, -16, -10, -7, 5, 9, -15, -10, -10, 8, -4, -1, -11, -1, -10, -15, 3, 3, 14, 10, -19, 2, -18, -12 }, - { -4, 0, 2, 0, 5, -2, -9, 0, 4, -4, 2, -1, -2, 2, -4, 9, + { -4, 0, 2, 0, 5, -2, -9, 0, 4, -4, 2, -1, -2, 2, -4, 9, 2, -6, -4, -2, -1, -3, -3, -1, 2, 5, -1, 11, -24, -44, -9, -15 }, - { -1, -10, 6, 21, 11, 15, -7, 10, -14, -9, -8, -8, 4, 6, 19, 1, + { -1, -10, 6, 21, 11, 15, -7, 10, -14, -9, -8, -8, 4, 6, 19, 1, -6, 1, -5, -17, -8, -10, 9, 5, 11, 18, -1, 10, -16, -7, -9, -8 }, - { 3, -5, 0, 0, -2, -2, -6, 4, -4, 1, -1, 0, 7, -3, 4, -4, + { 3, -5, 0, 0, -2, -2, -6, 4, -4, 1, -1, 0, 7, -3, 4, -4, -7, 7, 17, -20, 6, 4, 1, -6, -12, 31, 13, 19, -14, -10, -7, -2 }, - { -2, 6, -10, 3, 9, 6, -14, 15, 2, -5, 2, -11, 9, -8, 4, 6, + { -2, 6, -10, 3, 9, 6, -14, 15, 2, -5, 2, -11, 9, -8, 4, 6, 20, -15, -3, -3, -1, 32, -21, 6, 1, 9, 11, 17, -19, 6, -1, -3 }, - { 8, 10, -2, 0, -8, -16, 7, 7, 6, 10, 4, -14, 7, -6, 21, -7, + { 8, 10, -2, 0, -8, -16, 7, 7, 6, 10, 4, -14, 7, -6, 21, -7, 10, 5, 5, 0, -7, 2, -6, 0, -7, 11, -9, 15, -20, -7, -11, 2 }, - { 0, -7, 5, 2, 0, -3, -6, -4, -2, -1, -4, -5, -13, -1, 27, -9, + { 0, -7, 5, 2, 0, -3, -6, -4, -2, -1, -4, -5, -13, -1, 27, -9, -6, -11, -7, 1, 11, -4, -4, -14, -2, 11, 6, 10, -19, -6, -15, 2 }, - { 0, 7, -1, 2, -7, -15, -2, -3, 13, -5, -5, 12, 3, 0, 5, -5, + { 0, 7, -1, 2, -7, -15, -2, -3, 13, -5, -5, 12, 3, 0, 5, -5, -22, 2, 7, 22, 13, 0, -1, 2, 3, 2, -7, 7, -27, -4, -4, -12 }, - { 11, 1, -16, 6, -15, 1, 3, 2, 0, 2, -3, 2, 5, -2, -5, 9, + { 11, 1, -16, 6, -15, 1, 3, 2, 0, 2, -3, 2, 5, -2, -5, 9, 5, -3, 3, -2, -11, 3, 9, 6, 9, 3, -1, 12, -41, 8, -6, 9 }, - { 3, -7, 3, 2, 5, 5, 0, -1, 1, 3, -5, -2, -13, 7, -1, -2, + { 3, -7, 3, 2, 5, 5, 0, -1, 1, 3, -5, -2, -13, 7, -1, -2, -2, -6, 4, -6, 0, 2, -2, 2, 4, 1, -4, 1, -47, -21, 7, -6 }, - { 3, 16, -7, 13, -4, -2, 10, -3, -1, 18, -13, 7, -13, -4, 8, 4, + { 3, 16, -7, 13, -4, -2, 10, -3, -1, 18, -13, 7, -13, -4, 8, 4, 8, 9, -5, 13, 8, -5, 3, -6, 7, 18, -8, 10, -25, -3, -12, -12 }, - { 1, -1, -1, 0, 2, 5, -5, -3, 0, -5, -1, 0, -4, -8, -2, 3, + { 1, -1, -1, 0, 2, 5, -5, -3, 0, -5, -1, 0, -4, -8, -2, 3, 2, -2, -17, -6, -4, 1, 33, -6, -20, -6, 8, 31, -26, -8, -1, -4 }, - { 3, -3, -3, 5, -3, -2, 1, 7, 0, 3, 6, 3, 6, -2, 9, 15, + { 3, -3, -3, 5, -3, -2, 1, 7, 0, 3, 6, 3, 6, -2, 9, 15, -10, -3, -15, -5, -3, -4, -6, -30, 17, -8, -2, 2, -20, 0, -8, -2 }, - { -2, -1, -1, -1, 3, -5, -2, -3, 4, -2, 0, 5, 8, -3, 1, -4, + { -2, -1, -1, -1, 3, -5, -2, -3, 4, -2, 0, 5, 8, -3, 1, -4, 1, 1, -3, 4, 4, -14, 3, 11, -5, 3, -3, 7, -3, 13, 23, -16 }, - { 2, -6, 1, -3, 5, 0, -6, -11, -7, -4, -1, 2, -7, -1, -1, 7, + { 2, -6, 1, -3, 5, 0, -6, -11, -7, -4, -1, 2, -7, -1, -1, 7, 1, -2, 6, 12, -6, 8, -13, 17, 25, -23, -19, -7, -12, 9, 16, -17 }, - { 9, 4, 4, 4, -3, -1, 6, -2, -3, 0, 13, -4, -7, 14, 1, -7, + { 9, 4, 4, 4, -3, -1, 6, -2, -3, 0, 13, -4, -7, 14, 1, -7, 0, -5, 3, -19, -3, 5, 3, 9, -1, 9, -13, 13, -17, 4, 21, -26 }, - { 0, -5, 0, 0, -4, -5, 2, -6, -4, 5, -7, 10, 0, 2, 0, -2, + { 0, -5, 0, 0, -4, -5, 2, -6, -4, 5, -7, 10, 0, 2, 0, -2, -2, 0, 4, -6, 7, -2, 6, 5, -5, 2, -12, 1, -29, 29, 27, 12 }, - { 9, -10, -22, 6, -1, -1, 9, -14, -12, -2, 1, -1, 10, -11, -16, 0, + { 9, -10, -22, 6, -1, -1, 9, -14, -12, -2, 1, -1, 10, -11, -16, 0, 3, 11, 13, -14, -9, -2, -1, 6, 4, -14, 0, -10, -2, 16, 17, -11 }, - { 2, 0, -1, -2, 4, 3, -6, -2, 1, -1, 1, 3, -4, 1, 3, -4, + { 2, 0, -1, -2, 4, 3, -6, -2, 1, -1, 1, 3, -4, 1, 3, -4, -1, -1, 4, -1, 1, 0, 1, 6, -5, -7, 2, 1, -47, -3, 50, -17 }, - { 8, -4, -11, -7, 11, 11, 14, -7, 12, -7, 6, 2, 13, -6, -3, -2, + { 8, -4, -11, -7, 11, 11, 14, -7, 12, -7, 6, 2, 13, -6, -3, -2, -14, 6, 6, 6, 0, 2, -1, 5, -20, 2, -1, 4, -5, 6, 21, -11 }, - { -2, -9, 3, 0, -6, 7, 8, -8, 1, -3, 4, 1, 5, -2, -3, -7, + { -2, -9, 3, 0, -6, 7, 8, -8, 1, -3, 4, 1, 5, -2, -3, -7, 4, 7, -12, -9, -2, 10, -6, 13, 6, 5, 20, 2, -15, 9, 28, -7 }, - { 0, -5, -6, -6, -6, 1, -6, 6, -2, 4, 8, -3, 12, -1, -4, -2, + { 0, -5, -6, -6, -6, 1, -6, 6, -2, 4, 8, -3, 12, -1, -4, -2, 6, 16, -14, 9, -14, -2, -8, -27, -3, 18, -1, -7, -3, 8, 23, -23 }, - { 1, 4, -9, -1, -5, 10, -2, 1, -11, 1, -9, 4, 7, 14, -9, -2, + { 1, 4, -9, -1, -5, 10, -2, 1, -11, 1, -9, 4, 7, 14, -9, -2, -3, 2, -5, -1, -6, -10, -7, 11, 20, 2, 3, -19, 3, 15, 30, -9 }, - { 7, 2, -14, -4, 0, -2, 5, 2, 5, -2, 8, -3, -7, 6, 6, -11, + { 7, 2, -14, -4, 0, -2, 5, 2, 5, -2, 8, -3, -7, 6, 6, -11, -14, 1, 10, -1, -7, -8, 1, 10, 3, -6, -15, -12, -17, 4, 30, -6 }, - { 4, 2, 1, -2, 3, 0, 1, 0, 2, 0, 1, 6, -7, 0, 3, 4, + { 4, 2, 1, -2, 3, 0, 1, 0, 2, 0, 1, 6, -7, 0, 3, 4, 4, -4, -2, -5, -2, 2, -1, -2, 0, -2, -11, -7, -3, 42, 24, -14 }, - { 4, 1, 3, 2, 0, -2, -3, -2, 2, -1, 4, 11, -2, 2, 3, -4, + { 4, 1, 3, 2, 0, -2, -3, -2, 2, -1, 4, 11, -2, 2, 3, -4, -5, 9, 2, -4, -9, 5, 8, -1, -7, 1, 24, -13, -28, 20, 15, -22 }, - { -3, 7, 6, 3, -2, -5, -10, -2, -2, -1, -6, -6, -2, -14, -16, -6, + { -3, 7, 6, 3, -2, -5, -10, -2, -2, -1, -6, -6, -2, -14, -16, -6, -5, 0, 18, 0, 9, 1, 7, -13, -5, -6, -9, 11, -15, 9, 22, -11 }, - { 9, -2, 6, 5, 2, 9, -10, 1, 1, 5, -4, 12, 2, 2, -10, -7, + { 9, -2, 6, 5, 2, 9, -10, 1, 1, 5, -4, 12, 2, 2, -10, -7, -4, -6, 7, 9, 6, 15, 6, 6, -10, 10, 5, -13, -5, 6, 24, -12 }, - { 1, 3, -3, -3, 8, 1, -6, 2, -5, -3, 7, 2, 14, 6, 9, -6, + { 1, 3, -3, -3, 8, 1, -6, 2, -5, -3, 7, 2, 14, 6, 9, -6, -5, -4, 27, 7, -3, 8, -6, 3, -8, 8, 22, -5, -6, -2, 22, -17 }, - { -2, -2, 3, 10, 9, 9, 12, -15, -1, -11, -13, 3, -2, 1, -3, -11, + { -2, -2, 3, 10, 9, 9, 12, -15, -1, -11, -13, 3, -2, 1, -3, -11, 7, 9, 16, -3, -10, -5, -5, 1, 8, -3, 9, 9, -5, 3, 31, -12 }, - { 7, -5, 10, -4, -8, 2, 16, -2, 10, 10, -3, -2, 3, -8, -3, 3, + { 7, -5, 10, -4, -8, 2, 16, -2, 10, 10, -3, -2, 3, -8, -3, 3, -13, -6, 15, 20, -9, -3, -12, 1, -2, -16, 8, 8, -1, 16, 22, -5 }, - { 5, -3, -15, -2, 12, -8, 8, -5, 2, -8, 20, -18, 14, -4, 3, 3, + { 5, -3, -15, -2, 12, -8, 8, -5, 2, -8, 20, -18, 14, -4, 3, 3, 7, -13, -16, 1, -10, 7, 16, 7, 4, -14, -4, -5, -9, 8, 23, -6 }, - { 5, -4, -5, -4, 1, 8, 4, -7, -5, 8, 10, 6, -6, -10, -2, 6, + { 5, -4, -5, -4, 1, 8, 4, -7, -5, 8, 10, 6, -6, -10, -2, 6, 9, -17, -14, 11, 12, -3, -13, -7, 2, 18, 3, -25, -16, 18, 22, -5 }, - { 5, 6, -7, -20, -4, 2, 8, 4, -24, -4, 1, 4, -5, -2, 1, -10, + { 5, 6, -7, -20, -4, 2, 8, 4, -24, -4, 1, 4, -5, -2, 1, -10, -2, 9, 3, -4, -3, -4, -4, -4, 10, 10, 3, 0, -6, 25, 21, -11 }, - { 0, 7, -1, 14, -6, -4, -10, 5, 4, 4, 4, -5, 3, 4, -1, -7, + { 0, 7, -1, 14, -6, -4, -10, 5, 4, 4, 4, -5, 3, 4, -1, -7, 8, -19, 0, 6, 2, 3, -18, -3, -6, 2, 8, 14, -26, 22, 27, -13 }, - { -2, -6, 7, -5, 12, -7, 8, -1, 3, -2, 4, 1, 8, -2, 0, 14, + { -2, -6, 7, -5, 12, -7, 8, -1, 3, -2, 4, 1, 8, -2, 0, 14, 6, -5, 6, -4, -7, 7, -21, 8, 1, 8, -9, -4, -3, 11, 25, -13 }, - { 4, 4, -1, -6, 4, 9, -8, 1, -3, -10, -2, 0, 15, -9, -16, 11, + { 4, 4, -1, -6, 4, 9, -8, 1, -3, -10, -2, 0, 15, -9, -16, 11, 1, 1, 6, 3, -9, -5, 16, 26, 1, -14, 1, -3, -14, 7, 15, -9 }, - { -12, -2, -9, -13, 2, 6, 14, 0, 1, 0, -1, -13, 0, 10, -1, 6, + { -12, -2, -9, -13, 2, 6, 14, 0, 1, 0, -1, -13, 0, 10, -1, 6, 9, -7, 8, 8, 19, 6, -1, 9, 10, -4, 1, -7, -22, -2, 29, -7 }, - { 2, 4, 13, -12, -8, -4, -5, 13, 12, -5, -3, -3, -4, 1, -1, 10, + { 2, 4, 13, -12, -8, -4, -5, 13, 12, -5, -3, -3, -4, 1, -1, 10, 15, -6, -1, -11, -30, 4, 15, -1, 9, -7, 0, -2, -7, 10, 25, -16 }, - { 7, -15, -7, -7, -1, -5, -5, -11, -20, 10, 3, -10, -3, 5, 20, -4, + { 7, -15, -7, -7, -1, -5, -5, -11, -20, 10, 3, -10, -3, 5, 20, -4, 0, -2, -2, 17, 2, 0, -3, 3, 6, 5, -1, -12, -3, 15, 22, -16 }, - { 4, -1, 3, 4, -5, 0, -1, -5, -24, -29, 4, -9, 1, -3, 0, 0, + { 4, -1, 3, 4, -5, 0, -1, -5, -24, -29, 4, -9, 1, -3, 0, 0, 0, -4, 7, -4, -4, -4, 3, 1, -6, 5, -3, -5, -10, 3, 25, -10 }, - { -2, -1, -1, 4, 4, -1, 2, 0, -4, -4, 2, -1, -3, -1, -2, -2, + { -2, -1, -1, 4, 4, -1, 2, 0, -4, -4, 2, -1, -3, -1, -2, -2, 1, -3, -5, -1, 2, -3, -4, -4, -3, 5, -9, 1, -11, 7, 46, -46 }, - { 0, -9, 3, 4, 4, 3, -5, -6, 5, -4, 4, -2, 1, 7, -4, -10, + { 0, -9, 3, 4, 4, 3, -5, -6, 5, -4, 4, -2, 1, 7, -4, -10, 13, 1, 3, -6, 4, -4, 7, 2, -19, -25, -3, -16, -12, 16, 20, -1 }, - { 18, 6, 4, -12, 0, -14, 9, -6, -1, -4, -5, 2, 1, 12, 4, 2, + { 18, 6, 4, -12, 0, -14, 9, -6, -1, -4, -5, 2, 1, 12, 4, 2, 7, 0, 2, 5, -11, -5, -2, 2, -4, 10, 0, -9, -7, 9, 25, -8 }, - { 5, 0, -6, 5, 6, 3, 3, -10, -5, 1, -1, 4, 3, -11, -8, 5, + { 5, 0, -6, 5, 6, 3, 3, -10, -5, 1, -1, 4, 3, -11, -8, 5, 4, -5, 5, -5, -7, -5, 11, 5, 20, -8, -16, 21, -4, 27, 23, -5 } }; diff --git a/src/libdts/xine_dts_decoder.c b/src/libdts/xine_dts_decoder.c index 6573d5ed0..4c452c06d 100644 --- a/src/libdts/xine_dts_decoder.c +++ b/src/libdts/xine_dts_decoder.c @@ -1,26 +1,30 @@ -/* +/* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * 04-09-2001 DTS passtrough (C) Joachim Koenig + * 04-09-2001 DTS passtrough (C) Joachim Koenig * 09-12-2001 DTS passthrough inprovements (C) James Courtier-Dutton */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifndef __sun /* required for swab() */ #define _XOPEN_SOURCE 500 @@ -68,7 +72,7 @@ typedef struct { dts_state_t *dts_state; int64_t pts; - int audio_caps; + int audio_caps; int sync_state; int ac5_length, ac5_pcm_length, frame_todo; uint32_t syncdword; @@ -76,7 +80,7 @@ typedef struct { uint8_t *frame_ptr; int output_open; - + int bypass_mode; int dts_flags; int dts_sample_rate; @@ -84,8 +88,8 @@ typedef struct { int dts_flags_map[11]; /* Convert from stream dts_flags to the dts_flags we want from the dts downmixer */ int ao_flags_map[11]; /* Convert from the xine AO_CAP's to dts_flags. */ int have_lfe; - - + + } dts_decoder_t; static void dts_reset (audio_decoder_t *this_gen); @@ -134,7 +138,7 @@ static inline void float_to_int (float * _f, int16_t * s16, int num_channels) { static inline void mute_channel (int16_t * s16, int num_channels) { int i; - + for (i = 0; i < 256; i++) { s16[num_channels*i] = 0; } @@ -147,7 +151,7 @@ static void dts_decode_frame (dts_decoder_t *this, int64_t pts, int preview_mode int output_mode = AO_CAP_MODE_STEREO; uint8_t *data_out; uint8_t *data_in = this->frame_buffer; - + lprintf("decode_frame\n"); audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); audio_buffer->vpts = pts; @@ -156,13 +160,13 @@ static void dts_decode_frame (dts_decoder_t *this, int64_t pts, int preview_mode /* SPDIF digital output */ if (!this->output_open) { this->output_open = ((this->stream->audio_out->open) (this->stream->audio_out, this->stream, - 16, this->dts_sample_rate, + 16, this->dts_sample_rate, AO_CAP_MODE_AC5)); } - - if (!this->output_open) + + if (!this->output_open) return; - + data_out=(uint8_t *) audio_buffer->mem; if (this->ac5_length > 8191) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: ac5_length too long\n"); @@ -180,7 +184,7 @@ static void dts_decode_frame (dts_decoder_t *this, int64_t pts, int preview_mode ac5_spdif_type = 0x0d; /* DTS-1 (2048-sample bursts) */ break; default: - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: DTS %i-sample bursts not supported\n", this->ac5_pcm_length); return; } @@ -207,19 +211,27 @@ static void dts_decode_frame (dts_decoder_t *this, int64_t pts, int preview_mode audio_buffer->num_frames = this->ac5_pcm_length; - data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */ - data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */ - data_out[4] = ac5_spdif_type; /* DTS data */ - data_out[5] = 0; /* Unknown */ - data_out[6] = (this->ac5_length << 3) & 0xff; /* ac5_length * 8 */ - data_out[7] = ((this->ac5_length ) >> 5) & 0xff; - - if( this->ac5_pcm_length ) { - if( this->ac5_pcm_length % 2) { - swab(data_in, &data_out[8], this->ac5_length ); - } else { - swab(data_in, &data_out[8], this->ac5_length + 1); + // Checking if AC5 data plus IEC958 header will fit into frames samples data + if ( this->ac5_length + 8 <= this->ac5_pcm_length * 2 * 2 ) { + data_out[0] = 0x72; data_out[1] = 0xf8; /* spdif syncword */ + data_out[2] = 0x1f; data_out[3] = 0x4e; /* .............. */ + data_out[4] = ac5_spdif_type; /* DTS data */ + data_out[5] = 0; /* Unknown */ + data_out[6] = (this->ac5_length << 3) & 0xff; /* ac5_length * 8 */ + data_out[7] = ((this->ac5_length ) >> 5) & 0xff; + + if( this->ac5_pcm_length ) { + if( this->ac5_pcm_length % 2) { + swab(data_in, &data_out[8], this->ac5_length ); + } else { + swab(data_in, &data_out[8], this->ac5_length + 1); + } } + // Transmit it without header otherwise, receivers will autodetect DTS + } else { + lprintf("AC5 data is too large (%i > %i), sending without IEC958 header\n", + this->ac5_length + 8, this->ac5_pcm_length * 2 * 2); + memcpy(data_out, data_in, this->ac5_length); } } else { /* Software decode */ @@ -252,17 +264,17 @@ static void dts_decode_frame (dts_decoder_t *this, int64_t pts, int preview_mode if (!this->output_open) { this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, - 16, this->dts_sample_rate, + 16, this->dts_sample_rate, output_mode); } - - if (!this->output_open) + + if (!this->output_open) return; - number_of_dts_blocks = dts_blocks_num (this->dts_state); + number_of_dts_blocks = dts_blocks_num (this->dts_state); audio_buffer->num_frames = 256*number_of_dts_blocks; for(i = 0; i < number_of_dts_blocks; i++) { if(dts_block(this->dts_state)) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libdts: dts_block error on audio channel %d\n", i); audio_buffer->num_frames = 0; break; @@ -316,10 +328,10 @@ static void dts_decode_frame (dts_decoder_t *this, int64_t pts, int preview_mode } } } - + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - - + + } static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { @@ -328,7 +340,7 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { uint8_t *current = (uint8_t *)buf->content; uint8_t *sync_start=current + 1; uint8_t *end = buf->content + buf->size; - + lprintf("decode_data\n"); if (buf->decoder_flags & BUF_FLAG_PREVIEW) @@ -441,14 +453,14 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } } break; - + case 2: /* Filling frame_buffer with sync_info bytes */ *this->frame_ptr++ = *current++; this->frame_todo--; if (this->frame_todo < 1) { this->sync_state = 3; } else break; - + case 3: /* Ready for decode */ #if 0 dtsdec_decode_frame (this, this->pts_list[0], buf->decoder_flags & BUF_FLAG_PREVIEW); @@ -460,19 +472,19 @@ static void dts_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->syncdword = 0; this->sync_state = 0; break; - default: /* No come here */ + default: /* No come here */ break; } } } static void dts_dispose (audio_decoder_t *this_gen) { - dts_decoder_t *this = (dts_decoder_t *) this_gen; - - if (this->output_open) + dts_decoder_t *this = (dts_decoder_t *) this_gen; + + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = 0; - + free (this); } @@ -481,7 +493,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre lprintf("open_plugin\n"); - this = (dts_decoder_t *) xine_xmalloc (sizeof (dts_decoder_t)); + this = calloc(1, sizeof (dts_decoder_t)); this->audio_decoder.decode_data = dts_decode_data; this->audio_decoder.reset = dts_reset; @@ -519,7 +531,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre this->dts_flags_map[DTS_3F2R] = DTS_3F2R | DTS_LFE; this->ao_flags_map[DTS_2F2R] = AO_CAP_MODE_4CHANNEL; this->ao_flags_map[DTS_3F2R] = AO_CAP_MODE_5CHANNEL; - + } else if (this->audio_caps & AO_CAP_MODE_5CHANNEL) { this->dts_flags_map[DTS_2F2R] = DTS_2F2R; @@ -590,7 +602,7 @@ static void *init_plugin (xine_t *xine, void *data) { lprintf("init_plugin\n"); - this = (dts_class_t *) xine_xmalloc (sizeof (dts_class_t)); + this = calloc(1, sizeof (dts_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -600,7 +612,7 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_DTS, 0 }; @@ -610,7 +622,7 @@ static const decoder_info_t dec_info_audio = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 15, "dts", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libfaad/Makefile.am b/src/libfaad/Makefile.am index 729418f1c..92bab83fb 100644 --- a/src/libfaad/Makefile.am +++ b/src/libfaad/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = codebook @@ -10,8 +11,10 @@ xineplug_LTLIBRARIES = $(faad_module) VPATH = @srcdir@:@srcdir@/codebook: -xineplug_decode_faad_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -fno-strict-aliasing -xineplug_decode_faad_la_SOURCES = \ +if EXTERNAL_LIBFAAD +libfaad_sources = +else +libfaad_sources = \ bits.c \ cfft.c \ common.c \ @@ -49,11 +52,21 @@ xineplug_decode_faad_la_SOURCES = \ ssr_fb.c \ ssr_ipqf.c \ syntax.c \ - tns.c \ + tns.c +endif + +xineplug_decode_faad_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -fno-strict-aliasing +xineplug_decode_faad_la_SOURCES = \ + $(libfaad_sources) \ xine_faad_decoder.c xineplug_decode_faad_la_LDFLAGS = $(xineplug_ldflags) +if EXTERNAL_LIBFAAD +xineplug_decode_faad_la_LIBADD = $(XINE_LIB) -lfaad -lm $(LTLIBINTL) +else xineplug_decode_faad_la_LIBADD = $(XINE_LIB) -lm $(LTLIBINTL) +endif + noinst_HEADERS = \ analysis.h \ @@ -103,4 +116,17 @@ noinst_HEADERS = \ ssr_win.h \ structs.h \ syntax.h \ - tns.h + tns.h \ + codebook/hcb.h \ + codebook/hcb_1.h \ + codebook/hcb_2.h \ + codebook/hcb_3.h \ + codebook/hcb_4.h \ + codebook/hcb_5.h \ + codebook/hcb_6.h \ + codebook/hcb_7.h \ + codebook/hcb_8.h \ + codebook/hcb_9.h \ + codebook/hcb_10.h \ + codebook/hcb_11.h \ + codebook/hcb_sf.h diff --git a/src/libfaad/analysis.h b/src/libfaad/analysis.h index 810a95f3b..50e43fa04 100644 --- a/src/libfaad/analysis.h +++ b/src/libfaad/analysis.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: analysis.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: analysis.h,v 1.18 2007/11/01 12:33:29 menno Exp $ **/ #ifndef __ANALYSIS_H__ diff --git a/src/libfaad/bits.c b/src/libfaad/bits.c index ae273c7d8..dc14d7a03 100644 --- a/src/libfaad/bits.c +++ b/src/libfaad/bits.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,17 +19,19 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: bits.c,v 1.9 2005/10/29 23:57:06 tmmm Exp $ +** $Id: bits.c,v 1.44 2007/11/01 12:33:29 menno Exp $ **/ #include "common.h" #include "structs.h" #include <stdlib.h> -#include <string.h> #include "bits.h" /* initialize buffer, call once before first getbits or showbits */ @@ -40,25 +42,38 @@ void faad_initbits(bitfile *ld, const void *_buffer, const uint32_t buffer_size) if (ld == NULL) return; - memset(ld, 0, sizeof(bitfile)); + // useless + //memset(ld, 0, sizeof(bitfile)); if (buffer_size == 0 || _buffer == NULL) { ld->error = 1; - ld->no_more_reading = 1; return; } - ld->buffer = faad_malloc((buffer_size+12)*sizeof(uint8_t)); - memset(ld->buffer, 0, (buffer_size+12)*sizeof(uint8_t)); - memcpy(ld->buffer, _buffer, buffer_size*sizeof(uint8_t)); + ld->buffer = _buffer; ld->buffer_size = buffer_size; + ld->bytes_left = buffer_size; - tmp = getdword((uint32_t*)ld->buffer); + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)ld->buffer); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)ld->buffer, ld->bytes_left); + ld->bytes_left = 0; + } ld->bufa = tmp; - tmp = getdword((uint32_t*)ld->buffer + 1); + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)ld->buffer + 1); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)ld->buffer + 1, ld->bytes_left); + ld->bytes_left = 0; + } ld->bufb = tmp; ld->start = (uint32_t*)ld->buffer; @@ -66,21 +81,12 @@ void faad_initbits(bitfile *ld, const void *_buffer, const uint32_t buffer_size) ld->bits_left = 32; - ld->bytes_used = 0; - ld->no_more_reading = 0; ld->error = 0; } void faad_endbits(bitfile *ld) { - if (ld) - { - if (ld->buffer) - { - faad_free(ld->buffer); - ld->buffer = NULL; - } - } + // void } uint32_t faad_get_processed_bits(bitfile *ld) @@ -90,12 +96,12 @@ uint32_t faad_get_processed_bits(bitfile *ld) uint8_t faad_byte_align(bitfile *ld) { - uint8_t remainder = (uint8_t)((32 - ld->bits_left) % 8); + int remainder = (32 - ld->bits_left) & 0x7; if (remainder) { faad_flushbits(ld, 8 - remainder); - return (8 - remainder); + return (uint8_t)(8 - remainder); } return 0; } @@ -105,20 +111,22 @@ void faad_flushbits_ex(bitfile *ld, uint32_t bits) uint32_t tmp; ld->bufa = ld->bufb; - if (ld->no_more_reading == 0) + if (ld->bytes_left >= 4) { tmp = getdword(ld->tail); - ld->tail++; + ld->bytes_left -= 4; } else { - tmp = 0; + tmp = getdword_n(ld->tail, ld->bytes_left); + ld->bytes_left = 0; } ld->bufb = tmp; + ld->tail++; ld->bits_left += (32 - bits); - ld->bytes_used += 4; - if (ld->bytes_used == ld->buffer_size) - ld->no_more_reading = 1; - if (ld->bytes_used > ld->buffer_size) - ld->error = 1; + //ld->bytes_left -= 4; +// if (ld->bytes_left == 0) +// ld->no_more_reading = 1; +// if (ld->bytes_left < 0) +// ld->error = 1; } /* rewind to beginning */ @@ -126,30 +134,79 @@ void faad_rewindbits(bitfile *ld) { uint32_t tmp; - tmp = ld->start[0]; -#ifndef ARCH_IS_BIG_ENDIAN - BSWAP(tmp); -#endif + ld->bytes_left = ld->buffer_size; + + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)&ld->start[0]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)&ld->start[0], ld->bytes_left); + ld->bytes_left = 0; + } ld->bufa = tmp; - tmp = ld->start[1]; -#ifndef ARCH_IS_BIG_ENDIAN - BSWAP(tmp); -#endif + if (ld->bytes_left >= 4) + { + tmp = getdword((uint32_t*)&ld->start[1]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n((uint32_t*)&ld->start[1], ld->bytes_left); + ld->bytes_left = 0; + } ld->bufb = tmp; + ld->bits_left = 32; ld->tail = &ld->start[2]; - ld->bytes_used = 0; - ld->no_more_reading = 0; +} + +/* reset to a certain point */ +void faad_resetbits(bitfile *ld, int bits) +{ + uint32_t tmp; + int words = bits >> 5; + int remainder = bits & 0x1F; + + ld->bytes_left = ld->buffer_size - words*4; + + if (ld->bytes_left >= 4) + { + tmp = getdword(&ld->start[words]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n(&ld->start[words], ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufa = tmp; + + if (ld->bytes_left >= 4) + { + tmp = getdword(&ld->start[words+1]); + ld->bytes_left -= 4; + } else { + tmp = getdword_n(&ld->start[words+1], ld->bytes_left); + ld->bytes_left = 0; + } + ld->bufb = tmp; + + ld->bits_left = 32 - remainder; + ld->tail = &ld->start[words+2]; + + /* recheck for reading too many bytes */ + ld->error = 0; +// if (ld->bytes_left == 0) +// ld->no_more_reading = 1; +// if (ld->bytes_left < 0) +// ld->error = 1; } uint8_t *faad_getbitbuffer(bitfile *ld, uint32_t bits DEBUGDEC) { - uint16_t i; - uint8_t temp; - uint16_t bytes = (uint16_t)bits / 8; - uint8_t remainder = (uint8_t)bits % 8; + int i; + unsigned int temp; + int bytes = bits >> 3; + int remainder = bits & 0x7; uint8_t *buffer = (uint8_t*)faad_malloc((bytes+1)*sizeof(uint8_t)); @@ -160,9 +217,9 @@ uint8_t *faad_getbitbuffer(bitfile *ld, uint32_t bits if (remainder) { - temp = (uint8_t)faad_getbits(ld, remainder DEBUGVAR(print,var,dbg)) << (8-remainder); + temp = faad_getbits(ld, remainder DEBUGVAR(print,var,dbg)) << (8-remainder); - buffer[bytes] = temp; + buffer[bytes] = (uint8_t)temp; } return buffer; @@ -207,7 +264,8 @@ void faad_initbits_rev(bitfile *ld, void *buffer, if (ld->bits_left == 0) ld->bits_left = 32; - ld->bytes_used = 0; - ld->no_more_reading = 0; + ld->bytes_left = ld->buffer_size; ld->error = 0; } + +/* EOF */ diff --git a/src/libfaad/bits.h b/src/libfaad/bits.h index 05460f0cc..e303e8e72 100644 --- a/src/libfaad/bits.h +++ b/src/libfaad/bits.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: bits.h,v 1.11 2005/10/30 01:21:53 tmmm Exp $ +** $Id: bits.h,v 1.45 2007/11/01 12:33:29 menno Exp $ **/ #ifndef __BITS_H__ @@ -37,8 +40,10 @@ extern "C" { #include <stdio.h> #endif -#define BYTE_NUMBIT 8 -#define bit2byte(a) ((a+7)/BYTE_NUMBIT) +#define BYTE_NUMBIT 8 +#define BYTE_NUMBIT_LD 3 +//#define bit2byte(a) ((a+7)/BYTE_NUMBIT) +#define bit2byte(a) ((a+7)>>BYTE_NUMBIT_LD) typedef struct _bitfile { @@ -47,25 +52,16 @@ typedef struct _bitfile uint32_t bufb; uint32_t bits_left; uint32_t buffer_size; /* size of the buffer in bytes */ - uint32_t bytes_used; - uint8_t no_more_reading; + uint32_t bytes_left; uint8_t error; uint32_t *tail; uint32_t *start; - void *buffer; + const void *buffer; } bitfile; -#if defined(_MSC_VER) -#define BSWAP(a) __asm mov eax,a __asm bswap eax __asm mov a, eax -#elif defined(LINUX) || defined(DJGPP) || defined (__MINGW32__) || defined (__CYGWIN__) -#define BSWAP(a) __asm__ ( "bswapl %0\n" : "=r" (a) : "0" (a) ) -#else -#define BSWAP(a) \ - ((a) = ( ((a)&0xff)<<24) | (((a)&0xff00)<<8) | (((a)>>8)&0xff00) | (((a)>>24)&0xff)) -#endif - -static uint32_t bitmask[] = { +#if 0 +static uint32_t const bitmask[] = { 0x0, 0x1, 0x3, 0x7, 0xF, 0x1F, 0x3F, 0x7F, 0xFF, 0x1FF, 0x3FF, 0x7FF, 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF, 0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF, 0x1FFFFF, 0x3FFFFF, @@ -74,6 +70,7 @@ static uint32_t bitmask[] = { /* added bitmask 32, correct?!?!?! */ , 0xFFFFFFFF }; +#endif void faad_initbits(bitfile *ld, const void *buffer, const uint32_t buffer_size); void faad_endbits(bitfile *ld); @@ -83,6 +80,7 @@ uint8_t faad_byte_align(bitfile *ld); uint32_t faad_get_processed_bits(bitfile *ld); void faad_flushbits_ex(bitfile *ld, uint32_t bits); void faad_rewindbits(bitfile *ld); +void faad_resetbits(bitfile *ld, int bits); uint8_t *faad_getbitbuffer(bitfile *ld, uint32_t bits DEBUGDEC); #ifdef DRM @@ -93,7 +91,6 @@ uint32_t faad_origbitbuffer_size(bitfile *ld); /* circumvent memory alignment errors on ARM */ static INLINE uint32_t getdword(void *mem) { -#ifdef ARM uint32_t tmp; #ifndef ARCH_IS_BIG_ENDIAN ((uint8_t*)&tmp)[0] = ((uint8_t*)mem)[3]; @@ -108,25 +105,52 @@ static INLINE uint32_t getdword(void *mem) #endif return tmp; -#else - uint32_t tmp; - tmp = *(uint32_t*)mem; +} + +/* reads only n bytes from the stream instead of the standard 4 */ +static /*INLINE*/ uint32_t getdword_n(void *mem, int n) +{ + uint32_t tmp = 0; #ifndef ARCH_IS_BIG_ENDIAN - BSWAP(tmp); + switch (n) + { + case 3: + ((uint8_t*)&tmp)[1] = ((uint8_t*)mem)[2]; + case 2: + ((uint8_t*)&tmp)[2] = ((uint8_t*)mem)[1]; + case 1: + ((uint8_t*)&tmp)[3] = ((uint8_t*)mem)[0]; + default: + break; + } +#else + switch (n) + { + case 3: + ((uint8_t*)&tmp)[2] = ((uint8_t*)mem)[2]; + case 2: + ((uint8_t*)&tmp)[1] = ((uint8_t*)mem)[1]; + case 1: + ((uint8_t*)&tmp)[0] = ((uint8_t*)mem)[0]; + default: + break; + } #endif + return tmp; -#endif } static INLINE uint32_t faad_showbits(bitfile *ld, uint32_t bits) { if (bits <= ld->bits_left) { - return (ld->bufa >> (ld->bits_left - bits)) & bitmask[bits]; + //return (ld->bufa >> (ld->bits_left - bits)) & bitmask[bits]; + return (ld->bufa << (32 - ld->bits_left)) >> (32 - bits); } bits -= ld->bits_left; - return ((ld->bufa & bitmask[ld->bits_left]) << bits) | (ld->bufb >> (32 - bits)); + //return ((ld->bufa & bitmask[ld->bits_left]) << bits) | (ld->bufb >> (32 - bits)); + return ((ld->bufa & ((1<<ld->bits_left)-1)) << bits) | (ld->bufb >> (32 - bits)); } static INLINE void faad_flushbits(bitfile *ld, uint32_t bits) @@ -144,11 +168,11 @@ static INLINE void faad_flushbits(bitfile *ld, uint32_t bits) } /* return next n bits (right adjusted) */ -static INLINE uint32_t faad_getbits(bitfile *ld, uint32_t n DEBUGDEC) +static /*INLINE*/ uint32_t faad_getbits(bitfile *ld, uint32_t n DEBUGDEC) { uint32_t ret; - if (ld->no_more_reading || n == 0) + if (n == 0) return 0; ret = faad_showbits(ld, n); @@ -230,22 +254,23 @@ static INLINE void faad_flushbits_rev(bitfile *ld, uint32_t bits) ld->start--; ld->bits_left += (32 - bits); - ld->bytes_used += 4; - if (ld->bytes_used == ld->buffer_size) - ld->no_more_reading = 1; - if (ld->bytes_used > ld->buffer_size) + if (ld->bytes_left < 4) + { ld->error = 1; + ld->bytes_left = 0; + } else { + ld->bytes_left -= 4; + } +// if (ld->bytes_left == 0) +// ld->no_more_reading = 1; } } -static INLINE uint32_t faad_getbits_rev(bitfile *ld, uint32_t n +static /*INLINE*/ uint32_t faad_getbits_rev(bitfile *ld, uint32_t n DEBUGDEC) { uint32_t ret; - if (ld->no_more_reading) - return 0; - if (n == 0) return 0; @@ -261,28 +286,73 @@ static INLINE uint32_t faad_getbits_rev(bitfile *ld, uint32_t n } #ifdef DRM +/* CRC lookup table for G8 polynome in DRM standard */ +static const uint8_t crc_table_G8[256] = { + 0x0, 0x1d, 0x3a, 0x27, 0x74, 0x69, 0x4e, 0x53, + 0xe8, 0xf5, 0xd2, 0xcf, 0x9c, 0x81, 0xa6, 0xbb, + 0xcd, 0xd0, 0xf7, 0xea, 0xb9, 0xa4, 0x83, 0x9e, + 0x25, 0x38, 0x1f, 0x2, 0x51, 0x4c, 0x6b, 0x76, + 0x87, 0x9a, 0xbd, 0xa0, 0xf3, 0xee, 0xc9, 0xd4, + 0x6f, 0x72, 0x55, 0x48, 0x1b, 0x6, 0x21, 0x3c, + 0x4a, 0x57, 0x70, 0x6d, 0x3e, 0x23, 0x4, 0x19, + 0xa2, 0xbf, 0x98, 0x85, 0xd6, 0xcb, 0xec, 0xf1, + 0x13, 0xe, 0x29, 0x34, 0x67, 0x7a, 0x5d, 0x40, + 0xfb, 0xe6, 0xc1, 0xdc, 0x8f, 0x92, 0xb5, 0xa8, + 0xde, 0xc3, 0xe4, 0xf9, 0xaa, 0xb7, 0x90, 0x8d, + 0x36, 0x2b, 0xc, 0x11, 0x42, 0x5f, 0x78, 0x65, + 0x94, 0x89, 0xae, 0xb3, 0xe0, 0xfd, 0xda, 0xc7, + 0x7c, 0x61, 0x46, 0x5b, 0x8, 0x15, 0x32, 0x2f, + 0x59, 0x44, 0x63, 0x7e, 0x2d, 0x30, 0x17, 0xa, + 0xb1, 0xac, 0x8b, 0x96, 0xc5, 0xd8, 0xff, 0xe2, + 0x26, 0x3b, 0x1c, 0x1, 0x52, 0x4f, 0x68, 0x75, + 0xce, 0xd3, 0xf4, 0xe9, 0xba, 0xa7, 0x80, 0x9d, + 0xeb, 0xf6, 0xd1, 0xcc, 0x9f, 0x82, 0xa5, 0xb8, + 0x3, 0x1e, 0x39, 0x24, 0x77, 0x6a, 0x4d, 0x50, + 0xa1, 0xbc, 0x9b, 0x86, 0xd5, 0xc8, 0xef, 0xf2, + 0x49, 0x54, 0x73, 0x6e, 0x3d, 0x20, 0x7, 0x1a, + 0x6c, 0x71, 0x56, 0x4b, 0x18, 0x5, 0x22, 0x3f, + 0x84, 0x99, 0xbe, 0xa3, 0xf0, 0xed, 0xca, 0xd7, + 0x35, 0x28, 0xf, 0x12, 0x41, 0x5c, 0x7b, 0x66, + 0xdd, 0xc0, 0xe7, 0xfa, 0xa9, 0xb4, 0x93, 0x8e, + 0xf8, 0xe5, 0xc2, 0xdf, 0x8c, 0x91, 0xb6, 0xab, + 0x10, 0xd, 0x2a, 0x37, 0x64, 0x79, 0x5e, 0x43, + 0xb2, 0xaf, 0x88, 0x95, 0xc6, 0xdb, 0xfc, 0xe1, + 0x5a, 0x47, 0x60, 0x7d, 0x2e, 0x33, 0x14, 0x9, + 0x7f, 0x62, 0x45, 0x58, 0xb, 0x16, 0x31, 0x2c, + 0x97, 0x8a, 0xad, 0xb0, 0xe3, 0xfe, 0xd9, 0xc4, +}; + static uint8_t faad_check_CRC(bitfile *ld, uint16_t len) { - uint8_t CRC; - uint16_t r=255; /* Initialize to all ones */ + int bytes, rem; + unsigned int CRC; + unsigned int r=255; /* Initialize to all ones */ /* CRC polynome used x^8 + x^4 + x^3 + x^2 +1 */ #define GPOLY 0435 faad_rewindbits(ld); - CRC = (uint8_t) ~faad_getbits(ld, 8 - DEBUGVAR(1,999,"faad_check_CRC(): CRC")); /* CRC is stored inverted */ + CRC = (unsigned int) ~faad_getbits(ld, 8 + DEBUGVAR(1,999,"faad_check_CRC(): CRC")) & 0xFF; /* CRC is stored inverted */ + + bytes = len >> 3; + rem = len & 0x7; - for (; len>0; len--) + for (; bytes > 0; bytes--) + { + r = crc_table_G8[( r ^ faad_getbits(ld, 8 DEBUGVAR(1,998,"")) ) & 0xFF]; + } + for (; rem > 0; rem--) { r = ( (r << 1) ^ (( ( faad_get1bit(ld DEBUGVAR(1,998,"")) & 1) ^ ((r >> 7) & 1)) * GPOLY )) & 0xFF; } if (r != CRC) + // if (0) { - return 8; + return 28; } else { return 0; } diff --git a/src/libfaad/cfft.c b/src/libfaad/cfft.c index 61cac2fd5..5b01d75d3 100644 --- a/src/libfaad/cfft.c +++ b/src/libfaad/cfft.c @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: cfft.c,v 1.12 2006/09/26 18:00:31 dgp85 Exp $ +** $Id: cfft.c,v 1.35 2007/11/01 12:33:29 menno Exp $ **/ /* @@ -546,7 +549,7 @@ static void passf5(const uint16_t ido, const uint16_t l1, const complex_t *cc, ComplexMult(&RE(c4), &RE(c5), ti12, ti11, RE(t5), RE(t4)); ComplexMult(&IM(c4), &IM(c5), - ti12, ti12, IM(t5), IM(t4)); + ti12, ti11, IM(t5), IM(t4)); RE(ch[ah+l1]) = RE(c2) + IM(c5); IM(ch[ah+l1]) = IM(c2) - RE(c5); @@ -648,7 +651,7 @@ static void passf5(const uint16_t ido, const uint16_t l1, const complex_t *cc, ComplexMult(&RE(c4), &RE(c5), ti12, ti11, RE(t5), RE(t4)); ComplexMult(&IM(c4), &IM(c5), - ti12, ti12, IM(t5), IM(t4)); + ti12, ti11, IM(t5), IM(t4)); IM(d2) = IM(c2) - RE(c5); IM(d3) = IM(c3) - RE(c4); @@ -992,13 +995,11 @@ cfft_info *cffti(uint16_t n) void cfftu(cfft_info *cfft) { - if ( ! cfft ) return; - - faad_free(cfft->work); + if (cfft->work) faad_free(cfft->work); #ifndef FIXED_POINT - faad_free(cfft->tab); + if (cfft->tab) faad_free(cfft->tab); #endif - faad_free(cfft); + if (cfft) faad_free(cfft); } diff --git a/src/libfaad/cfft.h b/src/libfaad/cfft.h index a29537bed..dc89cdc85 100644 --- a/src/libfaad/cfft.h +++ b/src/libfaad/cfft.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: cfft.h,v 1.9 2005/10/29 23:57:06 tmmm Exp $ +** $Id: cfft.h,v 1.24 2007/11/01 12:33:29 menno Exp $ **/ #ifndef __CFFT_H__ diff --git a/src/libfaad/cfft_tab.h b/src/libfaad/cfft_tab.h index 072a991f1..80b1b75be 100644 --- a/src/libfaad/cfft_tab.h +++ b/src/libfaad/cfft_tab.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: cfft_tab.h,v 1.6 2005/10/29 23:57:06 tmmm Exp $ +** $Id: cfft_tab.h,v 1.21 2007/11/01 12:33:29 menno Exp $ **/ #ifndef __CFFT_TAB_H__ diff --git a/src/libfaad/codebook/Makefile.am b/src/libfaad/codebook/Makefile.am index e4691f4b9..63d225b2d 100644 --- a/src/libfaad/codebook/Makefile.am +++ b/src/libfaad/codebook/Makefile.am @@ -12,4 +12,4 @@ EXTRA_DIST = hcb.h \ hcb_9.h \ hcb_10.h \ hcb_11.h \ - hcb_sf.h + hcb_sf.h diff --git a/src/libfaad/codebook/hcb.h b/src/libfaad/codebook/hcb.h index 96093300c..29bbca4f8 100644 --- a/src/libfaad/codebook/hcb.h +++ b/src/libfaad/codebook/hcb.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb.h,v 1.6 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb.h,v 1.8 2007/11/01 12:34:10 menno Exp $ **/ #ifndef __HCB_H__ diff --git a/src/libfaad/codebook/hcb_1.h b/src/libfaad/codebook/hcb_1.h index 220299c55..f6632c230 100644 --- a/src/libfaad/codebook/hcb_1.h +++ b/src/libfaad/codebook/hcb_1.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_1.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_1.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_1 */ diff --git a/src/libfaad/codebook/hcb_10.h b/src/libfaad/codebook/hcb_10.h index 60bcab90a..87e621df5 100644 --- a/src/libfaad/codebook/hcb_10.h +++ b/src/libfaad/codebook/hcb_10.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_10.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_10.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_10 */ diff --git a/src/libfaad/codebook/hcb_11.h b/src/libfaad/codebook/hcb_11.h index bd4f647e6..509a1d684 100644 --- a/src/libfaad/codebook/hcb_11.h +++ b/src/libfaad/codebook/hcb_11.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_11.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_11.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_11 */ diff --git a/src/libfaad/codebook/hcb_2.h b/src/libfaad/codebook/hcb_2.h index 6aff6b12b..8edfe525d 100644 --- a/src/libfaad/codebook/hcb_2.h +++ b/src/libfaad/codebook/hcb_2.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_2.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_2.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_2 */ diff --git a/src/libfaad/codebook/hcb_3.h b/src/libfaad/codebook/hcb_3.h index 25b54da90..e9481e198 100644 --- a/src/libfaad/codebook/hcb_3.h +++ b/src/libfaad/codebook/hcb_3.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_3.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_3.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* Binary search huffman table HCB_3 */ diff --git a/src/libfaad/codebook/hcb_4.h b/src/libfaad/codebook/hcb_4.h index 9378b0980..c2b43e005 100644 --- a/src/libfaad/codebook/hcb_4.h +++ b/src/libfaad/codebook/hcb_4.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_4.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_4.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_4 */ diff --git a/src/libfaad/codebook/hcb_5.h b/src/libfaad/codebook/hcb_5.h index 7e50207e3..ca7c473bf 100644 --- a/src/libfaad/codebook/hcb_5.h +++ b/src/libfaad/codebook/hcb_5.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_5.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_5.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* Binary search huffman table HCB_5 */ diff --git a/src/libfaad/codebook/hcb_6.h b/src/libfaad/codebook/hcb_6.h index 12417d997..2181d63d5 100644 --- a/src/libfaad/codebook/hcb_6.h +++ b/src/libfaad/codebook/hcb_6.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_6.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_6.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_6 */ diff --git a/src/libfaad/codebook/hcb_7.h b/src/libfaad/codebook/hcb_7.h index e5392326d..54c85c11d 100644 --- a/src/libfaad/codebook/hcb_7.h +++ b/src/libfaad/codebook/hcb_7.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_7.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_7.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* Binary search huffman table HCB_7 */ diff --git a/src/libfaad/codebook/hcb_8.h b/src/libfaad/codebook/hcb_8.h index 951743bed..6e3f1009e 100644 --- a/src/libfaad/codebook/hcb_8.h +++ b/src/libfaad/codebook/hcb_8.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_8.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_8.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* 2-step huffman table HCB_8 */ diff --git a/src/libfaad/codebook/hcb_9.h b/src/libfaad/codebook/hcb_9.h index daccf6197..bdba2c222 100644 --- a/src/libfaad/codebook/hcb_9.h +++ b/src/libfaad/codebook/hcb_9.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_9.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_9.h,v 1.5 2007/11/01 12:34:11 menno Exp $ **/ /* Binary search huffman table HCB_9 */ diff --git a/src/libfaad/codebook/hcb_sf.h b/src/libfaad/codebook/hcb_sf.h index 494053177..3c02b3d84 100644 --- a/src/libfaad/codebook/hcb_sf.h +++ b/src/libfaad/codebook/hcb_sf.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcb_sf.h,v 1.4 2005/10/29 23:57:08 tmmm Exp $ +** $Id: hcb_sf.h,v 1.7 2007/11/01 12:34:11 menno Exp $ **/ /* Binary search huffman table HCB_SF */ diff --git a/src/libfaad/common.c b/src/libfaad/common.c index 8c0d93e95..595605586 100644 --- a/src/libfaad/common.c +++ b/src/libfaad/common.c @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: common.c,v 1.8 2005/10/29 23:57:06 tmmm Exp $ +** $Id: common.c,v 1.26 2007/11/01 12:33:30 menno Exp $ **/ /* just some common functions that could be used anywhere */ @@ -229,16 +232,16 @@ static uint32_t __r2 = 1; * which gives a period of 18.410.713.077.675.721.215. The result is the * XORed values of both generators. */ -uint32_t random_int(void) +uint32_t ne_rng(uint32_t *__r1, uint32_t *__r2) { uint32_t t1, t2, t3, t4; - t3 = t1 = __r1; t4 = t2 = __r2; // Parity calculation is done via table lookup, this is also available + t3 = t1 = *__r1; t4 = t2 = *__r2; // Parity calculation is done via table lookup, this is also available t1 &= 0xF5; t2 >>= 25; // on CPUs without parity, can be implemented in C and avoid unpredictable t1 = Parity [t1]; t2 &= 0x63; // jumps and slow rotate through the carry flag operations. t1 <<= 31; t2 = Parity [t2]; - return (__r1 = (t3 >> 1) | t1 ) ^ (__r2 = (t4 + t4) | t2 ); + return (*__r1 = (t3 >> 1) | t1 ) ^ (*__r2 = (t4 + t4) | t2 ); } uint32_t ones32(uint32_t x) diff --git a/src/libfaad/common.h b/src/libfaad/common.h index 31f07708a..4419f1eb5 100644 --- a/src/libfaad/common.h +++ b/src/libfaad/common.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: common.h,v 1.17 2006/06/17 20:43:57 dgp85 Exp $ +** $Id: common.h,v 1.72 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __COMMON_H__ @@ -32,13 +35,16 @@ extern "C" { #endif -#ifdef __CYGWIN__ -#define __STRICT_ANSI__ +#ifdef HAVE_CONFIG_H +# include "config.h" #endif -#include "config.h" - +#if 1 #define INLINE __inline +#else +#define INLINE inline +#endif + #if 0 //defined(_WIN32) && !defined(_WIN32_WCE) #define ALIGN __declspec(align(16)) #else @@ -63,10 +69,13 @@ extern "C" { /* Use if target platform has address generators with autoincrement */ //#define PREFER_POINTERS -#if defined(_WIN32_WCE) || defined(__arm__) +#ifdef _WIN32_WCE #define FIXED_POINT #endif +#ifdef __BFIN__ +#define FIXED_POINT +#endif #define ERROR_RESILIENCE @@ -79,8 +88,6 @@ extern "C" { #define LTP_DEC /* Allow decoding of LD profile AAC */ #define LD_DEC -/* Allow decoding of scalable profiles */ -//#define SCALABLE_DEC /* Allow decoding of Digital Radio Mondiale (DRM) */ //#define DRM //#define DRM_PS @@ -114,20 +121,25 @@ extern "C" { //#define SBR_LOW_POWER #define PS_DEC +#ifdef SBR_LOW_POWER +#undef PS_DEC +#endif + /* FIXED POINT: No MAIN decoding */ #ifdef FIXED_POINT # ifdef MAIN_DEC # undef MAIN_DEC # endif -# ifdef SBR_DEC -# undef SBR_DEC -# endif #endif // FIXED_POINT #ifdef DRM -# ifndef SCALABLE_DEC -# define SCALABLE_DEC +# ifndef ALLOW_SMALL_FRAMELENGTH +# define ALLOW_SMALL_FRAMELENGTH # endif +# undef LD_DEC +# undef LTP_DEC +# undef MAIN_DEC +# undef SSR_DEC #endif @@ -152,6 +164,23 @@ extern "C" { /* END COMPILE TIME DEFINITIONS */ +#if defined(_WIN32) && !defined(__MINGW32__) + +#include <stdlib.h> + +typedef unsigned __int64 uint64_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int8 uint8_t; +typedef __int64 int64_t; +typedef __int32 int32_t; +typedef __int16 int16_t; +typedef __int8 int8_t; +typedef float float32_t; + + +#else + #include <stdio.h> #if HAVE_SYS_TYPES_H # include <sys/types.h> @@ -176,8 +205,6 @@ extern "C" { #if HAVE_STRINGS_H # include <strings.h> #endif - -/* precedence defining int-types by header files for all platforms */ #if HAVE_INTTYPES_H # include <inttypes.h> #else @@ -185,30 +212,23 @@ extern "C" { # include <stdint.h> # else /* we need these... */ -# ifdef WIN32 -typedef unsigned __int64 uint64_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int8 uint8_t; -typedef __int64 int64_t; -typedef __int32 int32_t; -typedef __int16 int16_t; -typedef __int8 int8_t; -# else /* WIN32 */ -typedef float float32_t; +#ifndef __TCS__ typedef unsigned long long uint64_t; +typedef long long int64_t; +#else +typedef unsigned long uint64_t; +typedef long int64_t; +#endif typedef unsigned long uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t; -typedef long long int64_t; typedef long int32_t; typedef short int16_t; typedef char int8_t; -# endif /* WIN32 */ # endif #endif #if HAVE_UNISTD_H -# include <unistd.h> +//# include <unistd.h> #endif #ifndef HAVE_FLOAT32_T @@ -229,6 +249,8 @@ char *strchr(), *strrchr(); # endif #endif +#endif + #ifdef WORDS_BIGENDIAN #define ARCH_IS_BIG_ENDIAN #endif @@ -289,7 +311,6 @@ char *strchr(), *strrchr(); } -#ifndef HAVE_LRINTF #if defined(_WIN32) && !defined(__MINGW32__) #define HAS_LRINTF static INLINE int lrintf(float f) @@ -302,7 +323,9 @@ char *strchr(), *strrchr(); } return i; } - #elif (defined(__i386__) && defined(__GNUC__)) + #elif (defined(__i386__) && defined(__GNUC__) && \ + !defined(__CYGWIN__) && !defined(__MINGW32__)) + #ifndef HAVE_LRINTF #define HAS_LRINTF // from http://www.stereopsis.com/FPU.html static INLINE int lrintf(float f) @@ -315,8 +338,9 @@ char *strchr(), *strrchr(); : "m" (f)); return i; } + #endif /* HAVE_LRINTF */ #endif -#endif + #ifdef __ICL /* only Intel C compiler has fmath ??? */ @@ -331,8 +355,6 @@ char *strchr(), *strrchr(); #else -#include <math.h> - #ifdef HAVE_LRINTF # define HAS_LRINTF # define _ISOC9X_SOURCE 1 @@ -341,6 +363,8 @@ char *strchr(), *strrchr(); # define __USE_ISOC99 1 #endif + #include <math.h> + #ifdef HAVE_SINF # define sin sinf #error @@ -380,7 +404,7 @@ typedef real_t complex_t[2]; /* common functions */ uint8_t cpu_has_sse(void); -uint32_t random_int(void); +uint32_t ne_rng(uint32_t *__r1, uint32_t *__r2); uint32_t ones32(uint32_t x); uint32_t floor_log2(uint32_t x); uint32_t wl_min_lzc(uint32_t x); diff --git a/src/libfaad/decoder.c b/src/libfaad/decoder.c index 33aee247e..7fb4b1965 100644 --- a/src/libfaad/decoder.c +++ b/src/libfaad/decoder.c @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: decoder.c,v 1.10 2005/10/29 23:57:06 tmmm Exp $ +** $Id: decoder.c,v 1.111 2007/11/01 12:33:30 menno Exp $ **/ #include "common.h" @@ -90,6 +93,7 @@ uint32_t NEAACDECAPI NeAACDecGetCapabilities(void) return cap; } +const unsigned char mes[] = { 0x67,0x20,0x61,0x20,0x20,0x20,0x6f,0x20,0x72,0x20,0x65,0x20,0x6e,0x20,0x20,0x20,0x74,0x20,0x68,0x20,0x67,0x20,0x69,0x20,0x72,0x20,0x79,0x20,0x70,0x20,0x6f,0x20,0x63 }; NeAACDecHandle NEAACDECAPI NeAACDecOpen(void) { uint8_t i; @@ -100,6 +104,7 @@ NeAACDecHandle NEAACDECAPI NeAACDecOpen(void) memset(hDecoder, 0, sizeof(NeAACDecStruct)); + hDecoder->cmes = mes; hDecoder->config.outputFormat = FAAD_FMT_16BIT; hDecoder->config.defObjectType = MAIN; hDecoder->config.defSampleRate = 44100; /* Default: 44.1kHz */ @@ -116,6 +121,9 @@ NeAACDecHandle NEAACDECAPI NeAACDecOpen(void) hDecoder->frame = 0; hDecoder->sample_buffer = NULL; + hDecoder->__r1 = 1; + hDecoder->__r2 = 1; + for (i = 0; i < MAX_CHANNELS; i++) { hDecoder->window_shape_prev[i] = 0; @@ -194,6 +202,7 @@ uint8_t NEAACDECAPI NeAACDecSetConfiguration(NeAACDecHandle hDecoder, return 0; } + int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer, uint32_t buffer_size, uint32_t *samplerate, uint8_t *channels) @@ -203,6 +212,7 @@ int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer, adif_header adif; adts_header adts; + if ((hDecoder == NULL) || (samplerate == NULL) || (channels == NULL)) return -1; @@ -257,7 +267,6 @@ int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer, } faad_endbits(&ld); } - hDecoder->channelConfiguration = *channels; #if (defined(PS_DEC) || defined(DRM_PS)) /* check if we have a mono file */ @@ -268,6 +277,8 @@ int32_t NEAACDECAPI NeAACDecInit(NeAACDecHandle hDecoder, uint8_t *buffer, } #endif + hDecoder->channelConfiguration = *channels; + #ifdef SBR_DEC /* implicit signalling */ if (*samplerate <= 24000 && !(hDecoder->config.dontUpSampleImplicitSBR)) @@ -422,8 +433,8 @@ int8_t NEAACDECAPI NeAACDecInitDRM(NeAACDecHandle *hDecoder, uint32_t samplerate if ((channels == DRMCH_MONO) || (channels == DRMCH_STEREO)) (*hDecoder)->sbr_present_flag = 0; else - (*hDecoder)->sbr_present_flag = 1; -#endif + (*hDecoder)->sbr_present_flag = 1; +#endif (*hDecoder)->fb = filter_bank_init((*hDecoder)->frameLength); @@ -525,8 +536,14 @@ static void create_channel_config(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hI chdir = hInfo->num_front_channels; if (chdir & 1) { +#if (defined(PS_DEC) || defined(DRM_PS)) + /* When PS is enabled output is always stereo */ + hInfo->channel_position[chpos++] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[chpos++] = FRONT_CHANNEL_RIGHT; +#else hInfo->channel_position[chpos++] = FRONT_CHANNEL_CENTER; chdir--; +#endif } for (i = 0; i < chdir; i += 2) { @@ -565,8 +582,15 @@ static void create_channel_config(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hI switch (hDecoder->channelConfiguration) { case 1: +#if (defined(PS_DEC) || defined(DRM_PS)) + /* When PS is enabled output is always stereo */ + hInfo->num_front_channels = 2; + hInfo->channel_position[0] = FRONT_CHANNEL_LEFT; + hInfo->channel_position[1] = FRONT_CHANNEL_RIGHT; +#else hInfo->num_front_channels = 1; hInfo->channel_position[0] = FRONT_CHANNEL_CENTER; +#endif break; case 2: hInfo->num_front_channels = 2; @@ -722,13 +746,25 @@ void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder, sample_buffer, sample_buffer_size); } +#ifdef DRM + +#define ERROR_STATE_INIT 6 + +static void conceal_output(NeAACDecHandle hDecoder, uint16_t frame_len, + uint8_t out_ch, void *sample_buffer) +{ + return; +} +#endif + static void* aac_frame_decode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, uint8_t *buffer, uint32_t buffer_size, void **sample_buffer2, uint32_t sample_buffer_size) { + uint16_t i; uint8_t channels = 0; uint8_t output_channels = 0; - bitfile ld; + bitfile ld = {0}; uint32_t bitsconsumed; uint16_t frame_len; void *sample_buffer; @@ -753,6 +789,33 @@ static void* aac_frame_decode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, memset(hInfo, 0, sizeof(NeAACDecFrameInfo)); memset(hDecoder->internal_channel, 0, MAX_CHANNELS*sizeof(hDecoder->internal_channel[0])); +#ifdef USE_TIME_LIMIT + if ((TIME_LIMIT * get_sample_rate(hDecoder->sf_index)) > hDecoder->TL_count) + { + hDecoder->TL_count += 1024; + } else { + hInfo->error = (NUM_ERROR_MESSAGES-1); + goto error; + } +#endif + + + /* check for some common metadata tag types in the bitstream + * No need to return an error + */ + /* ID3 */ + if (buffer_size >= 128) + { + if (memcmp(buffer, "TAG", 3) == 0) + { + /* found it */ + hInfo->bytesconsumed = 128; /* 128 bytes fixed size */ + /* no error, but no output either */ + return NULL; + } + } + + /* initialize the bitstream */ faad_initbits(&ld, buffer, buffer_size); @@ -780,7 +843,7 @@ static void* aac_frame_decode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, /* We do not support stereo right now */ if (0) //(hDecoder->channelConfiguration == 2) { - hInfo->error = 8; // Throw CRC error + hInfo->error = 28; // Throw CRC error goto error; } @@ -808,14 +871,14 @@ static void* aac_frame_decode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, #endif /* decode the complete bitstream */ -#ifdef SCALABLE_DEC - if ((hDecoder->object_type == 6) || (hDecoder->object_type == DRM_ER_LC)) +#ifdef DRM + if (/*(hDecoder->object_type == 6) ||*/ (hDecoder->object_type == DRM_ER_LC)) { - aac_scalable_main_element(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); + DRM_aac_scalable_main_element(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); } else { #endif raw_data_block(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc); -#ifdef SCALABLE_DEC +#ifdef DRM } #endif @@ -978,10 +1041,16 @@ static void* aac_frame_decode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, } #endif + sample_buffer = output_to_PCM(hDecoder, hDecoder->time_out, sample_buffer, output_channels, frame_len, hDecoder->config.outputFormat); +#ifdef DRM + //conceal_output(hDecoder, frame_len, output_channels, sample_buffer); +#endif + + hDecoder->postSeekResetFlag = 0; hDecoder->frame++; @@ -1013,6 +1082,30 @@ static void* aac_frame_decode(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, error: + +#ifdef DRM + hDecoder->error_state = ERROR_STATE_INIT; +#endif + + /* reset filterbank state */ + for (i = 0; i < MAX_CHANNELS; i++) + { + if (hDecoder->fb_intermed[i] != NULL) + { + memset(hDecoder->fb_intermed[i], 0, hDecoder->frameLength*sizeof(real_t)); + } + } +#ifdef SBR_DEC + for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++) + { + if (hDecoder->sbr[i] != NULL) + { + sbrReset(hDecoder->sbr[i]); + } + } +#endif + + faad_endbits(&ld); /* cleanup */ diff --git a/src/libfaad/decoder.h b/src/libfaad/decoder.h index 5a3a2663f..a4cb567d2 100644 --- a/src/libfaad/decoder.h +++ b/src/libfaad/decoder.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: decoder.h,v 1.9 2005/10/29 23:57:06 tmmm Exp $ +** $Id: decoder.h,v 1.48 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __DECODER_H__ diff --git a/src/libfaad/drc.c b/src/libfaad/drc.c index ef4b6a96e..3c9ff3ae0 100644 --- a/src/libfaad/drc.c +++ b/src/libfaad/drc.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: drc.c,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: drc.c,v 1.28 2007/11/01 12:33:30 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/drc.h b/src/libfaad/drc.h index 046ecbc3e..49118bcd0 100644 --- a/src/libfaad/drc.h +++ b/src/libfaad/drc.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: drc.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: drc.h,v 1.22 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __DRC_H__ diff --git a/src/libfaad/drm_dec.c b/src/libfaad/drm_dec.c index a782b0f22..61cb8180e 100644 --- a/src/libfaad/drm_dec.c +++ b/src/libfaad/drm_dec.c @@ -1,28 +1,31 @@ /* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR and PS decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: drm_dec.c,v 1.1 2005/10/30 00:50:19 tmmm Exp $ +** $Id: drm_dec.c,v 1.9 2007/11/01 12:33:30 menno Exp $ **/ #include <stdlib.h> @@ -243,17 +246,9 @@ static const real_t sa_sqrt_1_minus[8][2] = { { FRAC_CONST(0.929071574), FRAC_CONST(0) } }; -static const uint8_t sa_freq_scale[9][2] = +static const uint8_t sa_freq_scale[9] = { - { 0, 0}, - { 1, 1}, - { 2, 2}, - { 3, 3}, - { 5, 5}, - { 7, 7}, - {10,10}, - {13,13}, - {46,23} + 0, 1, 2, 3, 5, 7, 10, 13, 23 }; static const uint8_t pan_freq_scale[21] = @@ -290,9 +285,9 @@ static const real_t filter_coeff[] = FRAC_CONST(0.48954165955695) }; -static const uint8_t delay_length[][2] = +static const uint8_t delay_length[3] = { - { 1, 3 }, { 2, 4 }, { 3, 5 } + 3, 4, 5 }; static const real_t delay_fraction[] = @@ -300,15 +295,9 @@ static const real_t delay_fraction[] = FRAC_CONST(0.43), FRAC_CONST(0.75), FRAC_CONST(0.347) }; -static const real_t peak_decay[2] = -{ - FRAC_CONST(0.58664621951003), FRAC_CONST(0.76592833836465) -}; +static const real_t peak_decay = FRAC_CONST(0.76592833836465); -static const real_t smooth_coeff[2] = -{ - FRAC_CONST(0.6), FRAC_CONST(0.25) -}; +static const real_t smooth_coeff = FRAC_CONST(0.25); /* Please note that these are the same tables as in plain PS */ static const complex_t Q_Fract_allpass_Qmf[][3] = { @@ -566,25 +555,22 @@ static void drm_ps_delta_decode(drm_ps_info *ps) { if (ps->bs_sa_dt_flag && !ps->g_last_had_sa) { - for (band = 0; band < DRM_NUM_SA_BANDS; band++) - { - ps->g_prev_sa_index[band] = 0; - } - } - if (ps->bs_sa_dt_flag) - { + /* wait until we get a DT frame */ + ps->bs_enable_sa = 0; + } else if (ps->bs_sa_dt_flag) { + /* DT frame, we have a last frame, so we can decode */ ps->g_sa_index[0] = sa_delta_clip(ps, ps->g_prev_sa_index[0]+ps->bs_sa_data[0]); - } else { + /* DF always decodable */ ps->g_sa_index[0] = sa_delta_clip(ps,ps->bs_sa_data[0]); } for (band = 1; band < DRM_NUM_SA_BANDS; band++) { - if (ps->bs_sa_dt_flag) + if (ps->bs_sa_dt_flag && ps->g_last_had_sa) { ps->g_sa_index[band] = sa_delta_clip(ps, ps->g_prev_sa_index[band] + ps->bs_sa_data[band]); - } else { + } else if (!ps->bs_sa_dt_flag) { ps->g_sa_index[band] = sa_delta_clip(ps, ps->g_sa_index[band-1] + ps->bs_sa_data[band]); } } @@ -618,28 +604,19 @@ static void drm_ps_delta_decode(drm_ps_info *ps) { if (ps->bs_pan_dt_flag && !ps->g_last_had_pan) { -/* The DRM PS spec doesn't say anything about this case. (deltacoded in time without a previous frame) - AAC PS spec you must tread previous frame as 0, so that's what we try. -*/ - for (band = 0; band < DRM_NUM_PAN_BANDS; band++) - { - ps->g_prev_pan_index[band] = 0; - } - } - - if (ps->bs_pan_dt_flag) - { - ps->g_pan_index[0] = pan_delta_clip(ps, ps->g_prev_pan_index[0]+ps->bs_pan_data[0]); + ps->bs_enable_pan = 0; + } else if (ps->bs_pan_dt_flag) { + ps->g_pan_index[0] = pan_delta_clip(ps, ps->g_prev_pan_index[0]+ps->bs_pan_data[0]); } else { - ps->g_pan_index[0] = pan_delta_clip(ps, ps->bs_pan_data[0]); + ps->g_pan_index[0] = pan_delta_clip(ps, ps->bs_pan_data[0]); } for (band = 1; band < DRM_NUM_PAN_BANDS; band++) { - if (ps->bs_pan_dt_flag) + if (ps->bs_pan_dt_flag && ps->g_last_had_pan) { ps->g_pan_index[band] = pan_delta_clip(ps, ps->g_prev_pan_index[band] + ps->bs_pan_data[band]); - } else { + } else if (!ps->bs_pan_dt_flag) { ps->g_pan_index[band] = pan_delta_clip(ps, ps->g_pan_index[band-1] + ps->bs_pan_data[band]); } } @@ -658,7 +635,7 @@ static void drm_ps_delta_decode(drm_ps_info *ps) } } -static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64], uint8_t rateselect) +static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64]) { uint8_t s, b, k; complex_t qfrac, tmp0, tmp, in, R0; @@ -673,7 +650,7 @@ static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64], uint8_t ra uint32_t in_re, in_im; #endif - for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b++) + for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS]; b++) { /* set delay indices */ for (k = 0; k < NUM_OF_LINKS; k++) @@ -701,16 +678,16 @@ static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64], uint8_t ra power = MUL_R(RE(in),RE(in)) + MUL_R(IM(in),IM(in)); #endif - ps->peakdecay_fast[b] = MUL_F(ps->peakdecay_fast[b], peak_decay[rateselect]); + ps->peakdecay_fast[b] = MUL_F(ps->peakdecay_fast[b], peak_decay); if (ps->peakdecay_fast[b] < power) ps->peakdecay_fast[b] = power; peakdiff = ps->prev_peakdiff[b]; - peakdiff += MUL_F((ps->peakdecay_fast[b] - power - ps->prev_peakdiff[b]), smooth_coeff[rateselect]); + peakdiff += MUL_F((ps->peakdecay_fast[b] - power - ps->prev_peakdiff[b]), smooth_coeff); ps->prev_peakdiff[b] = peakdiff; nrg = ps->prev_nrg[b]; - nrg += MUL_F((power - ps->prev_nrg[b]), smooth_coeff[rateselect]); + nrg += MUL_F((power - ps->prev_nrg[b]), smooth_coeff); ps->prev_nrg[b] = nrg; if (MUL_R(peakdiff, gamma) <= nrg) { @@ -763,7 +740,7 @@ static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64], uint8_t ra for (k = 0; k < NUM_OF_LINKS; k++) { - if (++temp_delay_ser[k] >= delay_length[k][rateselect]) + if (++temp_delay_ser[k] >= delay_length[k]) temp_delay_ser[k] = 0; } } @@ -773,7 +750,7 @@ static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64], uint8_t ra ps->delay_buf_index_ser[k] = temp_delay_ser[k]; } -static void drm_add_ambiance(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[38][64], qmf_t X_right[38][64]) +static void drm_add_ambiance(drm_ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]) { uint8_t s, b, ifreq, qclass; real_t sa_map[MAX_SA_BAND], sa_dir_map[MAX_SA_BAND], k_sa_map[MAX_SA_BAND], k_sa_dir_map[MAX_SA_BAND]; @@ -783,7 +760,7 @@ static void drm_add_ambiance(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[3 { /* Instead of dequantization and mapping, we use an inverse mapping to look up all the values we need */ - for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b++) + for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS]; b++) { const real_t inv_f_num_of_subsamples = FRAC_CONST(0.03333333333); @@ -804,7 +781,7 @@ static void drm_add_ambiance(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[3 for (s = 0; s < NUM_OF_SUBSAMPLES; s++) { - for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b++) + for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS]; b++) { QMF_RE(X_right[s][b]) = MUL_F(QMF_RE(X_left[s][b]), sa_dir_map[b]) - MUL_F(QMF_RE(ps->SA[s][b]), sa_map[b]); QMF_IM(X_right[s][b]) = MUL_F(QMF_IM(X_left[s][b]), sa_dir_map[b]) - MUL_F(QMF_IM(ps->SA[s][b]), sa_map[b]); @@ -814,7 +791,7 @@ static void drm_add_ambiance(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[3 sa_map[b] += k_sa_map[b]; sa_dir_map[b] += k_sa_dir_map[b]; } - for (b = sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b < NUM_OF_QMF_CHANNELS; b++) + for (b = sa_freq_scale[DRM_NUM_SA_BANDS]; b < NUM_OF_QMF_CHANNELS; b++) { QMF_RE(X_right[s][b]) = QMF_RE(X_left[s][b]); QMF_IM(X_right[s][b]) = QMF_IM(X_left[s][b]); @@ -833,7 +810,7 @@ static void drm_add_ambiance(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[3 } } -static void drm_add_pan(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[38][64], qmf_t X_right[38][64]) +static void drm_add_pan(drm_ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]) { uint8_t s, b, qclass, ifreq; real_t tmp, coeff1, coeff2; @@ -924,10 +901,8 @@ void drm_ps_free(drm_ps_info *ps) } /* main DRM PS decoding function */ -uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, uint32_t samplerate, qmf_t X_left[38][64], qmf_t X_right[38][64]) -{ - uint8_t rateselect = (samplerate >= 24000); - +uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, qmf_t X_left[38][64], qmf_t X_right[38][64]) +{ if (ps == NULL) { memcpy(X_right, X_left, sizeof(qmf_t)*30*64); @@ -958,8 +933,8 @@ uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, uint32_t samplerate, qmf_t ps->drm_ps_data_available = 0; - drm_calc_sa_side_signal(ps, X_left, rateselect); - drm_add_ambiance(ps, rateselect, X_left, X_right); + drm_calc_sa_side_signal(ps, X_left); + drm_add_ambiance(ps, X_left, X_right); if (ps->bs_enable_sa) { @@ -973,7 +948,7 @@ uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, uint32_t samplerate, qmf_t if (ps->bs_enable_pan) { - drm_add_pan(ps, rateselect, X_left, X_right); + drm_add_pan(ps, X_left, X_right); ps->g_last_had_pan = 1; diff --git a/src/libfaad/drm_dec.h b/src/libfaad/drm_dec.h index bb7d6dc93..d0ac995e4 100644 --- a/src/libfaad/drm_dec.h +++ b/src/libfaad/drm_dec.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: drm_dec.h,v 1.1 2005/10/30 00:50:19 tmmm Exp $ +** $Id: drm_dec.h,v 1.8 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __DRM_DEC_H__ @@ -88,7 +91,7 @@ uint16_t drm_ps_data(drm_ps_info *ps, bitfile *ld); drm_ps_info *drm_ps_init(void); void drm_ps_free(drm_ps_info *ps); -uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, uint32_t samplerate, qmf_t X_left[38][64], qmf_t X_right[38][64]); +uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, qmf_t X_left[38][64], qmf_t X_right[38][64]); #ifdef __cplusplus } diff --git a/src/libfaad/error.c b/src/libfaad/error.c index 2fbe08fc1..c552e06cd 100644 --- a/src/libfaad/error.c +++ b/src/libfaad/error.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: error.c,v 1.8 2005/10/29 23:57:06 tmmm Exp $ +** $Id: error.c,v 1.32 2007/11/01 12:33:30 menno Exp $ **/ #include "common.h" @@ -56,6 +59,11 @@ char *err_msg[] = { "Unexpected fill element with SBR data", "Not all elements were provided with SBR data", "LTP decoding not available", - "Output data buffer too small" + "Output data buffer too small", + "CRC error in DRM data", + "PNS not allowed in DRM data stream", + "No standard extension payload allowed in DRM", + "PCE shall be the first element in a frame", + "Bitstream value not allowed by specification" }; diff --git a/src/libfaad/error.h b/src/libfaad/error.h index 1009a9f57..7f750217c 100644 --- a/src/libfaad/error.h +++ b/src/libfaad/error.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: error.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: error.h,v 1.26 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __ERROR_H__ @@ -32,7 +35,7 @@ extern "C" { #endif -#define NUM_ERROR_MESSAGES 28 +#define NUM_ERROR_MESSAGES 33 extern char *err_msg[]; #ifdef __cplusplus diff --git a/src/libfaad/faad.h b/src/libfaad/faad.h deleted file mode 100644 index e46c31d87..000000000 --- a/src/libfaad/faad.h +++ /dev/null @@ -1,217 +0,0 @@ -/* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 2 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software -** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -** -** Any non-GPL usage of this software or parts of this software is strictly -** forbidden. -** -** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. -** -** $Id: faad.h,v 1.7 2004/12/03 01:15:30 tmattern Exp $ -**/ - -#ifndef __AACDEC_H__ -#define __AACDEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#ifdef _WIN32 - #pragma pack(push, 8) - #ifndef FAADAPI - #define FAADAPI __cdecl - #endif -#else - #ifndef FAADAPI - #define FAADAPI - #endif -#endif - -#define FAAD2_VERSION "2.0 " - -/* object types for AAC */ -#define MAIN 1 -#define LC 2 -#define SSR 3 -#define LTP 4 -#define HE_AAC 5 -#define ER_LC 17 -#define ER_LTP 19 -#define LD 23 -#define DRM_ER_LC 27 /* special object type for DRM */ - -/* header types */ -#define RAW 0 -#define ADIF 1 -#define ADTS 2 - -/* SBR signalling */ -#define NO_SBR 0 -#define SBR_UPSAMPLED 1 -#define SBR_DOWNSAMPLED 2 -#define NO_SBR_UPSAMPLED 3 - -/* library output formats */ -#define FAAD_FMT_16BIT 1 -#define FAAD_FMT_24BIT 2 -#define FAAD_FMT_32BIT 3 -#define FAAD_FMT_FLOAT 4 -#define FAAD_FMT_DOUBLE 5 - -/* Capabilities */ -#define LC_DEC_CAP (1<<0) /* Can decode LC */ -#define MAIN_DEC_CAP (1<<1) /* Can decode MAIN */ -#define LTP_DEC_CAP (1<<2) /* Can decode LTP */ -#define LD_DEC_CAP (1<<3) /* Can decode LD */ -#define ERROR_RESILIENCE_CAP (1<<4) /* Can decode ER */ -#define FIXED_POINT_CAP (1<<5) /* Fixed point */ - -/* Channel definitions */ -#define FRONT_CHANNEL_CENTER (1) -#define FRONT_CHANNEL_LEFT (2) -#define FRONT_CHANNEL_RIGHT (3) -#define SIDE_CHANNEL_LEFT (4) -#define SIDE_CHANNEL_RIGHT (5) -#define BACK_CHANNEL_LEFT (6) -#define BACK_CHANNEL_RIGHT (7) -#define BACK_CHANNEL_CENTER (8) -#define LFE_CHANNEL (9) -#define UNKNOWN_CHANNEL (0) - -/* DRM channel definitions */ -#define DRMCH_MONO 1 -#define DRMCH_STEREO 2 -#define DRMCH_SBR_MONO 3 -#define DRMCH_SBR_LC_STEREO 4 -#define DRMCH_SBR_STEREO 5 - - -/* A decode call can eat up to FAAD_MIN_STREAMSIZE bytes per decoded channel, - so at least so much bytes per channel should be available in this stream */ -#define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */ - - -typedef void *faacDecHandle; - -typedef struct mp4AudioSpecificConfig -{ - /* Audio Specific Info */ - unsigned char objectTypeIndex; - unsigned char samplingFrequencyIndex; - unsigned long samplingFrequency; - unsigned char channelsConfiguration; - - /* GA Specific Info */ - unsigned char frameLengthFlag; - unsigned char dependsOnCoreCoder; - unsigned short coreCoderDelay; - unsigned char extensionFlag; - unsigned char aacSectionDataResilienceFlag; - unsigned char aacScalefactorDataResilienceFlag; - unsigned char aacSpectralDataResilienceFlag; - unsigned char epConfig; - - char sbr_present_flag; - char forceUpSampling; -} mp4AudioSpecificConfig; - -typedef struct faacDecConfiguration -{ - unsigned char defObjectType; - unsigned long defSampleRate; - unsigned char outputFormat; - unsigned char downMatrix; - unsigned char useOldADTSFormat; - unsigned char dontUpSampleImplicitSBR; -} faacDecConfiguration, *faacDecConfigurationPtr; - -typedef struct faacDecFrameInfo -{ - unsigned long bytesconsumed; - unsigned long samples; - unsigned char channels; - unsigned char error; - unsigned long samplerate; - - /* SBR: 0: off, 1: on; upsample, 2: on; downsampled, 3: off; upsampled */ - unsigned char sbr; - - /* MPEG-4 ObjectType */ - unsigned char object_type; - - /* AAC header type; MP4 will be signalled as RAW also */ - unsigned char header_type; - - /* multichannel configuration */ - unsigned char num_front_channels; - unsigned char num_side_channels; - unsigned char num_back_channels; - unsigned char num_lfe_channels; - unsigned char channel_position[64]; -} faacDecFrameInfo; - -char* FAADAPI faacDecGetErrorMessage(unsigned char errcode); - -unsigned long FAADAPI faacDecGetCapabilities(void); - -faacDecHandle FAADAPI faacDecOpen(void); - -faacDecConfigurationPtr FAADAPI faacDecGetCurrentConfiguration(faacDecHandle hDecoder); - -unsigned char FAADAPI faacDecSetConfiguration(faacDecHandle hDecoder, - faacDecConfigurationPtr config); - -/* Init the library based on info from the AAC file (ADTS/ADIF) */ -long FAADAPI faacDecInit(faacDecHandle hDecoder, - unsigned char *buffer, - unsigned long buffer_size, - unsigned long *samplerate, - unsigned char *channels); - -/* Init the library using a DecoderSpecificInfo */ -char FAADAPI faacDecInit2(faacDecHandle hDecoder, unsigned char *pBuffer, - unsigned long SizeOfDecoderSpecificInfo, - unsigned long *samplerate, unsigned char *channels); - -/* Init the library for DRM */ -char FAADAPI faacDecInitDRM(faacDecHandle hDecoder, unsigned long samplerate, - unsigned char channels); - -void FAADAPI faacDecPostSeekReset(faacDecHandle hDecoder, long frame); - -void FAADAPI faacDecClose(faacDecHandle hDecoder); - -void* FAADAPI faacDecDecode(faacDecHandle hDecoder, - faacDecFrameInfo *hInfo, - unsigned char *buffer, - unsigned long buffer_size); - -char FAADAPI AudioSpecificConfig(unsigned char *pBuffer, - unsigned long buffer_size, - mp4AudioSpecificConfig *mp4ASC); - -#ifdef _WIN32 - #pragma pack(pop) -#endif - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/src/libfaad/filtbank.c b/src/libfaad/filtbank.c index 2919b5be3..eaeddcce6 100644 --- a/src/libfaad/filtbank.c +++ b/src/libfaad/filtbank.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: filtbank.c,v 1.10 2005/10/29 23:57:06 tmmm Exp $ +** $Id: filtbank.c,v 1.45 2007/11/01 12:33:30 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/filtbank.h b/src/libfaad/filtbank.h index 54c72c0ef..de0149c97 100644 --- a/src/libfaad/filtbank.h +++ b/src/libfaad/filtbank.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: filtbank.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: filtbank.h,v 1.27 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __FILTBANK_H__ diff --git a/src/libfaad/fixed.h b/src/libfaad/fixed.h index c58ee26cb..531583772 100644 --- a/src/libfaad/fixed.h +++ b/src/libfaad/fixed.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: fixed.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: fixed.h,v 1.32 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __FIXED_H__ @@ -36,6 +39,7 @@ extern "C" { #include <cmnintrin.h> #endif + #define COEF_BITS 28 #define COEF_PRECISION (1 << COEF_BITS) #define REAL_BITS 14 // MAXIMUM OF 14 FOR FIXED POINT SBR @@ -240,9 +244,27 @@ static INLINE void ComplexMult(real_t *y1, real_t *y2, return _MulHigh(A,B) << (32-FRAC_BITS); } #else +#ifdef __BFIN__ +#define _MulHigh(X,Y) ({ int __xxo; \ + asm ( \ + "a1 = %2.H * %1.L (IS,M);\n\t" \ + "a0 = %1.H * %2.H, a1+= %1.H * %2.L (IS,M);\n\t"\ + "a1 = a1 >>> 16;\n\t" \ + "%0 = (a0 += a1);\n\t" \ + : "=d" (__xxo) : "d" (X), "d" (Y) : "A0","A1"); __xxo; }) + +#define MUL_F(X,Y) ({ int __xxo; \ + asm ( \ + "a1 = %2.H * %1.L (M);\n\t" \ + "a0 = %1.H * %2.H, a1+= %1.H * %2.L (M);\n\t" \ + "a1 = a1 >>> 16;\n\t" \ + "%0 = (a0 += a1);\n\t" \ + : "=d" (__xxo) : "d" (X), "d" (Y) : "A0","A1"); __xxo; }) +#else #define _MulHigh(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (FRAC_SIZE-1))) >> FRAC_SIZE) #define MUL_F(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (FRAC_BITS-1))) >> FRAC_BITS) #endif +#endif #define MUL_Q2(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (Q2_BITS-1))) >> Q2_BITS) #define MUL_SHIFT6(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (6-1))) >> 6) #define MUL_SHIFT23(A,B) (real_t)(((int64_t)(A)*(int64_t)(B)+(1 << (23-1))) >> 23) diff --git a/src/libfaad/hcr.c b/src/libfaad/hcr.c index 94f08fd2a..c76629641 100644 --- a/src/libfaad/hcr.c +++ b/src/libfaad/hcr.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2004 G.C. Pascutto, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: hcr.c,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: hcr.c,v 1.24 2007/11/01 12:33:30 menno Exp $ **/ #include "common.h" @@ -222,6 +225,7 @@ uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, uint16_t sp_offset[8]; uint16_t g, i, sortloop, set, bitsread; + uint16_t bitsleft, codewordsleft; uint8_t w_idx, sfb, this_CB, last_CB, this_sec_CB; const uint16_t nshort = hDecoder->frameLength/8; @@ -236,7 +240,7 @@ uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, /* since there is spectral data, at least one codeword has nonzero length */ if (ics->length_of_longest_codeword == 0) return 10; - + if (sp_data_len < ics->length_of_longest_codeword) return 10; @@ -272,7 +276,7 @@ uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, for (sfb = 0; sfb < ics->max_sfb; sfb++) { /* loop over all in this sfb, 4 lines per loop */ - for (w_idx = 0; 4*w_idx < (ics->swb_offset[sfb+1] - ics->swb_offset[sfb]); w_idx++) + for (w_idx = 0; 4*w_idx < (min(ics->swb_offset[sfb+1], ics->swb_offset_max) - ics->swb_offset[sfb]); w_idx++) { for(g = 0; g < ics->num_window_groups; g++) { @@ -404,6 +408,25 @@ uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, rewrev_bits(&segment[i]); } +#if 0 // Seems to give false errors + bitsleft = 0; + + for (i = 0; i < numberOfSegments && !bitsleft; i++) + bitsleft += segment[i].len; + + if (bitsleft) return 10; + + codewordsleft = 0; + + for (i = 0; (i < numberOfCodewords - numberOfSegments) && (!codewordsleft); i++) + if (!codeword[i].decoded) + codewordsleft++; + + if (codewordsleft) return 10; +#endif + + return 0; + } #endif diff --git a/src/libfaad/huffman.c b/src/libfaad/huffman.c index 6c24a6cec..e2656c089 100644 --- a/src/libfaad/huffman.c +++ b/src/libfaad/huffman.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: huffman.c,v 1.5 2005/10/29 23:57:06 tmmm Exp $ +** $Id: huffman.c,v 1.26 2007/11/01 12:33:30 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/huffman.h b/src/libfaad/huffman.h index cffe23093..f8bcb237e 100644 --- a/src/libfaad/huffman.h +++ b/src/libfaad/huffman.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: huffman.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: huffman.h,v 1.28 2007/11/01 12:33:30 menno Exp $ **/ #ifndef __HUFFMAN_H__ diff --git a/src/libfaad/ic_predict.c b/src/libfaad/ic_predict.c index 82753a9f2..70027ba2f 100644 --- a/src/libfaad/ic_predict.c +++ b/src/libfaad/ic_predict.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ic_predict.c,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: ic_predict.c,v 1.28 2007/11/01 12:33:31 menno Exp $ **/ #include "common.h" @@ -81,7 +84,8 @@ static void ic_predict(pred_state *state, real_t input, real_t *output, uint8_t { uint16_t tmp; int16_t i, j; - real_t dr1, predictedvalue; + real_t dr1; + float32_t predictedvalue; real_t e0, e1; real_t k1, k2; @@ -114,7 +118,7 @@ static void ic_predict(pred_state *state, real_t input, real_t *output, uint8_t #define B 0.953125 real_t c = COR[0]; real_t v = VAR[0]; - real_t tmp; + float32_t tmp; if (c == 0 || v <= 1) { k1 = 0; @@ -144,7 +148,7 @@ static void ic_predict(pred_state *state, real_t input, real_t *output, uint8_t #define B 0.953125 real_t c = COR[1]; real_t v = VAR[1]; - real_t tmp; + float32_t tmp; if (c == 0 || v <= 1) { k2 = 0; @@ -209,7 +213,7 @@ void pns_reset_pred_state(ic_stream *ics, pred_state *state) if (is_noise(ics, g, sfb)) { offs = ics->swb_offset[sfb]; - offs2 = ics->swb_offset[sfb+1]; + offs2 = min(ics->swb_offset[sfb+1], ics->swb_offset_max); for (i = offs; i < offs2; i++) reset_pred_state(&state[i]); @@ -241,7 +245,7 @@ void ic_prediction(ic_stream *ics, real_t *spec, pred_state *state, for (sfb = 0; sfb < max_pred_sfb(sf_index); sfb++) { uint16_t low = ics->swb_offset[sfb]; - uint16_t high = ics->swb_offset[sfb+1]; + uint16_t high = min(ics->swb_offset[sfb+1], ics->swb_offset_max); for (bin = low; bin < high; bin++) { diff --git a/src/libfaad/ic_predict.h b/src/libfaad/ic_predict.h index 233992b96..e69cd114e 100644 --- a/src/libfaad/ic_predict.h +++ b/src/libfaad/ic_predict.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ic_predict.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: ic_predict.h,v 1.23 2007/11/01 12:33:31 menno Exp $ **/ #ifdef MAIN_DEC diff --git a/src/libfaad/iq_table.h b/src/libfaad/iq_table.h index 9002e15d7..3cc2b8061 100644 --- a/src/libfaad/iq_table.h +++ b/src/libfaad/iq_table.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: iq_table.h,v 1.6 2005/10/29 23:57:06 tmmm Exp $ +** $Id: iq_table.h,v 1.20 2007/11/01 12:33:31 menno Exp $ **/ #ifndef IQ_TABLE_H__ diff --git a/src/libfaad/is.c b/src/libfaad/is.c index 9fcdbcbb5..5236db077 100644 --- a/src/libfaad/is.c +++ b/src/libfaad/is.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: is.c,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: is.c,v 1.28 2007/11/01 12:33:31 menno Exp $ **/ #include "common.h" @@ -84,7 +87,7 @@ void is_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, /* Scale from left to right channel, do not touch left channel */ - for (i = icsr->swb_offset[sfb]; i < icsr->swb_offset[sfb+1]; i++) + for (i = icsr->swb_offset[sfb]; i < min(icsr->swb_offset[sfb+1], ics->swb_offset_max); i++) { #ifndef FIXED_POINT r_spec[(group*nshort)+i] = MUL_R(l_spec[(group*nshort)+i], scale); diff --git a/src/libfaad/is.h b/src/libfaad/is.h index 0786f7258..3e3b750ab 100644 --- a/src/libfaad/is.h +++ b/src/libfaad/is.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: is.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: is.h,v 1.20 2007/11/01 12:33:31 menno Exp $ **/ #ifndef __IS_H__ diff --git a/src/libfaad/kbd_win.h b/src/libfaad/kbd_win.h index 046b6b995..de404c7ea 100644 --- a/src/libfaad/kbd_win.h +++ b/src/libfaad/kbd_win.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: kbd_win.h,v 1.7 2005/10/29 23:57:06 tmmm Exp $ +** $Id: kbd_win.h,v 1.21 2007/11/01 12:33:31 menno Exp $ **/ #ifndef __KBD_WIN_H__ diff --git a/src/libfaad/lt_predict.c b/src/libfaad/lt_predict.c index 3aab00426..2be18ae9f 100644 --- a/src/libfaad/lt_predict.c +++ b/src/libfaad/lt_predict.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: lt_predict.c,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: lt_predict.c,v 1.27 2007/11/01 12:33:31 menno Exp $ **/ @@ -53,9 +56,6 @@ uint8_t is_ltp_ot(uint8_t object_type) #ifdef LD_DEC || (object_type == LD) #endif -#ifdef SCALABLE_DEC - || (object_type == 6) /* TODO */ -#endif ) { return 1; @@ -120,7 +120,7 @@ void lt_prediction(ic_stream *ics, ltp_info *ltp, real_t *spec, if (ltp->long_used[sfb]) { uint16_t low = ics->swb_offset[sfb]; - uint16_t high = ics->swb_offset[sfb+1]; + uint16_t high = min(ics->swb_offset[sfb+1], ics->swb_offset_max); for (bin = low; bin < high; bin++) { diff --git a/src/libfaad/lt_predict.h b/src/libfaad/lt_predict.h index faa2fbca7..117f83424 100644 --- a/src/libfaad/lt_predict.h +++ b/src/libfaad/lt_predict.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: lt_predict.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: lt_predict.h,v 1.20 2007/11/01 12:33:31 menno Exp $ **/ #ifdef LTP_DEC diff --git a/src/libfaad/mdct.c b/src/libfaad/mdct.c index 0df3d6aae..247691e40 100644 --- a/src/libfaad/mdct.c +++ b/src/libfaad/mdct.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: mdct.c,v 1.11 2005/10/29 23:57:07 tmmm Exp $ +** $Id: mdct.c,v 1.47 2007/11/01 12:33:31 menno Exp $ **/ /* @@ -33,7 +36,7 @@ * As described in: * P. Duhamel, Y. Mahieux, and J.P. Petit, "A Fast Algorithm for the * Implementation of Filter Banks Based on 'Time Domain Aliasing - * Cancellation'," IEEE Proc. on ICASSP'91, 1991, pp. 2209-2212. + * Cancellation’," IEEE Proc. on ICASSP‘91, 1991, pp. 2209-2212. * * * As of April 6th 2002 completely rewritten. diff --git a/src/libfaad/mdct.h b/src/libfaad/mdct.h index c2b738795..736180ead 100644 --- a/src/libfaad/mdct.h +++ b/src/libfaad/mdct.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: mdct.h,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: mdct.h,v 1.30 2007/11/01 12:33:31 menno Exp $ **/ #ifndef __MDCT_H__ diff --git a/src/libfaad/mdct_tab.h b/src/libfaad/mdct_tab.h index 7dd17166b..eea285b67 100644 --- a/src/libfaad/mdct_tab.h +++ b/src/libfaad/mdct_tab.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: mdct_tab.h,v 1.1 2005/10/30 00:50:19 tmmm Exp $ +** $Id: mdct_tab.h,v 1.7 2007/11/01 12:33:32 menno Exp $ **/ #ifndef __MDCT_TAB_H__ diff --git a/src/libfaad/mp4.c b/src/libfaad/mp4.c index 651280805..ef3f8a9c9 100644 --- a/src/libfaad/mp4.c +++ b/src/libfaad/mp4.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: mp4.c,v 1.9 2005/10/29 23:57:07 tmmm Exp $ +** $Id: mp4.c,v 1.38 2007/11/01 12:33:32 menno Exp $ **/ #include "common.h" @@ -58,11 +61,7 @@ static uint8_t ObjectTypesTable[32] = { #else 0, /* 5 SBR */ #endif -#ifdef SCALABLE_DEC - 1, /* 6 AAC Scalable */ -#else 0, /* 6 AAC Scalable */ -#endif 0, /* 7 TwinVQ */ 0, /* 8 CELP */ 0, /* 9 HVXC */ @@ -83,11 +82,7 @@ static uint8_t ObjectTypesTable[32] = { #else 0, /* 19 ER AAC LTP */ #endif -#ifdef SCALABLE_DEC - 1, /* 20 ER AAC scalable */ -#else 0, /* 20 ER AAC scalable */ -#endif 0, /* 21 ER TwinVQ */ 0, /* 22 ER BSAC */ #ifdef LD_DEC @@ -248,10 +243,10 @@ int8_t AudioSpecificConfig2(uint8_t *pBuffer, if (syncExtensionType == 0x2b7) { - mp4ASC->objectTypeIndex = (uint8_t)faad_getbits(&ld, 5 + uint8_t tmp_OTi = (uint8_t)faad_getbits(&ld, 5 DEBUGVAR(1,10,"parse_audio_decoder_specific_info(): extensionAudioObjectType")); - if (mp4ASC->objectTypeIndex == 5) + if (tmp_OTi == 5) { mp4ASC->sbr_present_flag = (uint8_t)faad_get1bit(&ld DEBUGVAR(1,11,"parse_audio_decoder_specific_info(): sbr_present_flag")); @@ -259,6 +254,10 @@ int8_t AudioSpecificConfig2(uint8_t *pBuffer, if (mp4ASC->sbr_present_flag) { uint8_t tmp; + + /* Don't set OT to SBR until checked that it is actually there */ + mp4ASC->objectTypeIndex = tmp_OTi; + tmp = (uint8_t)faad_getbits(&ld, 4 DEBUGVAR(1,12,"parse_audio_decoder_specific_info(): extensionSamplingFrequencyIndex")); diff --git a/src/libfaad/mp4.h b/src/libfaad/mp4.h index 478c9b9be..532ba3524 100644 --- a/src/libfaad/mp4.h +++ b/src/libfaad/mp4.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: mp4.h,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: mp4.h,v 1.25 2007/11/01 12:33:32 menno Exp $ **/ #ifndef __MP4_H__ diff --git a/src/libfaad/ms.c b/src/libfaad/ms.c index 93b0a2051..97c8fb198 100644 --- a/src/libfaad/ms.c +++ b/src/libfaad/ms.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ms.c,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: ms.c,v 1.21 2007/11/01 12:33:32 menno Exp $ **/ #include "common.h" @@ -58,7 +61,7 @@ void ms_decode(ic_stream *ics, ic_stream *icsr, real_t *l_spec, real_t *r_spec, if ((ics->ms_used[g][sfb] || ics->ms_mask_present == 2) && !is_intensity(icsr, g, sfb) && !is_noise(ics, g, sfb)) { - for (i = ics->swb_offset[sfb]; i < ics->swb_offset[sfb+1]; i++) + for (i = ics->swb_offset[sfb]; i < min(ics->swb_offset[sfb+1], ics->swb_offset_max); i++) { k = (group*nshort) + i; tmp = l_spec[k] - r_spec[k]; diff --git a/src/libfaad/ms.h b/src/libfaad/ms.h index 4bc7c8175..30cfadaf6 100644 --- a/src/libfaad/ms.h +++ b/src/libfaad/ms.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ms.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: ms.h,v 1.19 2007/11/01 12:33:32 menno Exp $ **/ #ifndef __MS_H__ diff --git a/src/libfaad/output.c b/src/libfaad/output.c index 33ebed39c..a96ebd983 100644 --- a/src/libfaad/output.c +++ b/src/libfaad/output.c @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: output.c,v 1.9 2006/06/30 21:36:27 dgp85 Exp $ +** $Id: output.c,v 1.46 2007/11/01 12:33:32 menno Exp $ **/ #include "common.h" @@ -463,7 +466,7 @@ static INLINE real_t get_sample(real_t **input, uint8_t channel, uint16_t sample } } -static void* output_to_PCM_orig(NeAACDecHandle hDecoder, +void* output_to_PCM(NeAACDecHandle hDecoder, real_t **input, void *sample_buffer, uint8_t channels, uint16_t frame_len, uint8_t format) { @@ -554,56 +557,4 @@ static void* output_to_PCM_orig(NeAACDecHandle hDecoder, return sample_buffer; } -void *output_to_PCM(NeAACDecHandle hDecoder, - real_t **input, void *sample_buffer, uint8_t channels, - uint16_t frame_len, uint8_t format) -{ - int ch, i; - int16_t *short_sample_buffer; - real_t *ch0, *ch1, *ch2, *ch3, *ch4; - - if (format != FAAD_FMT_16BIT) - return output_to_PCM_orig(hDecoder, input, sample_buffer, channels, frame_len, format); - - short_sample_buffer = (int16_t *)sample_buffer; - ch0 = input[hDecoder->internal_channel[0]]; - ch1 = input[hDecoder->internal_channel[1]]; - ch2 = input[hDecoder->internal_channel[2]]; - ch3 = input[hDecoder->internal_channel[3]]; - ch4 = input[hDecoder->internal_channel[4]]; - - if (hDecoder->downMatrix) - { - for (i = 0; i < frame_len; ++i) - { - int32_t tmp = (ch1[i] + ((ch0[i] + ch3[i]) >> 1) + ((ch0[i] + ch3[i]) >> 2) + (1 << (REAL_BITS))) >> (REAL_BITS + 1); - if ((tmp + 0x8000) & ~0xffff) - tmp = ~(tmp >> 31) - 0x8000; - short_sample_buffer[0] = tmp; - tmp = (ch2[i] + ((ch0[i] + ch4[i]) >> 1) + ((ch0[i] + ch4[i]) >> 2) + (1 << (REAL_BITS))) >> (REAL_BITS + 1); - if ((tmp + 0x8000) & ~0xffff) - tmp = ~(tmp >> 31) - 0x8000; - short_sample_buffer[1] = tmp; - short_sample_buffer += channels; - } - return sample_buffer; - } - - /* Copy output to a standard PCM buffer */ - for (i = 0; i < frame_len; ++i) - { - for (ch = 0; ch < channels; ++ch) - { - int32_t tmp = input[hDecoder->internal_channel[ch]][i]; - tmp += (1 << (REAL_BITS - 1)); - tmp >>= REAL_BITS; - if ((tmp + 0x8000) & ~0xffff) - tmp = ~(tmp >> 31) - 0x8000; - *(short_sample_buffer++) = tmp; - } - } - - return sample_buffer; -} - #endif diff --git a/src/libfaad/output.h b/src/libfaad/output.h index 1b15dae58..0451d8b73 100644 --- a/src/libfaad/output.h +++ b/src/libfaad/output.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: output.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: output.h,v 1.25 2007/11/01 12:33:32 menno Exp $ **/ #ifndef __OUTPUT_H__ diff --git a/src/libfaad/pns.c b/src/libfaad/pns.c index 5266d8eef..248fd05ef 100644 --- a/src/libfaad/pns.c +++ b/src/libfaad/pns.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: pns.c,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: pns.c,v 1.38 2007/11/01 12:33:32 menno Exp $ **/ #include "common.h" @@ -33,7 +36,8 @@ /* static function declarations */ static void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t size, - uint8_t sub); + uint8_t sub, + /* RNG states */ uint32_t *__r1, uint32_t *__r2); #ifdef FIXED_POINT @@ -68,7 +72,7 @@ real_t fp_sqrt(real_t value) return root; } -static real_t pow2_table[] = +static real_t const pow2_table[] = { COEF_CONST(1.0), COEF_CONST(1.18920711500272), @@ -83,7 +87,8 @@ static real_t pow2_table[] = multiplication/accumulation per random value. */ static INLINE void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t size, - uint8_t sub) + uint8_t sub, + /* RNG states */ uint32_t *__r1, uint32_t *__r2) { #ifndef FIXED_POINT uint16_t i; @@ -93,7 +98,7 @@ static INLINE void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t for (i = 0; i < size; i++) { - real_t tmp = scale*(real_t)(int32_t)random_int(); + real_t tmp = scale*(real_t)(int32_t)ne_rng(__r1, __r2); spec[i] = tmp; energy += tmp*tmp; } @@ -112,7 +117,7 @@ static INLINE void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t for (i = 0; i < size; i++) { /* this can be replaced by a 16 bit random generator!!!! */ - real_t tmp = (int32_t)random_int(); + real_t tmp = (int32_t)ne_rng(__r1, __r2); if (tmp < 0) tmp = -(tmp & ((1<<(REAL_BITS-1))-1)); else @@ -152,7 +157,8 @@ static INLINE void gen_rand_vector(real_t *spec, int16_t scale_factor, uint16_t void pns_decode(ic_stream *ics_left, ic_stream *ics_right, real_t *spec_left, real_t *spec_right, uint16_t frame_len, - uint8_t channel_pair, uint8_t object_type) + uint8_t channel_pair, uint8_t object_type, + /* RNG states */ uint32_t *__r1, uint32_t *__r2) { uint8_t g, sfb, b; uint16_t size, offs; @@ -202,11 +208,11 @@ void pns_decode(ic_stream *ics_left, ic_stream *ics_right, #endif offs = ics_left->swb_offset[sfb]; - size = ics_left->swb_offset[sfb+1] - offs; + size = min(ics_left->swb_offset[sfb+1], ics_left->swb_offset_max) - offs; /* Generate random vector */ gen_rand_vector(&spec_left[(group*nshort)+offs], - ics_left->scale_factors[g][sfb], size, sub); + ics_left->scale_factors[g][sfb], size, sub, __r1, __r2); } /* From the spec: @@ -233,7 +239,7 @@ void pns_decode(ic_stream *ics_left, ic_stream *ics_right, uint16_t c; offs = ics_right->swb_offset[sfb]; - size = ics_right->swb_offset[sfb+1] - offs; + size = min(ics_right->swb_offset[sfb+1], ics_right->swb_offset_max) - offs; for (c = 0; c < size; c++) { @@ -250,11 +256,11 @@ void pns_decode(ic_stream *ics_left, ic_stream *ics_right, #endif offs = ics_right->swb_offset[sfb]; - size = ics_right->swb_offset[sfb+1] - offs; + size = min(ics_right->swb_offset[sfb+1], ics_right->swb_offset_max) - offs; /* Generate random vector */ gen_rand_vector(&spec_right[(group*nshort)+offs], - ics_right->scale_factors[g][sfb], size, sub); + ics_right->scale_factors[g][sfb], size, sub, __r1, __r2); } } } diff --git a/src/libfaad/pns.h b/src/libfaad/pns.h index 2f246cc4f..38ced252d 100644 --- a/src/libfaad/pns.h +++ b/src/libfaad/pns.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: pns.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: pns.h,v 1.27 2007/11/01 12:33:33 menno Exp $ **/ #ifndef __PNS_H__ @@ -38,7 +41,8 @@ extern "C" { void pns_decode(ic_stream *ics_left, ic_stream *ics_right, real_t *spec_left, real_t *spec_right, uint16_t frame_len, - uint8_t channel_pair, uint8_t object_type); + uint8_t channel_pair, uint8_t object_type, + /* RNG states */ uint32_t *__r1, uint32_t *__r2); static INLINE uint8_t is_noise(ic_stream *ics, uint8_t group, uint8_t sfb) { diff --git a/src/libfaad/ps_dec.c b/src/libfaad/ps_dec.c index 3b957bfda..aebfe0a48 100644 --- a/src/libfaad/ps_dec.c +++ b/src/libfaad/ps_dec.c @@ -1,28 +1,31 @@ /* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR and PS decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ps_dec.c,v 1.3 2006/09/26 17:55:59 dgp85 Exp $ +** $Id: ps_dec.c,v 1.14 2007/11/01 12:33:33 menno Exp $ **/ #include "common.h" @@ -159,7 +162,7 @@ typedef struct /* static function declarations */ static void ps_data_decode(ps_info *ps); -static hyb_info *hybrid_init(void); +static hyb_info *hybrid_init(); static void channel_filter2(hyb_info *hyb, uint8_t frame_len, const real_t *filter, qmf_t *buffer, qmf_t **X_hybrid); static void INLINE DCT3_4_unscaled(real_t *y, real_t *x); @@ -175,7 +178,7 @@ static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev, int8_t min_index, int8_t max_index); static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_prev, uint8_t dt_flag, uint8_t nr_par, uint8_t stride, - int8_t log2modulo); + int8_t and_modulo); static void map20indexto34(int8_t *index, uint8_t bins); #ifdef PS_LOW_POWER static void map34indexto20(int8_t *index, uint8_t bins); @@ -189,7 +192,7 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64 /* */ -static hyb_info *hybrid_init(void) +static hyb_info *hybrid_init() { uint8_t i; @@ -230,16 +233,24 @@ static void hybrid_free(hyb_info *hyb) { uint8_t i; - faad_free(hyb->work); + if (hyb->work) + faad_free(hyb->work); for (i = 0; i < 5; i++) - faad_free(hyb->buffer[i]); - faad_free(hyb->buffer); + { + if (hyb->buffer[i]) + faad_free(hyb->buffer[i]); + } + if (hyb->buffer) + faad_free(hyb->buffer); for (i = 0; i < hyb->frame_len; i++) - faad_free(hyb->temp[i]); - - faad_free(hyb->temp); + { + if (hyb->temp[i]) + faad_free(hyb->temp[i]); + } + if (hyb->temp) + faad_free(hyb->temp); } /* real filter, size 2 */ @@ -666,7 +677,7 @@ static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev, /* in: log2 value of the modulo value to allow using AND instead of MOD */ static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_prev, uint8_t dt_flag, uint8_t nr_par, uint8_t stride, - int8_t log2modulo) + int8_t and_modulo) { int8_t i; @@ -676,19 +687,19 @@ static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_pre { /* delta coded in frequency direction */ index[0] = 0 + index[0]; - index[0] &= log2modulo; + index[0] &= and_modulo; for (i = 1; i < nr_par; i++) { index[i] = index[i-1] + index[i]; - index[i] &= log2modulo; + index[i] &= and_modulo; } } else { /* delta coded in time direction */ for (i = 0; i < nr_par; i++) { index[i] = index_prev[i*stride] + index[i]; - index[i] &= log2modulo; + index[i] &= and_modulo; } } } else { @@ -833,11 +844,11 @@ static void ps_data_decode(ps_info *ps) /* delta modulo decode ipd parameters */ delta_modulo_decode(ps->enable_ipdopd, ps->ipd_index[env], ipd_index_prev, - ps->ipd_dt[env], ps->nr_ipdopd_par, 1, /*log2(8)*/ 3); + ps->ipd_dt[env], ps->nr_ipdopd_par, 1, 7); /* delta modulo decode opd parameters */ delta_modulo_decode(ps->enable_ipdopd, ps->opd_index[env], opd_index_prev, - ps->opd_dt[env], ps->nr_ipdopd_par, 1, /*log2(8)*/ 3); + ps->opd_dt[env], ps->nr_ipdopd_par, 1, 7); } /* handle error case */ @@ -906,8 +917,6 @@ static void ps_data_decode(ps_info *ps) if (ps->border_position[ps->num_env] < 32 /* 30 for 960? */) { - ps->num_env++; - ps->border_position[ps->num_env] = 32 /* 30 for 960? */; for (bin = 0; bin < 34; bin++) { ps->iid_index[ps->num_env][bin] = ps->iid_index[ps->num_env-1][bin]; @@ -918,6 +927,8 @@ static void ps_data_decode(ps_info *ps) ps->ipd_index[ps->num_env][bin] = ps->ipd_index[ps->num_env-1][bin]; ps->opd_index[ps->num_env][bin] = ps->opd_index[ps->num_env-1][bin]; } + ps->num_env++; + ps->border_position[ps->num_env] = 32 /* 30 for 960? */; } for (env = 1; env < ps->num_env; env++) @@ -1410,6 +1421,26 @@ static const real_t ipdopd_sin_tab[] = { FRAC_CONST(-0.000000000000000) }; +static real_t magnitude_c(complex_t c) +{ +#ifdef FIXED_POINT +#define ps_abs(A) (((A) > 0) ? (A) : (-(A))) +#define ALPHA FRAC_CONST(0.948059448969) +#define BETA FRAC_CONST(0.392699081699) + + real_t abs_inphase = ps_abs(RE(c)); + real_t abs_quadrature = ps_abs(IM(c)); + + if (abs_inphase > abs_quadrature) { + return MUL_F(abs_inphase, ALPHA) + MUL_F(abs_quadrature, BETA); + } else { + return MUL_F(abs_quadrature, ALPHA) + MUL_F(abs_inphase, BETA); + } +#else + return sqrt(RE(c)*RE(c) + IM(c)*IM(c)); +#endif +} + static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64], qmf_t X_hybrid_left[32][32], qmf_t X_hybrid_right[32][32]) { @@ -1580,8 +1611,7 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64 if ((ps->enable_ipdopd) && (bk < nr_ipdopd_par)) { int8_t i; - real_t xxyy, ppqq; - real_t yq, xp, xq, py, tmp; + real_t xy, pq, xypq; /* ringbuffer index */ i = ps->phase_hist; @@ -1614,7 +1644,7 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64 /* ringbuffer index */ if (i == 0) - { + { i = 2; } i--; @@ -1644,53 +1674,54 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64 RE(phaseRight) = (float)cos(opd); IM(phaseRight) = (float)sin(opd); #else + // x = IM(tempLeft) // y = RE(tempLeft) // p = IM(tempRight) // q = RE(tempRight) - // cos(atan2(x,y)) = 1/sqrt(1 + (x*x)/(y*y)) - // sin(atan2(x,y)) = x/(y*sqrt(1 + (x*x)/(y*y))) - // cos(atan2(x,y)-atan2(p,q)) = (y*q+x*p)/(y*q * sqrt(1 + (x*x)/(y*y)) * sqrt(1 + (p*p)/(q*q))); - // sin(atan2(x,y)-atan2(p,q)) = (x*q-p*y)/(y*q * sqrt(1 + (x*x)/(y*y)) * sqrt(1 + (p*p)/(q*q))); + // cos(atan2(x,y)) = y/sqrt((x*x) + (y*y)) + // sin(atan2(x,y)) = x/sqrt((x*x) + (y*y)) + // cos(atan2(x,y)-atan2(p,q)) = (y*q + x*p) / ( sqrt((x*x) + (y*y)) * sqrt((p*p) + (q*q)) ); + // sin(atan2(x,y)-atan2(p,q)) = (x*q - y*p) / ( sqrt((x*x) + (y*y)) * sqrt((p*p) + (q*q)) ); - /* (x*x)/(y*y) (REAL > 0) */ - xxyy = DIV_R(MUL_C(IM(tempLeft),IM(tempLeft)), MUL_C(RE(tempLeft),RE(tempLeft))); - ppqq = DIV_R(MUL_C(IM(tempRight),IM(tempRight)), MUL_C(RE(tempRight),RE(tempRight))); + xy = magnitude_c(tempRight); + pq = magnitude_c(tempLeft); - /* 1 + (x*x)/(y*y) (REAL > 1) */ - xxyy += REAL_CONST(1); - ppqq += REAL_CONST(1); - - /* 1 / sqrt(1 + (x*x)/(y*y)) (FRAC <= 1) */ - xxyy = DIV_R(FRAC_CONST(1), ps_sqrt(xxyy)); - ppqq = DIV_R(FRAC_CONST(1), ps_sqrt(ppqq)); + if (xy != 0) + { + RE(phaseLeft) = DIV_R(RE(tempRight), xy); + IM(phaseLeft) = DIV_R(IM(tempRight), xy); + } else { + RE(phaseLeft) = 0; + IM(phaseLeft) = 0; + } - /* COEF */ - yq = MUL_C(RE(tempLeft), RE(tempRight)); - xp = MUL_C(IM(tempLeft), IM(tempRight)); - xq = MUL_C(IM(tempLeft), RE(tempRight)); - py = MUL_C(RE(tempLeft), IM(tempRight)); + xypq = MUL_R(xy, pq); - RE(phaseLeft) = xxyy; - IM(phaseLeft) = MUL_R(xxyy, (DIV_R(IM(tempLeft), RE(tempLeft)))); + if (xypq != 0) + { + real_t tmp1 = MUL_R(RE(tempRight), RE(tempLeft)) + MUL_R(IM(tempRight), IM(tempLeft)); + real_t tmp2 = MUL_R(IM(tempRight), RE(tempLeft)) - MUL_R(RE(tempRight), IM(tempLeft)); - tmp = DIV_C(MUL_F(xxyy, ppqq), yq); + RE(phaseRight) = DIV_R(tmp1, xypq); + IM(phaseRight) = DIV_R(tmp2, xypq); + } else { + RE(phaseRight) = 0; + IM(phaseRight) = 0; + } - /* MUL_C(FRAC,COEF) = FRAC */ - RE(phaseRight) = MUL_C(tmp, (yq+xp)); - IM(phaseRight) = MUL_C(tmp, (xq-py)); #endif - /* MUL_F(COEF, FRAC) = COEF */ - IM(h11) = MUL_F(RE(h11), IM(phaseLeft)); - IM(h12) = MUL_F(RE(h12), IM(phaseRight)); - IM(h21) = MUL_F(RE(h21), IM(phaseLeft)); - IM(h22) = MUL_F(RE(h22), IM(phaseRight)); + /* MUL_F(COEF, REAL) = COEF */ + IM(h11) = MUL_R(RE(h11), IM(phaseLeft)); + IM(h12) = MUL_R(RE(h12), IM(phaseRight)); + IM(h21) = MUL_R(RE(h21), IM(phaseLeft)); + IM(h22) = MUL_R(RE(h22), IM(phaseRight)); - RE(h11) = MUL_F(RE(h11), RE(phaseLeft)); - RE(h12) = MUL_F(RE(h12), RE(phaseRight)); - RE(h21) = MUL_F(RE(h21), RE(phaseLeft)); - RE(h22) = MUL_F(RE(h22), RE(phaseRight)); + RE(h11) = MUL_R(RE(h11), RE(phaseLeft)); + RE(h12) = MUL_R(RE(h12), RE(phaseRight)); + RE(h21) = MUL_R(RE(h21), RE(phaseLeft)); + RE(h22) = MUL_R(RE(h22), RE(phaseRight)); } /* length of the envelope n_e+1 - n_e (in time samples) */ @@ -1927,8 +1958,8 @@ ps_info *ps_init(uint8_t sr_index) /* main Parametric Stereo decoding function */ uint8_t ps_decode(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64]) { - qmf_t X_hybrid_left[32][32] = {{{0}}}; - qmf_t X_hybrid_right[32][32] = {{{0}}}; + qmf_t X_hybrid_left[32][32] = {{0}}; + qmf_t X_hybrid_right[32][32] = {{0}}; /* delta decoding of the bitstream data */ ps_data_decode(ps); diff --git a/src/libfaad/ps_dec.h b/src/libfaad/ps_dec.h index 978161fff..d96561404 100644 --- a/src/libfaad/ps_dec.h +++ b/src/libfaad/ps_dec.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ps_dec.h,v 1.1 2005/10/30 00:50:19 tmmm Exp $ +** $Id: ps_dec.h,v 1.12 2007/11/01 12:33:33 menno Exp $ **/ #ifndef __PS_DEC_H__ diff --git a/src/libfaad/ps_syntax.c b/src/libfaad/ps_syntax.c index fc2f9e7f2..50253d459 100644 --- a/src/libfaad/ps_syntax.c +++ b/src/libfaad/ps_syntax.c @@ -1,6 +1,6 @@ /* -** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR and PS decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ps_syntax.c,v 1.1 2005/10/30 00:50:19 tmmm Exp $ +** $Id: ps_syntax.c,v 1.11 2007/11/01 12:33:33 menno Exp $ **/ #include "common.h" @@ -308,9 +311,9 @@ static const int8_t t_huff_opd[][2] = { { 2, 3 }, /* index 1: 2 bits: 0x */ { 4, 5 }, /* index 2: 3 bits: 00x */ { /*1*/ -30, /*7*/ -24 }, /* index 3: 3 bits: 01x */ - { /*5*/ -26, 6 }, /* index 4: 4 bits: 000x */ - { /*2*/ -29, /*6*/ -25 }, /* index 5: 4 bits: 001x */ - { /*4*/ -27, /*3*/ -28 } /* index 6: 5 bits: 0001x */ + { /*5*/ -26, /*2*/ -29 }, /* index 4: 4 bits: 000x */ + { /*6*/ -25, 6 }, /* index 5: 4 bits: 001x */ + { /*4*/ -27, /*3*/ -28 } /* index 6: 5 bits: 0011x */ }; /* static function declarations */ @@ -380,7 +383,10 @@ uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header) /* we are here, but no header has been read yet */ if (ps->header_read == 0) + { + ps->ps_data_available = 0; return 1; + } ps->frame_class = (uint8_t)faad_get1bit(ld DEBUGVAR(1,1006,"ps_data(): frame_class")); @@ -394,7 +400,7 @@ uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header) for (n = 1; n < ps->num_env+1; n++) { ps->border_position[n] = (uint8_t)faad_getbits(ld, 5 - DEBUGVAR(1,1008,"ps_data(): border_position")); + DEBUGVAR(1,1008,"ps_data(): border_position")) + 1; } } diff --git a/src/libfaad/ps_tables.h b/src/libfaad/ps_tables.h index c71489617..f3370be9d 100644 --- a/src/libfaad/ps_tables.h +++ b/src/libfaad/ps_tables.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ps_tables.h,v 1.1 2005/10/30 00:50:19 tmmm Exp $ +** $Id: ps_tables.h,v 1.8 2007/11/01 12:33:33 menno Exp $ **/ #ifndef __PS_TABLES_H__ @@ -541,7 +544,7 @@ static const real_t sf_iid_fine[] = { }; #ifdef __cplusplus - +} #endif #endif diff --git a/src/libfaad/pulse.c b/src/libfaad/pulse.c index 9e0a705e6..3dd973abf 100644 --- a/src/libfaad/pulse.c +++ b/src/libfaad/pulse.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,12 +19,14 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: pulse.c,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: pulse.c,v 1.21 2007/11/01 12:33:34 menno Exp $ **/ - #include "common.h" #include "structs.h" @@ -37,7 +39,7 @@ uint8_t pulse_decode(ic_stream *ics, int16_t *spec_data, uint16_t framelen) uint16_t k; pulse_info *pul = &(ics->pul); - k = ics->swb_offset[pul->pulse_start_sfb]; + k = min(ics->swb_offset[pul->pulse_start_sfb], ics->swb_offset_max); for (i = 0; i <= pul->number_pulse; i++) { diff --git a/src/libfaad/pulse.h b/src/libfaad/pulse.h index a057c0d3b..f7676cd89 100644 --- a/src/libfaad/pulse.h +++ b/src/libfaad/pulse.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: pulse.h,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: pulse.h,v 1.20 2007/11/01 12:33:34 menno Exp $ **/ #ifndef __PULSE_H__ diff --git a/src/libfaad/rvlc.c b/src/libfaad/rvlc.c index bad49a0c6..73619c6d1 100644 --- a/src/libfaad/rvlc.c +++ b/src/libfaad/rvlc.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: rvlc.c,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: rvlc.c,v 1.21 2007/11/01 12:33:34 menno Exp $ **/ /* RVLC scalefactor decoding diff --git a/src/libfaad/rvlc.h b/src/libfaad/rvlc.h index 867468580..56f630fa4 100644 --- a/src/libfaad/rvlc.h +++ b/src/libfaad/rvlc.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: rvlc.h,v 1.6 2005/10/29 23:57:07 tmmm Exp $ +** $Id: rvlc.h,v 1.17 2007/11/01 12:33:34 menno Exp $ **/ #ifndef __RVLC_SCF_H__ diff --git a/src/libfaad/sbr_dct.c b/src/libfaad/sbr_dct.c index ba8bbaf9b..16e7128ea 100644 --- a/src/libfaad/sbr_dct.c +++ b/src/libfaad/sbr_dct.c @@ -1,30 +1,38 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_dct.c,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_dct.c,v 1.20 2007/11/01 12:33:34 menno Exp $ **/ + +/* Most of the DCT/DST codes here are generated using Spiral which is GPL + * For more info see: http://www.spiral.net/ + */ + #include "common.h" #ifdef SBR_DEC @@ -479,6 +487,413 @@ void DCT4_32(real_t *y, real_t *x) y[1] = f397 - f396; } +void DST4_32(real_t *y, real_t *x) +{ + real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9; + real_t f10, f11, f12, f13, f14, f15, f16, f17, f18, f19; + real_t f20, f21, f22, f23, f24, f25, f26, f27, f28, f29; + real_t f30, f31, f32, f33, f34, f35, f36, f37, f38, f39; + real_t f40, f41, f42, f43, f44, f45, f46, f47, f48, f49; + real_t f50, f51, f52, f53, f54, f55, f56, f57, f58, f59; + real_t f60, f61, f62, f63, f64, f65, f66, f67, f68, f69; + real_t f70, f71, f72, f73, f74, f75, f76, f77, f78, f79; + real_t f80, f81, f82, f83, f84, f85, f86, f87, f88, f89; + real_t f90, f91, f92, f93, f94, f95, f96, f97, f98, f99; + real_t f100, f101, f102, f103, f104, f105, f106, f107, f108, f109; + real_t f110, f111, f112, f113, f114, f115, f116, f117, f118, f119; + real_t f120, f121, f122, f123, f124, f125, f126, f127, f128, f129; + real_t f130, f131, f132, f133, f134, f135, f136, f137, f138, f139; + real_t f140, f141, f142, f143, f144, f145, f146, f147, f148, f149; + real_t f150, f151, f152, f153, f154, f155, f156, f157, f158, f159; + real_t f160, f161, f162, f163, f164, f165, f166, f167, f168, f169; + real_t f170, f171, f172, f173, f174, f175, f176, f177, f178, f179; + real_t f180, f181, f182, f183, f184, f185, f186, f187, f188, f189; + real_t f190, f191, f192, f193, f194, f195, f196, f197, f198, f199; + real_t f200, f201, f202, f203, f204, f205, f206, f207, f208, f209; + real_t f210, f211, f212, f213, f214, f215, f216, f217, f218, f219; + real_t f220, f221, f222, f223, f224, f225, f226, f227, f228, f229; + real_t f230, f231, f232, f233, f234, f235, f236, f237, f238, f239; + real_t f240, f241, f242, f243, f244, f245, f246, f247, f248, f249; + real_t f250, f251, f252, f253, f254, f255, f256, f257, f258, f259; + real_t f260, f261, f262, f263, f264, f265, f266, f267, f268, f269; + real_t f270, f271, f272, f273, f274, f275, f276, f277, f278, f279; + real_t f280, f281, f282, f283, f284, f285, f286, f287, f288, f289; + real_t f290, f291, f292, f293, f294, f295, f296, f297, f298, f299; + real_t f300, f301, f302, f303, f304, f305, f306, f307, f308, f309; + real_t f310, f311, f312, f313, f314, f315, f316, f317, f318, f319; + real_t f320, f321, f322, f323, f324, f325, f326, f327, f328, f329; + real_t f330, f331, f332, f333, f334, f335; + + f0 = x[0] - x[1]; + f1 = x[2] - x[1]; + f2 = x[2] - x[3]; + f3 = x[4] - x[3]; + f4 = x[4] - x[5]; + f5 = x[6] - x[5]; + f6 = x[6] - x[7]; + f7 = x[8] - x[7]; + f8 = x[8] - x[9]; + f9 = x[10] - x[9]; + f10 = x[10] - x[11]; + f11 = x[12] - x[11]; + f12 = x[12] - x[13]; + f13 = x[14] - x[13]; + f14 = x[14] - x[15]; + f15 = x[16] - x[15]; + f16 = x[16] - x[17]; + f17 = x[18] - x[17]; + f18 = x[18] - x[19]; + f19 = x[20] - x[19]; + f20 = x[20] - x[21]; + f21 = x[22] - x[21]; + f22 = x[22] - x[23]; + f23 = x[24] - x[23]; + f24 = x[24] - x[25]; + f25 = x[26] - x[25]; + f26 = x[26] - x[27]; + f27 = x[28] - x[27]; + f28 = x[28] - x[29]; + f29 = x[30] - x[29]; + f30 = x[30] - x[31]; + f31 = MUL_F(FRAC_CONST(0.7071067811865476), f15); + f32 = x[0] - f31; + f33 = x[0] + f31; + f34 = f7 + f23; + f35 = MUL_C(COEF_CONST(1.3065629648763766), f7); + f36 = MUL_F(FRAC_CONST(-0.9238795325112866), f34); + f37 = MUL_F(FRAC_CONST(-0.5411961001461967), f23); + f38 = f35 + f36; + f39 = f37 - f36; + f40 = f33 - f39; + f41 = f33 + f39; + f42 = f32 - f38; + f43 = f32 + f38; + f44 = f11 - f19; + f45 = f11 + f19; + f46 = MUL_F(FRAC_CONST(0.7071067811865476), f45); + f47 = f3 - f46; + f48 = f3 + f46; + f49 = MUL_F(FRAC_CONST(0.7071067811865476), f44); + f50 = f49 - f27; + f51 = f49 + f27; + f52 = f51 + f48; + f53 = MUL_F(FRAC_CONST(-0.7856949583871021), f51); + f54 = MUL_F(FRAC_CONST(0.9807852804032304), f52); + f55 = MUL_C(COEF_CONST(1.1758756024193588), f48); + f56 = f53 + f54; + f57 = f55 - f54; + f58 = f50 + f47; + f59 = MUL_F(FRAC_CONST(-0.2758993792829430), f50); + f60 = MUL_F(FRAC_CONST(0.8314696123025452), f58); + f61 = MUL_C(COEF_CONST(1.3870398453221475), f47); + f62 = f59 + f60; + f63 = f61 - f60; + f64 = f41 - f56; + f65 = f41 + f56; + f66 = f43 - f62; + f67 = f43 + f62; + f68 = f42 - f63; + f69 = f42 + f63; + f70 = f40 - f57; + f71 = f40 + f57; + f72 = f5 - f9; + f73 = f5 + f9; + f74 = f13 - f17; + f75 = f13 + f17; + f76 = f21 - f25; + f77 = f21 + f25; + f78 = MUL_F(FRAC_CONST(0.7071067811865476), f75); + f79 = f1 - f78; + f80 = f1 + f78; + f81 = f73 + f77; + f82 = MUL_C(COEF_CONST(1.3065629648763766), f73); + f83 = MUL_F(FRAC_CONST(-0.9238795325112866), f81); + f84 = MUL_F(FRAC_CONST(-0.5411961001461967), f77); + f85 = f82 + f83; + f86 = f84 - f83; + f87 = f80 - f86; + f88 = f80 + f86; + f89 = f79 - f85; + f90 = f79 + f85; + f91 = MUL_F(FRAC_CONST(0.7071067811865476), f74); + f92 = f29 - f91; + f93 = f29 + f91; + f94 = f76 + f72; + f95 = MUL_C(COEF_CONST(1.3065629648763766), f76); + f96 = MUL_F(FRAC_CONST(-0.9238795325112866), f94); + f97 = MUL_F(FRAC_CONST(-0.5411961001461967), f72); + f98 = f95 + f96; + f99 = f97 - f96; + f100 = f93 - f99; + f101 = f93 + f99; + f102 = f92 - f98; + f103 = f92 + f98; + f104 = f101 + f88; + f105 = MUL_F(FRAC_CONST(-0.8971675863426361), f101); + f106 = MUL_F(FRAC_CONST(0.9951847266721968), f104); + f107 = MUL_C(COEF_CONST(1.0932018670017576), f88); + f108 = f105 + f106; + f109 = f107 - f106; + f110 = f90 - f103; + f111 = MUL_F(FRAC_CONST(-0.6666556584777466), f103); + f112 = MUL_F(FRAC_CONST(0.9569403357322089), f110); + f113 = MUL_C(COEF_CONST(1.2472250129866713), f90); + f114 = f112 - f111; + f115 = f113 - f112; + f116 = f102 + f89; + f117 = MUL_F(FRAC_CONST(-0.4105245275223571), f102); + f118 = MUL_F(FRAC_CONST(0.8819212643483549), f116); + f119 = MUL_C(COEF_CONST(1.3533180011743529), f89); + f120 = f117 + f118; + f121 = f119 - f118; + f122 = f87 - f100; + f123 = MUL_F(FRAC_CONST(-0.1386171691990915), f100); + f124 = MUL_F(FRAC_CONST(0.7730104533627370), f122); + f125 = MUL_C(COEF_CONST(1.4074037375263826), f87); + f126 = f124 - f123; + f127 = f125 - f124; + f128 = f65 - f108; + f129 = f65 + f108; + f130 = f67 - f114; + f131 = f67 + f114; + f132 = f69 - f120; + f133 = f69 + f120; + f134 = f71 - f126; + f135 = f71 + f126; + f136 = f70 - f127; + f137 = f70 + f127; + f138 = f68 - f121; + f139 = f68 + f121; + f140 = f66 - f115; + f141 = f66 + f115; + f142 = f64 - f109; + f143 = f64 + f109; + f144 = f0 + f30; + f145 = MUL_C(COEF_CONST(1.0478631305325901), f0); + f146 = MUL_F(FRAC_CONST(-0.9987954562051724), f144); + f147 = MUL_F(FRAC_CONST(-0.9497277818777548), f30); + f148 = f145 + f146; + f149 = f147 - f146; + f150 = f4 + f26; + f151 = MUL_F(FRAC_CONST(1.2130114330978077), f4); + f152 = MUL_F(FRAC_CONST(-0.9700312531945440), f150); + f153 = MUL_F(FRAC_CONST(-0.7270510732912803), f26); + f154 = f151 + f152; + f155 = f153 - f152; + f156 = f8 + f22; + f157 = MUL_C(COEF_CONST(1.3315443865537255), f8); + f158 = MUL_F(FRAC_CONST(-0.9039892931234433), f156); + f159 = MUL_F(FRAC_CONST(-0.4764341996931612), f22); + f160 = f157 + f158; + f161 = f159 - f158; + f162 = f12 + f18; + f163 = MUL_C(COEF_CONST(1.3989068359730781), f12); + f164 = MUL_F(FRAC_CONST(-0.8032075314806453), f162); + f165 = MUL_F(FRAC_CONST(-0.2075082269882124), f18); + f166 = f163 + f164; + f167 = f165 - f164; + f168 = f16 + f14; + f169 = MUL_C(COEF_CONST(1.4125100802019777), f16); + f170 = MUL_F(FRAC_CONST(-0.6715589548470187), f168); + f171 = MUL_F(FRAC_CONST(0.0693921705079402), f14); + f172 = f169 + f170; + f173 = f171 - f170; + f174 = f20 + f10; + f175 = MUL_C(COEF_CONST(1.3718313541934939), f20); + f176 = MUL_F(FRAC_CONST(-0.5141027441932219), f174); + f177 = MUL_F(FRAC_CONST(0.3436258658070501), f10); + f178 = f175 + f176; + f179 = f177 - f176; + f180 = f24 + f6; + f181 = MUL_C(COEF_CONST(1.2784339185752409), f24); + f182 = MUL_F(FRAC_CONST(-0.3368898533922200), f180); + f183 = MUL_F(FRAC_CONST(0.6046542117908008), f6); + f184 = f181 + f182; + f185 = f183 - f182; + f186 = f28 + f2; + f187 = MUL_C(COEF_CONST(1.1359069844201433), f28); + f188 = MUL_F(FRAC_CONST(-0.1467304744553624), f186); + f189 = MUL_F(FRAC_CONST(0.8424460355094185), f2); + f190 = f187 + f188; + f191 = f189 - f188; + f192 = f149 - f173; + f193 = f149 + f173; + f194 = f148 - f172; + f195 = f148 + f172; + f196 = f155 - f179; + f197 = f155 + f179; + f198 = f154 - f178; + f199 = f154 + f178; + f200 = f161 - f185; + f201 = f161 + f185; + f202 = f160 - f184; + f203 = f160 + f184; + f204 = f167 - f191; + f205 = f167 + f191; + f206 = f166 - f190; + f207 = f166 + f190; + f208 = f192 + f194; + f209 = MUL_C(COEF_CONST(1.1758756024193588), f192); + f210 = MUL_F(FRAC_CONST(-0.9807852804032304), f208); + f211 = MUL_F(FRAC_CONST(-0.7856949583871021), f194); + f212 = f209 + f210; + f213 = f211 - f210; + f214 = f196 + f198; + f215 = MUL_C(COEF_CONST(1.3870398453221475), f196); + f216 = MUL_F(FRAC_CONST(-0.5555702330196022), f214); + f217 = MUL_F(FRAC_CONST(0.2758993792829431), f198); + f218 = f215 + f216; + f219 = f217 - f216; + f220 = f200 + f202; + f221 = MUL_F(FRAC_CONST(0.7856949583871022), f200); + f222 = MUL_F(FRAC_CONST(0.1950903220161283), f220); + f223 = MUL_C(COEF_CONST(1.1758756024193586), f202); + f224 = f221 + f222; + f225 = f223 - f222; + f226 = f204 + f206; + f227 = MUL_F(FRAC_CONST(-0.2758993792829430), f204); + f228 = MUL_F(FRAC_CONST(0.8314696123025452), f226); + f229 = MUL_C(COEF_CONST(1.3870398453221475), f206); + f230 = f227 + f228; + f231 = f229 - f228; + f232 = f193 - f201; + f233 = f193 + f201; + f234 = f195 - f203; + f235 = f195 + f203; + f236 = f197 - f205; + f237 = f197 + f205; + f238 = f199 - f207; + f239 = f199 + f207; + f240 = f213 - f225; + f241 = f213 + f225; + f242 = f212 - f224; + f243 = f212 + f224; + f244 = f219 - f231; + f245 = f219 + f231; + f246 = f218 - f230; + f247 = f218 + f230; + f248 = f232 + f234; + f249 = MUL_C(COEF_CONST(1.3065629648763766), f232); + f250 = MUL_F(FRAC_CONST(-0.9238795325112866), f248); + f251 = MUL_F(FRAC_CONST(-0.5411961001461967), f234); + f252 = f249 + f250; + f253 = f251 - f250; + f254 = f236 + f238; + f255 = MUL_F(FRAC_CONST(0.5411961001461969), f236); + f256 = MUL_F(FRAC_CONST(0.3826834323650898), f254); + f257 = MUL_C(COEF_CONST(1.3065629648763766), f238); + f258 = f255 + f256; + f259 = f257 - f256; + f260 = f240 + f242; + f261 = MUL_C(COEF_CONST(1.3065629648763766), f240); + f262 = MUL_F(FRAC_CONST(-0.9238795325112866), f260); + f263 = MUL_F(FRAC_CONST(-0.5411961001461967), f242); + f264 = f261 + f262; + f265 = f263 - f262; + f266 = f244 + f246; + f267 = MUL_F(FRAC_CONST(0.5411961001461969), f244); + f268 = MUL_F(FRAC_CONST(0.3826834323650898), f266); + f269 = MUL_C(COEF_CONST(1.3065629648763766), f246); + f270 = f267 + f268; + f271 = f269 - f268; + f272 = f233 - f237; + f273 = f233 + f237; + f274 = f235 - f239; + f275 = f235 + f239; + f276 = f253 - f259; + f277 = f253 + f259; + f278 = f252 - f258; + f279 = f252 + f258; + f280 = f241 - f245; + f281 = f241 + f245; + f282 = f243 - f247; + f283 = f243 + f247; + f284 = f265 - f271; + f285 = f265 + f271; + f286 = f264 - f270; + f287 = f264 + f270; + f288 = f272 - f274; + f289 = f272 + f274; + f290 = MUL_F(FRAC_CONST(0.7071067811865474), f288); + f291 = MUL_F(FRAC_CONST(0.7071067811865474), f289); + f292 = f276 - f278; + f293 = f276 + f278; + f294 = MUL_F(FRAC_CONST(0.7071067811865474), f292); + f295 = MUL_F(FRAC_CONST(0.7071067811865474), f293); + f296 = f280 - f282; + f297 = f280 + f282; + f298 = MUL_F(FRAC_CONST(0.7071067811865474), f296); + f299 = MUL_F(FRAC_CONST(0.7071067811865474), f297); + f300 = f284 - f286; + f301 = f284 + f286; + f302 = MUL_F(FRAC_CONST(0.7071067811865474), f300); + f303 = MUL_F(FRAC_CONST(0.7071067811865474), f301); + f304 = f129 - f273; + f305 = f129 + f273; + f306 = f131 - f281; + f307 = f131 + f281; + f308 = f133 - f285; + f309 = f133 + f285; + f310 = f135 - f277; + f311 = f135 + f277; + f312 = f137 - f295; + f313 = f137 + f295; + f314 = f139 - f303; + f315 = f139 + f303; + f316 = f141 - f299; + f317 = f141 + f299; + f318 = f143 - f291; + f319 = f143 + f291; + f320 = f142 - f290; + f321 = f142 + f290; + f322 = f140 - f298; + f323 = f140 + f298; + f324 = f138 - f302; + f325 = f138 + f302; + f326 = f136 - f294; + f327 = f136 + f294; + f328 = f134 - f279; + f329 = f134 + f279; + f330 = f132 - f287; + f331 = f132 + f287; + f332 = f130 - f283; + f333 = f130 + f283; + f334 = f128 - f275; + f335 = f128 + f275; + y[31] = MUL_F(FRAC_CONST(0.5001506360206510), f305); + y[30] = MUL_F(FRAC_CONST(0.5013584524464084), f307); + y[29] = MUL_F(FRAC_CONST(0.5037887256810443), f309); + y[28] = MUL_F(FRAC_CONST(0.5074711720725553), f311); + y[27] = MUL_F(FRAC_CONST(0.5124514794082247), f313); + y[26] = MUL_F(FRAC_CONST(0.5187927131053328), f315); + y[25] = MUL_F(FRAC_CONST(0.5265773151542700), f317); + y[24] = MUL_F(FRAC_CONST(0.5359098169079920), f319); + y[23] = MUL_F(FRAC_CONST(0.5469204379855088), f321); + y[22] = MUL_F(FRAC_CONST(0.5597698129470802), f323); + y[21] = MUL_F(FRAC_CONST(0.5746551840326600), f325); + y[20] = MUL_F(FRAC_CONST(0.5918185358574165), f327); + y[19] = MUL_F(FRAC_CONST(0.6115573478825099), f329); + y[18] = MUL_F(FRAC_CONST(0.6342389366884031), f331); + y[17] = MUL_F(FRAC_CONST(0.6603198078137061), f333); + y[16] = MUL_F(FRAC_CONST(0.6903721282002123), f335); + y[15] = MUL_F(FRAC_CONST(0.7251205223771985), f334); + y[14] = MUL_F(FRAC_CONST(0.7654941649730891), f332); + y[13] = MUL_F(FRAC_CONST(0.8127020908144905), f330); + y[12] = MUL_F(FRAC_CONST(0.8683447152233481), f328); + y[11] = MUL_F(FRAC_CONST(0.9345835970364075), f326); + y[10] = MUL_C(COEF_CONST(1.0144082649970547), f324); + y[9] = MUL_C(COEF_CONST(1.1120716205797176), f322); + y[8] = MUL_C(COEF_CONST(1.2338327379765710), f320); + y[7] = MUL_C(COEF_CONST(1.3892939586328277), f318); + y[6] = MUL_C(COEF_CONST(1.5939722833856311), f316); + y[5] = MUL_C(COEF_CONST(1.8746759800084078), f314); + y[4] = MUL_C(COEF_CONST(2.2820500680051619), f312); + y[3] = MUL_C(COEF_CONST(2.9246284281582162), f310); + y[2] = MUL_C(COEF_CONST(4.0846110781292477), f308); + y[1] = MUL_C(COEF_CONST(6.7967507116736332), f306); + y[0] = MUL_R(REAL_CONST(20.3738781672314530), f304); +} + #ifdef SBR_LOW_POWER void DCT2_16_unscaled(real_t *y, real_t *x) @@ -1811,7 +2226,7 @@ void dct4_kernel(real_t * in_real, real_t * in_imag, real_t * out_real, real_t * { // Tables with bit reverse values for 5 bits, bit reverse of i at i-th position const uint8_t bit_rev_tab[32] = { 0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30,1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31 }; - uint16_t i, i_rev; + uint32_t i, i_rev; /* Step 2: modulate */ // 3*32=96 multiplications @@ -1859,413 +2274,6 @@ void dct4_kernel(real_t * in_real, real_t * in_imag, real_t * out_real, real_t * } -void DST4_32(real_t *y, real_t *x) -{ - real_t f0, f1, f2, f3, f4, f5, f6, f7, f8, f9; - real_t f10, f11, f12, f13, f14, f15, f16, f17, f18, f19; - real_t f20, f21, f22, f23, f24, f25, f26, f27, f28, f29; - real_t f30, f31, f32, f33, f34, f35, f36, f37, f38, f39; - real_t f40, f41, f42, f43, f44, f45, f46, f47, f48, f49; - real_t f50, f51, f52, f53, f54, f55, f56, f57, f58, f59; - real_t f60, f61, f62, f63, f64, f65, f66, f67, f68, f69; - real_t f70, f71, f72, f73, f74, f75, f76, f77, f78, f79; - real_t f80, f81, f82, f83, f84, f85, f86, f87, f88, f89; - real_t f90, f91, f92, f93, f94, f95, f96, f97, f98, f99; - real_t f100, f101, f102, f103, f104, f105, f106, f107, f108, f109; - real_t f110, f111, f112, f113, f114, f115, f116, f117, f118, f119; - real_t f120, f121, f122, f123, f124, f125, f126, f127, f128, f129; - real_t f130, f131, f132, f133, f134, f135, f136, f137, f138, f139; - real_t f140, f141, f142, f143, f144, f145, f146, f147, f148, f149; - real_t f150, f151, f152, f153, f154, f155, f156, f157, f158, f159; - real_t f160, f161, f162, f163, f164, f165, f166, f167, f168, f169; - real_t f170, f171, f172, f173, f174, f175, f176, f177, f178, f179; - real_t f180, f181, f182, f183, f184, f185, f186, f187, f188, f189; - real_t f190, f191, f192, f193, f194, f195, f196, f197, f198, f199; - real_t f200, f201, f202, f203, f204, f205, f206, f207, f208, f209; - real_t f210, f211, f212, f213, f214, f215, f216, f217, f218, f219; - real_t f220, f221, f222, f223, f224, f225, f226, f227, f228, f229; - real_t f230, f231, f232, f233, f234, f235, f236, f237, f238, f239; - real_t f240, f241, f242, f243, f244, f245, f246, f247, f248, f249; - real_t f250, f251, f252, f253, f254, f255, f256, f257, f258, f259; - real_t f260, f261, f262, f263, f264, f265, f266, f267, f268, f269; - real_t f270, f271, f272, f273, f274, f275, f276, f277, f278, f279; - real_t f280, f281, f282, f283, f284, f285, f286, f287, f288, f289; - real_t f290, f291, f292, f293, f294, f295, f296, f297, f298, f299; - real_t f300, f301, f302, f303, f304, f305, f306, f307, f308, f309; - real_t f310, f311, f312, f313, f314, f315, f316, f317, f318, f319; - real_t f320, f321, f322, f323, f324, f325, f326, f327, f328, f329; - real_t f330, f331, f332, f333, f334, f335; - - f0 = x[0] - x[1]; - f1 = x[2] - x[1]; - f2 = x[2] - x[3]; - f3 = x[4] - x[3]; - f4 = x[4] - x[5]; - f5 = x[6] - x[5]; - f6 = x[6] - x[7]; - f7 = x[8] - x[7]; - f8 = x[8] - x[9]; - f9 = x[10] - x[9]; - f10 = x[10] - x[11]; - f11 = x[12] - x[11]; - f12 = x[12] - x[13]; - f13 = x[14] - x[13]; - f14 = x[14] - x[15]; - f15 = x[16] - x[15]; - f16 = x[16] - x[17]; - f17 = x[18] - x[17]; - f18 = x[18] - x[19]; - f19 = x[20] - x[19]; - f20 = x[20] - x[21]; - f21 = x[22] - x[21]; - f22 = x[22] - x[23]; - f23 = x[24] - x[23]; - f24 = x[24] - x[25]; - f25 = x[26] - x[25]; - f26 = x[26] - x[27]; - f27 = x[28] - x[27]; - f28 = x[28] - x[29]; - f29 = x[30] - x[29]; - f30 = x[30] - x[31]; - f31 = MUL_F(FRAC_CONST(0.7071067811865476), f15); - f32 = x[0] - f31; - f33 = x[0] + f31; - f34 = f7 + f23; - f35 = MUL_C(COEF_CONST(1.3065629648763766), f7); - f36 = MUL_F(FRAC_CONST(-0.9238795325112866), f34); - f37 = MUL_F(FRAC_CONST(-0.5411961001461967), f23); - f38 = f35 + f36; - f39 = f37 - f36; - f40 = f33 - f39; - f41 = f33 + f39; - f42 = f32 - f38; - f43 = f32 + f38; - f44 = f11 - f19; - f45 = f11 + f19; - f46 = MUL_F(FRAC_CONST(0.7071067811865476), f45); - f47 = f3 - f46; - f48 = f3 + f46; - f49 = MUL_F(FRAC_CONST(0.7071067811865476), f44); - f50 = f49 - f27; - f51 = f49 + f27; - f52 = f51 + f48; - f53 = MUL_F(FRAC_CONST(-0.7856949583871021), f51); - f54 = MUL_F(FRAC_CONST(0.9807852804032304), f52); - f55 = MUL_C(COEF_CONST(1.1758756024193588), f48); - f56 = f53 + f54; - f57 = f55 - f54; - f58 = f50 + f47; - f59 = MUL_F(FRAC_CONST(-0.2758993792829430), f50); - f60 = MUL_F(FRAC_CONST(0.8314696123025452), f58); - f61 = MUL_C(COEF_CONST(1.3870398453221475), f47); - f62 = f59 + f60; - f63 = f61 - f60; - f64 = f41 - f56; - f65 = f41 + f56; - f66 = f43 - f62; - f67 = f43 + f62; - f68 = f42 - f63; - f69 = f42 + f63; - f70 = f40 - f57; - f71 = f40 + f57; - f72 = f5 - f9; - f73 = f5 + f9; - f74 = f13 - f17; - f75 = f13 + f17; - f76 = f21 - f25; - f77 = f21 + f25; - f78 = MUL_F(FRAC_CONST(0.7071067811865476), f75); - f79 = f1 - f78; - f80 = f1 + f78; - f81 = f73 + f77; - f82 = MUL_C(COEF_CONST(1.3065629648763766), f73); - f83 = MUL_F(FRAC_CONST(-0.9238795325112866), f81); - f84 = MUL_F(FRAC_CONST(-0.5411961001461967), f77); - f85 = f82 + f83; - f86 = f84 - f83; - f87 = f80 - f86; - f88 = f80 + f86; - f89 = f79 - f85; - f90 = f79 + f85; - f91 = MUL_F(FRAC_CONST(0.7071067811865476), f74); - f92 = f29 - f91; - f93 = f29 + f91; - f94 = f76 + f72; - f95 = MUL_C(COEF_CONST(1.3065629648763766), f76); - f96 = MUL_F(FRAC_CONST(-0.9238795325112866), f94); - f97 = MUL_F(FRAC_CONST(-0.5411961001461967), f72); - f98 = f95 + f96; - f99 = f97 - f96; - f100 = f93 - f99; - f101 = f93 + f99; - f102 = f92 - f98; - f103 = f92 + f98; - f104 = f101 + f88; - f105 = MUL_F(FRAC_CONST(-0.8971675863426361), f101); - f106 = MUL_F(FRAC_CONST(0.9951847266721968), f104); - f107 = MUL_C(COEF_CONST(1.0932018670017576), f88); - f108 = f105 + f106; - f109 = f107 - f106; - f110 = f90 - f103; - f111 = MUL_F(FRAC_CONST(-0.6666556584777466), f103); - f112 = MUL_F(FRAC_CONST(0.9569403357322089), f110); - f113 = MUL_C(COEF_CONST(1.2472250129866713), f90); - f114 = f112 - f111; - f115 = f113 - f112; - f116 = f102 + f89; - f117 = MUL_F(FRAC_CONST(-0.4105245275223571), f102); - f118 = MUL_F(FRAC_CONST(0.8819212643483549), f116); - f119 = MUL_C(COEF_CONST(1.3533180011743529), f89); - f120 = f117 + f118; - f121 = f119 - f118; - f122 = f87 - f100; - f123 = MUL_F(FRAC_CONST(-0.1386171691990915), f100); - f124 = MUL_F(FRAC_CONST(0.7730104533627370), f122); - f125 = MUL_C(COEF_CONST(1.4074037375263826), f87); - f126 = f124 - f123; - f127 = f125 - f124; - f128 = f65 - f108; - f129 = f65 + f108; - f130 = f67 - f114; - f131 = f67 + f114; - f132 = f69 - f120; - f133 = f69 + f120; - f134 = f71 - f126; - f135 = f71 + f126; - f136 = f70 - f127; - f137 = f70 + f127; - f138 = f68 - f121; - f139 = f68 + f121; - f140 = f66 - f115; - f141 = f66 + f115; - f142 = f64 - f109; - f143 = f64 + f109; - f144 = f0 + f30; - f145 = MUL_C(COEF_CONST(1.0478631305325901), f0); - f146 = MUL_F(FRAC_CONST(-0.9987954562051724), f144); - f147 = MUL_F(FRAC_CONST(-0.9497277818777548), f30); - f148 = f145 + f146; - f149 = f147 - f146; - f150 = f4 + f26; - f151 = MUL_F(FRAC_CONST(1.2130114330978077), f4); - f152 = MUL_F(FRAC_CONST(-0.9700312531945440), f150); - f153 = MUL_F(FRAC_CONST(-0.7270510732912803), f26); - f154 = f151 + f152; - f155 = f153 - f152; - f156 = f8 + f22; - f157 = MUL_C(COEF_CONST(1.3315443865537255), f8); - f158 = MUL_F(FRAC_CONST(-0.9039892931234433), f156); - f159 = MUL_F(FRAC_CONST(-0.4764341996931612), f22); - f160 = f157 + f158; - f161 = f159 - f158; - f162 = f12 + f18; - f163 = MUL_C(COEF_CONST(1.3989068359730781), f12); - f164 = MUL_F(FRAC_CONST(-0.8032075314806453), f162); - f165 = MUL_F(FRAC_CONST(-0.2075082269882124), f18); - f166 = f163 + f164; - f167 = f165 - f164; - f168 = f16 + f14; - f169 = MUL_C(COEF_CONST(1.4125100802019777), f16); - f170 = MUL_F(FRAC_CONST(-0.6715589548470187), f168); - f171 = MUL_F(FRAC_CONST(0.0693921705079402), f14); - f172 = f169 + f170; - f173 = f171 - f170; - f174 = f20 + f10; - f175 = MUL_C(COEF_CONST(1.3718313541934939), f20); - f176 = MUL_F(FRAC_CONST(-0.5141027441932219), f174); - f177 = MUL_F(FRAC_CONST(0.3436258658070501), f10); - f178 = f175 + f176; - f179 = f177 - f176; - f180 = f24 + f6; - f181 = MUL_C(COEF_CONST(1.2784339185752409), f24); - f182 = MUL_F(FRAC_CONST(-0.3368898533922200), f180); - f183 = MUL_F(FRAC_CONST(0.6046542117908008), f6); - f184 = f181 + f182; - f185 = f183 - f182; - f186 = f28 + f2; - f187 = MUL_C(COEF_CONST(1.1359069844201433), f28); - f188 = MUL_F(FRAC_CONST(-0.1467304744553624), f186); - f189 = MUL_F(FRAC_CONST(0.8424460355094185), f2); - f190 = f187 + f188; - f191 = f189 - f188; - f192 = f149 - f173; - f193 = f149 + f173; - f194 = f148 - f172; - f195 = f148 + f172; - f196 = f155 - f179; - f197 = f155 + f179; - f198 = f154 - f178; - f199 = f154 + f178; - f200 = f161 - f185; - f201 = f161 + f185; - f202 = f160 - f184; - f203 = f160 + f184; - f204 = f167 - f191; - f205 = f167 + f191; - f206 = f166 - f190; - f207 = f166 + f190; - f208 = f192 + f194; - f209 = MUL_C(COEF_CONST(1.1758756024193588), f192); - f210 = MUL_F(FRAC_CONST(-0.9807852804032304), f208); - f211 = MUL_F(FRAC_CONST(-0.7856949583871021), f194); - f212 = f209 + f210; - f213 = f211 - f210; - f214 = f196 + f198; - f215 = MUL_C(COEF_CONST(1.3870398453221475), f196); - f216 = MUL_F(FRAC_CONST(-0.5555702330196022), f214); - f217 = MUL_F(FRAC_CONST(0.2758993792829431), f198); - f218 = f215 + f216; - f219 = f217 - f216; - f220 = f200 + f202; - f221 = MUL_F(FRAC_CONST(0.7856949583871022), f200); - f222 = MUL_F(FRAC_CONST(0.1950903220161283), f220); - f223 = MUL_C(COEF_CONST(1.1758756024193586), f202); - f224 = f221 + f222; - f225 = f223 - f222; - f226 = f204 + f206; - f227 = MUL_F(FRAC_CONST(-0.2758993792829430), f204); - f228 = MUL_F(FRAC_CONST(0.8314696123025452), f226); - f229 = MUL_C(COEF_CONST(1.3870398453221475), f206); - f230 = f227 + f228; - f231 = f229 - f228; - f232 = f193 - f201; - f233 = f193 + f201; - f234 = f195 - f203; - f235 = f195 + f203; - f236 = f197 - f205; - f237 = f197 + f205; - f238 = f199 - f207; - f239 = f199 + f207; - f240 = f213 - f225; - f241 = f213 + f225; - f242 = f212 - f224; - f243 = f212 + f224; - f244 = f219 - f231; - f245 = f219 + f231; - f246 = f218 - f230; - f247 = f218 + f230; - f248 = f232 + f234; - f249 = MUL_C(COEF_CONST(1.3065629648763766), f232); - f250 = MUL_F(FRAC_CONST(-0.9238795325112866), f248); - f251 = MUL_F(FRAC_CONST(-0.5411961001461967), f234); - f252 = f249 + f250; - f253 = f251 - f250; - f254 = f236 + f238; - f255 = MUL_F(FRAC_CONST(0.5411961001461969), f236); - f256 = MUL_F(FRAC_CONST(0.3826834323650898), f254); - f257 = MUL_C(COEF_CONST(1.3065629648763766), f238); - f258 = f255 + f256; - f259 = f257 - f256; - f260 = f240 + f242; - f261 = MUL_C(COEF_CONST(1.3065629648763766), f240); - f262 = MUL_F(FRAC_CONST(-0.9238795325112866), f260); - f263 = MUL_F(FRAC_CONST(-0.5411961001461967), f242); - f264 = f261 + f262; - f265 = f263 - f262; - f266 = f244 + f246; - f267 = MUL_F(FRAC_CONST(0.5411961001461969), f244); - f268 = MUL_F(FRAC_CONST(0.3826834323650898), f266); - f269 = MUL_C(COEF_CONST(1.3065629648763766), f246); - f270 = f267 + f268; - f271 = f269 - f268; - f272 = f233 - f237; - f273 = f233 + f237; - f274 = f235 - f239; - f275 = f235 + f239; - f276 = f253 - f259; - f277 = f253 + f259; - f278 = f252 - f258; - f279 = f252 + f258; - f280 = f241 - f245; - f281 = f241 + f245; - f282 = f243 - f247; - f283 = f243 + f247; - f284 = f265 - f271; - f285 = f265 + f271; - f286 = f264 - f270; - f287 = f264 + f270; - f288 = f272 - f274; - f289 = f272 + f274; - f290 = MUL_F(FRAC_CONST(0.7071067811865474), f288); - f291 = MUL_F(FRAC_CONST(0.7071067811865474), f289); - f292 = f276 - f278; - f293 = f276 + f278; - f294 = MUL_F(FRAC_CONST(0.7071067811865474), f292); - f295 = MUL_F(FRAC_CONST(0.7071067811865474), f293); - f296 = f280 - f282; - f297 = f280 + f282; - f298 = MUL_F(FRAC_CONST(0.7071067811865474), f296); - f299 = MUL_F(FRAC_CONST(0.7071067811865474), f297); - f300 = f284 - f286; - f301 = f284 + f286; - f302 = MUL_F(FRAC_CONST(0.7071067811865474), f300); - f303 = MUL_F(FRAC_CONST(0.7071067811865474), f301); - f304 = f129 - f273; - f305 = f129 + f273; - f306 = f131 - f281; - f307 = f131 + f281; - f308 = f133 - f285; - f309 = f133 + f285; - f310 = f135 - f277; - f311 = f135 + f277; - f312 = f137 - f295; - f313 = f137 + f295; - f314 = f139 - f303; - f315 = f139 + f303; - f316 = f141 - f299; - f317 = f141 + f299; - f318 = f143 - f291; - f319 = f143 + f291; - f320 = f142 - f290; - f321 = f142 + f290; - f322 = f140 - f298; - f323 = f140 + f298; - f324 = f138 - f302; - f325 = f138 + f302; - f326 = f136 - f294; - f327 = f136 + f294; - f328 = f134 - f279; - f329 = f134 + f279; - f330 = f132 - f287; - f331 = f132 + f287; - f332 = f130 - f283; - f333 = f130 + f283; - f334 = f128 - f275; - f335 = f128 + f275; - y[31] = MUL_F(FRAC_CONST(0.5001506360206510), f305); - y[30] = MUL_F(FRAC_CONST(0.5013584524464084), f307); - y[29] = MUL_F(FRAC_CONST(0.5037887256810443), f309); - y[28] = MUL_F(FRAC_CONST(0.5074711720725553), f311); - y[27] = MUL_F(FRAC_CONST(0.5124514794082247), f313); - y[26] = MUL_F(FRAC_CONST(0.5187927131053328), f315); - y[25] = MUL_F(FRAC_CONST(0.5265773151542700), f317); - y[24] = MUL_F(FRAC_CONST(0.5359098169079920), f319); - y[23] = MUL_F(FRAC_CONST(0.5469204379855088), f321); - y[22] = MUL_F(FRAC_CONST(0.5597698129470802), f323); - y[21] = MUL_F(FRAC_CONST(0.5746551840326600), f325); - y[20] = MUL_F(FRAC_CONST(0.5918185358574165), f327); - y[19] = MUL_F(FRAC_CONST(0.6115573478825099), f329); - y[18] = MUL_F(FRAC_CONST(0.6342389366884031), f331); - y[17] = MUL_F(FRAC_CONST(0.6603198078137061), f333); - y[16] = MUL_F(FRAC_CONST(0.6903721282002123), f335); - y[15] = MUL_F(FRAC_CONST(0.7251205223771985), f334); - y[14] = MUL_F(FRAC_CONST(0.7654941649730891), f332); - y[13] = MUL_F(FRAC_CONST(0.8127020908144905), f330); - y[12] = MUL_F(FRAC_CONST(0.8683447152233481), f328); - y[11] = MUL_F(FRAC_CONST(0.9345835970364075), f326); - y[10] = MUL_C(COEF_CONST(1.0144082649970547), f324); - y[9] = MUL_C(COEF_CONST(1.1120716205797176), f322); - y[8] = MUL_C(COEF_CONST(1.2338327379765710), f320); - y[7] = MUL_C(COEF_CONST(1.3892939586328277), f318); - y[6] = MUL_C(COEF_CONST(1.5939722833856311), f316); - y[5] = MUL_C(COEF_CONST(1.8746759800084078), f314); - y[4] = MUL_C(COEF_CONST(2.2820500680051619), f312); - y[3] = MUL_C(COEF_CONST(2.9246284281582162), f310); - y[2] = MUL_C(COEF_CONST(4.0846110781292477), f308); - y[1] = MUL_C(COEF_CONST(6.7967507116736332), f306); - y[0] = MUL_R(REAL_CONST(20.3738781672314530), f304); -} - #endif #endif diff --git a/src/libfaad/sbr_dct.h b/src/libfaad/sbr_dct.h index 6293486c7..ce44fd7ef 100644 --- a/src/libfaad/sbr_dct.h +++ b/src/libfaad/sbr_dct.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_dct.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_dct.h,v 1.19 2007/11/01 12:33:34 menno Exp $ **/ #ifndef __SBR_DCT_H__ diff --git a/src/libfaad/sbr_dec.c b/src/libfaad/sbr_dec.c index 24c1f5031..f87d0106c 100644 --- a/src/libfaad/sbr_dec.c +++ b/src/libfaad/sbr_dec.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_dec.c,v 1.9 2006/06/17 20:43:57 dgp85 Exp $ +** $Id: sbr_dec.c,v 1.43 2007/11/01 12:33:34 menno Exp $ **/ @@ -176,6 +179,72 @@ void sbrDecodeEnd(sbr_info *sbr) } } +void sbrReset(sbr_info *sbr) +{ + uint8_t j; + if (sbr->qmfa[0] != NULL) + memset(sbr->qmfa[0]->x, 0, 2 * sbr->qmfa[0]->channels * 10 * sizeof(real_t)); + if (sbr->qmfa[1] != NULL) + memset(sbr->qmfa[1]->x, 0, 2 * sbr->qmfa[1]->channels * 10 * sizeof(real_t)); + if (sbr->qmfs[0] != NULL) + memset(sbr->qmfs[0]->v, 0, 2 * sbr->qmfs[0]->channels * 20 * sizeof(real_t)); + if (sbr->qmfs[1] != NULL) + memset(sbr->qmfs[1]->v, 0, 2 * sbr->qmfs[1]->channels * 20 * sizeof(real_t)); + + for (j = 0; j < 5; j++) + { + if (sbr->G_temp_prev[0][j] != NULL) + memset(sbr->G_temp_prev[0][j], 0, 64*sizeof(real_t)); + if (sbr->G_temp_prev[1][j] != NULL) + memset(sbr->G_temp_prev[1][j], 0, 64*sizeof(real_t)); + if (sbr->Q_temp_prev[0][j] != NULL) + memset(sbr->Q_temp_prev[0][j], 0, 64*sizeof(real_t)); + if (sbr->Q_temp_prev[1][j] != NULL) + memset(sbr->Q_temp_prev[1][j], 0, 64*sizeof(real_t)); + } + + memset(sbr->Xsbr[0], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + memset(sbr->Xsbr[1], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); + + sbr->GQ_ringbuf_index[0] = 0; + sbr->GQ_ringbuf_index[1] = 0; + sbr->header_count = 0; + sbr->Reset = 1; + + sbr->L_E_prev[0] = 0; + sbr->L_E_prev[1] = 0; + sbr->bs_freq_scale = 2; + sbr->bs_alter_scale = 1; + sbr->bs_noise_bands = 2; + sbr->bs_limiter_bands = 2; + sbr->bs_limiter_gains = 2; + sbr->bs_interpol_freq = 1; + sbr->bs_smoothing_mode = 1; + sbr->bs_start_freq = 5; + sbr->bs_amp_res = 1; + sbr->bs_samplerate_mode = 1; + sbr->prevEnvIsShort[0] = -1; + sbr->prevEnvIsShort[1] = -1; + sbr->bsco = 0; + sbr->bsco_prev = 0; + sbr->M_prev = 0; + sbr->bs_start_freq_prev = -1; + + sbr->f_prev[0] = 0; + sbr->f_prev[1] = 0; + for (j = 0; j < MAX_M; j++) + { + sbr->E_prev[0][j] = 0; + sbr->Q_prev[0][j] = 0; + sbr->E_prev[1][j] = 0; + sbr->Q_prev[1][j] = 0; + sbr->bs_add_harmonic_prev[0][j] = 0; + sbr->bs_add_harmonic_prev[1][j] = 0; + } + sbr->bs_add_harmonic_flag_prev[0] = 0; + sbr->bs_add_harmonic_flag_prev[1] = 0; +} + static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch) { uint8_t i; @@ -226,11 +295,12 @@ static void sbr_save_matrix(sbr_info *sbr, uint8_t ch) } } -static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_NTSR][64], - uint8_t ch, uint8_t dont_process, - const uint8_t downSampledSBR) +static uint8_t sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_NTSR][64], + uint8_t ch, uint8_t dont_process, + const uint8_t downSampledSBR) { int16_t k, l; + uint8_t ret = 0; #ifdef SBR_LOW_POWER ALIGN real_t deg[64]; @@ -278,7 +348,7 @@ static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_ ,ch); #endif -#ifdef SBR_LOW_POWER +#if 0 //def SBR_LOW_POWER for (l = sbr->t_E[ch][0]; l < sbr->t_E[ch][sbr->L_E[ch]]; l++) { for (k = 0; k < sbr->kx; k++) @@ -290,12 +360,16 @@ static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_ #if 1 /* hf adjustment */ - hf_adjustment(sbr, sbr->Xsbr[ch] + ret = hf_adjustment(sbr, sbr->Xsbr[ch] #ifdef SBR_LOW_POWER ,deg #endif ,ch); #endif + if (ret > 0) + { + dont_process = 1; + } } if ((sbr->just_seeked != 0) || dont_process) @@ -367,6 +441,8 @@ static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_ #endif } } + + return ret; } uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan, @@ -400,7 +476,7 @@ uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_cha sbr->just_seeked = 0; } - sbr_process_channel(sbr, left_chan, X, 0, dont_process, downSampledSBR); + sbr->ret += sbr_process_channel(sbr, left_chan, X, 0, dont_process, downSampledSBR); /* subband synthesis */ if (downSampledSBR) { @@ -409,7 +485,7 @@ uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_cha sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X, left_chan); } - sbr_process_channel(sbr, right_chan, X, 1, dont_process, downSampledSBR); + sbr->ret += sbr_process_channel(sbr, right_chan, X, 1, dont_process, downSampledSBR); /* subband synthesis */ if (downSampledSBR) { @@ -483,7 +559,7 @@ uint8_t sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel, sbr->just_seeked = 0; } - sbr_process_channel(sbr, channel, X, 0, dont_process, downSampledSBR); + sbr->ret += sbr_process_channel(sbr, channel, X, 0, dont_process, downSampledSBR); /* subband synthesis */ if (downSampledSBR) { @@ -526,8 +602,8 @@ uint8_t sbrDecodeSingleFramePS(sbr_info *sbr, real_t *left_channel, real_t *righ uint8_t l, k; uint8_t dont_process = 0; uint8_t ret = 0; - ALIGN qmf_t X_left[38][64] = {{{0}}}; - ALIGN qmf_t X_right[38][64] = {{{0}}}; /* must set this to 0 */ + ALIGN qmf_t X_left[38][64] = {{0}}; + ALIGN qmf_t X_right[38][64] = {{0}}; /* must set this to 0 */ if (sbr == NULL) return 20; @@ -558,7 +634,7 @@ uint8_t sbrDecodeSingleFramePS(sbr_info *sbr, real_t *left_channel, real_t *righ sbr->qmfs[1] = qmfs_init((downSampledSBR)?32:64); } - sbr_process_channel(sbr, left_channel, X_left, 0, dont_process, downSampledSBR); + sbr->ret += sbr_process_channel(sbr, left_channel, X_left, 0, dont_process, downSampledSBR); /* copy some extra data for PS */ for (l = 32; l < 38; l++) @@ -574,7 +650,7 @@ uint8_t sbrDecodeSingleFramePS(sbr_info *sbr, real_t *left_channel, real_t *righ #ifdef DRM_PS if (sbr->Is_DRM_SBR) { - drm_ps_decode(sbr->drm_ps, (sbr->ret > 0), sbr->sample_rate, X_left, X_right); + drm_ps_decode(sbr->drm_ps, (sbr->ret > 0), X_left, X_right); } else { #endif #ifdef PS_DEC diff --git a/src/libfaad/sbr_dec.h b/src/libfaad/sbr_dec.h index 5efd5c5e0..40c1d5388 100644 --- a/src/libfaad/sbr_dec.h +++ b/src/libfaad/sbr_dec.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_dec.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_dec.h,v 1.39 2007/11/01 12:33:34 menno Exp $ **/ #ifndef __SBR_DEC_H__ @@ -183,6 +186,7 @@ typedef struct #endif #if (defined(PS_DEC) || defined(DRM_PS)) uint8_t ps_used; + uint8_t psResetFlag; #endif /* to get it compiling */ @@ -231,6 +235,7 @@ sbr_info *sbrDecodeInit(uint16_t framelength, uint8_t id_aac, #endif ); void sbrDecodeEnd(sbr_info *sbr); +void sbrReset(sbr_info *sbr); uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan, const uint8_t just_seeked, const uint8_t downSampledSBR); diff --git a/src/libfaad/sbr_e_nf.c b/src/libfaad/sbr_e_nf.c index 2d2bf4f85..14ba1e4a5 100644 --- a/src/libfaad/sbr_e_nf.c +++ b/src/libfaad/sbr_e_nf.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_e_nf.c,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_e_nf.c,v 1.21 2007/11/01 12:33:35 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/sbr_e_nf.h b/src/libfaad/sbr_e_nf.h index 48874c125..59017a906 100644 --- a/src/libfaad/sbr_e_nf.h +++ b/src/libfaad/sbr_e_nf.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_e_nf.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_e_nf.h,v 1.18 2007/11/01 12:33:35 menno Exp $ **/ #ifndef __SBR_E_NF_H__ diff --git a/src/libfaad/sbr_fbt.c b/src/libfaad/sbr_fbt.c index 511235863..5919c7b56 100644 --- a/src/libfaad/sbr_fbt.c +++ b/src/libfaad/sbr_fbt.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_fbt.c,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_fbt.c,v 1.21 2007/11/01 12:33:35 menno Exp $ **/ /* Calculate frequency band tables */ diff --git a/src/libfaad/sbr_fbt.h b/src/libfaad/sbr_fbt.h index 26c580efe..d24a25e27 100644 --- a/src/libfaad/sbr_fbt.h +++ b/src/libfaad/sbr_fbt.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_fbt.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_fbt.h,v 1.18 2007/11/01 12:33:35 menno Exp $ **/ #ifndef __SBR_FBT_H__ diff --git a/src/libfaad/sbr_hfadj.c b/src/libfaad/sbr_hfadj.c index 081f731e9..efac06502 100644 --- a/src/libfaad/sbr_hfadj.c +++ b/src/libfaad/sbr_hfadj.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_hfadj.c,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_hfadj.c,v 1.22 2007/11/01 12:33:35 menno Exp $ **/ /* High Frequency adjustment */ @@ -39,8 +42,8 @@ /* static function declarations */ -static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, - qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch); +static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, + qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch); static void calculate_gain(sbr_info *sbr, sbr_hfadj_info *adj, uint8_t ch); #ifdef SBR_LOW_POWER static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, uint8_t ch); @@ -49,13 +52,14 @@ static void aliasing_reduction(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, static void hf_assembly(sbr_info *sbr, sbr_hfadj_info *adj, qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch); -void hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] +uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] #ifdef SBR_LOW_POWER - ,real_t *deg /* aliasing degree */ + ,real_t *deg /* aliasing degree */ #endif - ,uint8_t ch) + ,uint8_t ch) { ALIGN sbr_hfadj_info adj = {{{0}}}; + uint8_t ret = 0; if (sbr->bs_frame_class[ch] == FIXFIX) { @@ -72,7 +76,9 @@ void hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] sbr->l_A[ch] = sbr->L_E[ch] + 1 - sbr->bs_pointer[ch]; } - estimate_current_envelope(sbr, &adj, Xsbr, ch); + ret = estimate_current_envelope(sbr, &adj, Xsbr, ch); + if (ret > 0) + return 1; calculate_gain(sbr, &adj, ch); @@ -82,6 +88,8 @@ void hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] #endif hf_assembly(sbr, &adj, Xsbr, ch); + + return 0; } static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t current_band) @@ -125,8 +133,8 @@ static uint8_t get_S_mapped(sbr_info *sbr, uint8_t ch, uint8_t l, uint8_t curren return 0; } -static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, - qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch) +static uint8_t estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, + qmf_t Xsbr[MAX_NTSRHFG][64], uint8_t ch) { uint8_t m, l, j, k, k_l, k_h, p; real_t nrg, div; @@ -142,6 +150,9 @@ static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, div = (real_t)(u_i - l_i); + if (div == 0) + div = 1; + for (m = 0; m < sbr->M; m++) { nrg = 0; @@ -192,6 +203,9 @@ static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, div = (real_t)((u_i - l_i)*(k_h - k_l)); + if (div == 0) + div = 1; + for (i = l_i + sbr->tHFAdj; i < u_i + sbr->tHFAdj; i++) { for (j = k_l; j < k_h; j++) @@ -225,6 +239,8 @@ static void estimate_current_envelope(sbr_info *sbr, sbr_hfadj_info *adj, } } } + + return 0; } #ifdef FIXED_POINT @@ -1342,15 +1358,27 @@ static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, ui { uint8_t l, k, i; uint8_t grouping; + uint8_t S_mapped; for (l = 0; l < sbr->L_E[ch]; l++) { + uint8_t current_res_band = 0; i = 0; grouping = 0; + S_mapped = get_S_mapped(sbr, ch, l, current_res_band); + for (k = sbr->kx; k < sbr->kx + sbr->M - 1; k++) { - if (deg[k + 1] && adj->S_mapped[l][k-sbr->kx] == 0) + if (k == sbr->f_table_res[sbr->f[ch][l]][current_res_band+1]) + { + /* step to next resolution band */ + current_res_band++; + + S_mapped = get_S_mapped(sbr, ch, l, current_res_band); + } + + if (deg[k + 1] && S_mapped == 0) { if (grouping == 0) { @@ -1361,7 +1389,7 @@ static void calc_gain_groups(sbr_info *sbr, sbr_hfadj_info *adj, real_t *deg, ui } else { if (grouping) { - if (adj->S_mapped[l][k-sbr->kx]) + if (S_mapped) { sbr->f_group[l][i] = k; } else { diff --git a/src/libfaad/sbr_hfadj.h b/src/libfaad/sbr_hfadj.h index aeaba32e8..03ef71a0c 100644 --- a/src/libfaad/sbr_hfadj.h +++ b/src/libfaad/sbr_hfadj.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_hfadj.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_hfadj.h,v 1.19 2007/11/01 12:33:35 menno Exp $ **/ #ifndef __SBR_HFADJ_H__ @@ -40,11 +43,11 @@ typedef struct } sbr_hfadj_info; -void hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] +uint8_t hf_adjustment(sbr_info *sbr, qmf_t Xsbr[MAX_NTSRHFG][64] #ifdef SBR_LOW_POWER - ,real_t *deg + ,real_t *deg #endif - ,uint8_t ch); + ,uint8_t ch); #ifdef __cplusplus diff --git a/src/libfaad/sbr_hfgen.c b/src/libfaad/sbr_hfgen.c index 688b9a0ea..b0f3219c3 100644 --- a/src/libfaad/sbr_hfgen.c +++ b/src/libfaad/sbr_hfgen.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_hfgen.c,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_hfgen.c,v 1.26 2007/11/01 12:33:35 menno Exp $ **/ /* High Frequency generation */ @@ -36,7 +39,6 @@ #include "sbr_hfgen.h" #include "sbr_fbt.h" - /* static function declarations */ #ifdef SBR_LOW_POWER static void calc_prediction_coef_lp(sbr_info *sbr, qmf_t Xlow[MAX_NTSRHFG][64], diff --git a/src/libfaad/sbr_hfgen.h b/src/libfaad/sbr_hfgen.h index 27a58be61..a7c842494 100644 --- a/src/libfaad/sbr_hfgen.h +++ b/src/libfaad/sbr_hfgen.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_hfgen.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_hfgen.h,v 1.20 2007/11/01 12:33:35 menno Exp $ **/ #ifndef __SBR_HFGEN_H__ diff --git a/src/libfaad/sbr_huff.c b/src/libfaad/sbr_huff.c index 39ae32b9b..6ba878640 100644 --- a/src/libfaad/sbr_huff.c +++ b/src/libfaad/sbr_huff.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_huff.c,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_huff.c,v 1.21 2007/11/01 12:33:35 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/sbr_huff.h b/src/libfaad/sbr_huff.h index 631a43a8d..f749f2e08 100644 --- a/src/libfaad/sbr_huff.h +++ b/src/libfaad/sbr_huff.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_huff.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_huff.h,v 1.21 2007/11/01 12:33:35 menno Exp $ **/ #ifndef __SBR_HUFF_H__ diff --git a/src/libfaad/sbr_noise.h b/src/libfaad/sbr_noise.h index a25fbf3cd..1cf7190de 100644 --- a/src/libfaad/sbr_noise.h +++ b/src/libfaad/sbr_noise.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_noise.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_noise.h,v 1.17 2007/11/01 12:33:35 menno Exp $ **/ #ifndef __SBR_NOISE_H__ diff --git a/src/libfaad/sbr_qmf.c b/src/libfaad/sbr_qmf.c index d534a0442..68f408916 100644 --- a/src/libfaad/sbr_qmf.c +++ b/src/libfaad/sbr_qmf.c @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_qmf.c,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_qmf.c,v 1.32 2007/11/01 12:33:36 menno Exp $ **/ #include "common.h" @@ -72,7 +75,7 @@ void sbr_qmf_analysis_32(sbr_info *sbr, qmfa_info *qmfa, const real_t *input, #else ALIGN real_t y[32]; #endif - uint16_t in = 0; + uint32_t in = 0; uint8_t l; /* qmf subsample l */ @@ -251,7 +254,7 @@ void sbr_qmf_synthesis_32(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][6 { ALIGN real_t x[16]; ALIGN real_t y[16]; - int16_t n, k, out = 0; + int32_t n, k, out = 0; uint8_t l; /* qmf subsample l */ @@ -320,7 +323,7 @@ void sbr_qmf_synthesis_64(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][6 { ALIGN real_t x[64]; ALIGN real_t y[64]; - int16_t n, k, out = 0; + int32_t n, k, out = 0; uint8_t l; @@ -392,7 +395,7 @@ void sbr_qmf_synthesis_32(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][6 #ifndef FIXED_POINT real_t scale = 1.f/64.f; #endif - int16_t n, k, out = 0; + int32_t n, k, out = 0; uint8_t l; @@ -475,7 +478,7 @@ void sbr_qmf_synthesis_64(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][6 #ifndef FIXED_POINT real_t scale = 1.f/64.f; #endif - int16_t n, k, out = 0; + int32_t n, k, out = 0; uint8_t l; diff --git a/src/libfaad/sbr_qmf.h b/src/libfaad/sbr_qmf.h index b1d673d9c..efb167be9 100644 --- a/src/libfaad/sbr_qmf.h +++ b/src/libfaad/sbr_qmf.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_qmf.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_qmf.h,v 1.25 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SBR_QMF_H__ diff --git a/src/libfaad/sbr_qmf_c.h b/src/libfaad/sbr_qmf_c.h index d9c079520..c2fcd2739 100644 --- a/src/libfaad/sbr_qmf_c.h +++ b/src/libfaad/sbr_qmf_c.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_qmf_c.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_qmf_c.h,v 1.17 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SBR_QMF_C_H__ diff --git a/src/libfaad/sbr_syntax.c b/src/libfaad/sbr_syntax.c index 19cb1b5c2..216c2e9e1 100644 --- a/src/libfaad/sbr_syntax.c +++ b/src/libfaad/sbr_syntax.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_syntax.c,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_syntax.c,v 1.38 2007/11/01 12:33:36 menno Exp $ **/ #include "common.h" @@ -46,6 +49,7 @@ #include "analysis.h" /* static function declarations */ +/* static function declarations */ static void sbr_header(bitfile *ld, sbr_info *sbr); static uint8_t calc_sbr_tables(sbr_info *sbr, uint8_t start_freq, uint8_t stop_freq, uint8_t samplerate_mode, uint8_t freq_scale, @@ -131,16 +135,23 @@ static uint8_t calc_sbr_tables(sbr_info *sbr, uint8_t start_freq, uint8_t stop_f } /* table 2 */ -uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt) +uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt, + uint8_t psResetFlag) { uint8_t result = 0; uint16_t num_align_bits = 0; - uint16_t num_sbr_bits = (uint16_t)faad_get_processed_bits(ld); + uint16_t num_sbr_bits1 = (uint16_t)faad_get_processed_bits(ld); + uint16_t num_sbr_bits2; uint8_t saved_start_freq, saved_samplerate_mode; uint8_t saved_stop_freq, saved_freq_scale; uint8_t saved_alter_scale, saved_xover_band; +#if (defined(PS_DEC) || defined(DRM_PS)) + if (psResetFlag) + sbr->psResetFlag = psResetFlag; +#endif + #ifdef DRM if (!sbr->Is_DRM_SBR) #endif @@ -206,28 +217,40 @@ uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt) { calc_sbr_tables(sbr, saved_start_freq, saved_stop_freq, saved_samplerate_mode, saved_freq_scale, - saved_alter_scale, saved_xover_band); + saved_alter_scale, saved_xover_band); } - /* we should be able to safely set result to 0 now */ - result = 0; + /* we should be able to safely set result to 0 now, */ + /* but practise indicates this doesn't work well */ } } else { result = 1; } -#ifdef DRM - if (!sbr->Is_DRM_SBR) -#endif + num_sbr_bits2 = (uint16_t)faad_get_processed_bits(ld) - num_sbr_bits1; + + /* check if we read more bits then were available for sbr */ + if (8*cnt < num_sbr_bits2) { - num_sbr_bits = (uint16_t)faad_get_processed_bits(ld) - num_sbr_bits; + faad_resetbits(ld, num_sbr_bits1 + 8*cnt); + num_sbr_bits2 = 8*cnt; - /* check if we read more bits then were available for sbr */ - if (8*cnt < num_sbr_bits) - return 1; +#ifdef PS_DEC + /* turn off PS for the unfortunate case that we randomly read some + * PS data that looks correct */ + sbr->ps_used = 0; +#endif + + /* Make sure it doesn't decode SBR in this frame, or we'll get glitches */ + return 1; + } +#ifdef DRM + if (!sbr->Is_DRM_SBR) +#endif + { /* -4 does not apply, bs_extension_type is re-read in this function */ - num_align_bits = 8*cnt /*- 4*/ - num_sbr_bits; + num_align_bits = 8*cnt /*- 4*/ - num_sbr_bits2; while (num_align_bits > 7) { @@ -364,11 +387,14 @@ static uint8_t sbr_single_channel_element(bitfile *ld, sbr_info *sbr) #ifdef DRM /* bs_coupling, from sbr_channel_pair_base_element(bs_amp_res) */ if (sbr->Is_DRM_SBR) + { faad_get1bit(ld); + } #endif if ((result = sbr_grid(ld, sbr, 0)) > 0) return result; + sbr_dtdf(ld, sbr, 0); invf_mode(ld, sbr, 0); sbr_envelope(ld, sbr, 0); @@ -431,7 +457,11 @@ static uint8_t sbr_single_channel_element(bitfile *ld, sbr_info *sbr) } else { /* to be safe make it 3, will switch to "default" * in sbr_extension() */ +#ifdef DRM + return 1; +#else sbr->bs_extension_id = 3; +#endif } } #endif @@ -829,6 +859,10 @@ static uint16_t sbr_extension(bitfile *ld, sbr_info *sbr, { sbr->ps = ps_init(get_sr_index(sbr->sample_rate)); } + if (sbr->psResetFlag) + { + sbr->ps->header_read = 0; + } ret = ps_data(sbr->ps, ld, &header); /* enable PS if and only if: a header has been decoded */ @@ -837,6 +871,11 @@ static uint16_t sbr_extension(bitfile *ld, sbr_info *sbr, sbr->ps_used = 1; } + if (header == 1) + { + sbr->psResetFlag = 0; + } + return ret; #endif #ifdef DRM_PS diff --git a/src/libfaad/sbr_syntax.h b/src/libfaad/sbr_syntax.h index 1baa5fec3..a13b2708f 100644 --- a/src/libfaad/sbr_syntax.h +++ b/src/libfaad/sbr_syntax.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_syntax.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_syntax.h,v 1.23 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SBR_SYNTAX_H__ @@ -55,7 +58,8 @@ extern "C" { #define NOISE_FLOOR_OFFSET 6 -uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt); +uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt, + uint8_t resetFlag); #ifdef __cplusplus } diff --git a/src/libfaad/sbr_tf_grid.c b/src/libfaad/sbr_tf_grid.c index ae741c256..b3b24fd16 100644 --- a/src/libfaad/sbr_tf_grid.c +++ b/src/libfaad/sbr_tf_grid.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_tf_grid.c,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_tf_grid.c,v 1.19 2007/11/01 12:33:36 menno Exp $ **/ /* Time/Frequency grid */ diff --git a/src/libfaad/sbr_tf_grid.h b/src/libfaad/sbr_tf_grid.h index 8772a384a..27a8f908e 100644 --- a/src/libfaad/sbr_tf_grid.h +++ b/src/libfaad/sbr_tf_grid.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sbr_tf_grid.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sbr_tf_grid.h,v 1.17 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SBR_TF_GRID_H__ diff --git a/src/libfaad/sine_win.h b/src/libfaad/sine_win.h index c7e6ecd6e..e4198da3a 100644 --- a/src/libfaad/sine_win.h +++ b/src/libfaad/sine_win.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: sine_win.h,v 1.6 2005/10/29 23:57:07 tmmm Exp $ +** $Id: sine_win.h,v 1.19 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SINE_WIN_H__ diff --git a/src/libfaad/specrec.c b/src/libfaad/specrec.c index fd4b0653c..ea6ca94b9 100644 --- a/src/libfaad/specrec.c +++ b/src/libfaad/specrec.c @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: specrec.c,v 1.10 2006/06/17 20:43:57 dgp85 Exp $ +** $Id: specrec.c,v 1.60 2007/11/01 12:33:36 menno Exp $ **/ /* @@ -327,6 +330,11 @@ uint8_t window_grouping_info(NeAACDecHandle hDecoder, ic_stream *ics) } #endif + if (ics->max_sfb > ics->num_swb) + { + return 32; + } + /* preparation of sect_sfb_offset for long blocks */ /* also copy the last value! */ #ifdef LD_DEC @@ -348,6 +356,7 @@ uint8_t window_grouping_info(NeAACDecHandle hDecoder, ic_stream *ics) } ics->sect_sfb_offset[0][ics->num_swb] = hDecoder->frameLength; ics->swb_offset[ics->num_swb] = hDecoder->frameLength; + ics->swb_offset_max = hDecoder->frameLength; } else { #endif for (i = 0; i < ics->num_swb; i++) @@ -357,6 +366,7 @@ uint8_t window_grouping_info(NeAACDecHandle hDecoder, ic_stream *ics) } ics->sect_sfb_offset[0][ics->num_swb] = hDecoder->frameLength; ics->swb_offset[ics->num_swb] = hDecoder->frameLength; + ics->swb_offset_max = hDecoder->frameLength; #ifdef LD_DEC } #endif @@ -367,9 +377,15 @@ uint8_t window_grouping_info(NeAACDecHandle hDecoder, ic_stream *ics) ics->window_group_length[ics->num_window_groups-1] = 1; ics->num_swb = num_swb_128_window[sf_index]; + if (ics->max_sfb > ics->num_swb) + { + return 32; + } + for (i = 0; i < ics->num_swb; i++) ics->swb_offset[i] = swb_offset_128_window[sf_index][i]; ics->swb_offset[ics->num_swb] = hDecoder->frameLength/8; + ics->swb_offset_max = hDecoder->frameLength/8; for (i = 0; i < ics->num_windows-1; i++) { if (bit_set(ics->scale_factor_grouping, 6-i) == 0) @@ -405,7 +421,7 @@ uint8_t window_grouping_info(NeAACDecHandle hDecoder, ic_stream *ics) } return 0; default: - return 1; + return 32; } } @@ -667,25 +683,46 @@ static uint8_t quant_to_spec(NeAACDecHandle hDecoder, static uint8_t allocate_single_channel(NeAACDecHandle hDecoder, uint8_t channel, uint8_t output_channels) { - uint8_t mul = 1; + int mul = 1; #ifdef MAIN_DEC /* MAIN object type prediction */ if (hDecoder->object_type == MAIN) { - hDecoder->pred_stat[channel] = (pred_state*)realloc(hDecoder->pred_stat[channel], hDecoder->frameLength * sizeof(pred_state)); - reset_all_predictors(hDecoder->pred_stat[channel], hDecoder->frameLength); + /* allocate the state only when needed */ + if (hDecoder->pred_stat[channel] != NULL) + { + faad_free(hDecoder->pred_stat[channel]); + hDecoder->pred_stat[channel] = NULL; + } + + hDecoder->pred_stat[channel] = (pred_state*)faad_malloc(hDecoder->frameLength * sizeof(pred_state)); + reset_all_predictors(hDecoder->pred_stat[channel], hDecoder->frameLength); } #endif #ifdef LTP_DEC if (is_ltp_ot(hDecoder->object_type)) { - hDecoder->lt_pred_stat[channel] = (int16_t*)realloc(hDecoder->lt_pred_stat[channel], hDecoder->frameLength*4 * sizeof(int16_t)); - memset(hDecoder->lt_pred_stat[channel], 0, hDecoder->frameLength*4 * sizeof(int16_t)); + /* allocate the state only when needed */ + if (hDecoder->lt_pred_stat[channel] != NULL) + { + faad_free(hDecoder->lt_pred_stat[channel]); + hDecoder->lt_pred_stat[channel] = NULL; + } + + hDecoder->lt_pred_stat[channel] = (int16_t*)faad_malloc(hDecoder->frameLength*4 * sizeof(int16_t)); + memset(hDecoder->lt_pred_stat[channel], 0, hDecoder->frameLength*4 * sizeof(int16_t)); } #endif + if (hDecoder->time_out[channel] != NULL) + { + faad_free(hDecoder->time_out[channel]); + hDecoder->time_out[channel] = NULL; + } + + { mul = 1; #ifdef SBR_DEC hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0; @@ -696,28 +733,48 @@ static uint8_t allocate_single_channel(NeAACDecHandle hDecoder, uint8_t channel, hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1; } #endif - hDecoder->time_out[channel] = (real_t*)realloc(hDecoder->time_out[channel], mul*hDecoder->frameLength*sizeof(real_t)); + hDecoder->time_out[channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t)); memset(hDecoder->time_out[channel], 0, mul*hDecoder->frameLength*sizeof(real_t)); + } + #if (defined(PS_DEC) || defined(DRM_PS)) if (output_channels == 2) { - hDecoder->time_out[channel+1] = (real_t*)realloc(hDecoder->time_out[channel+1], mul*hDecoder->frameLength*sizeof(real_t)); - memset(hDecoder->time_out[channel+1], 0, mul*hDecoder->frameLength*sizeof(real_t)); + if (hDecoder->time_out[channel+1] != NULL) + { + faad_free(hDecoder->time_out[channel+1]); + hDecoder->time_out[channel+1] = NULL; + } + + hDecoder->time_out[channel+1] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->time_out[channel+1], 0, mul*hDecoder->frameLength*sizeof(real_t)); } #endif - hDecoder->fb_intermed[channel] = (real_t*)realloc(hDecoder->fb_intermed[channel], hDecoder->frameLength*sizeof(real_t)); - memset(hDecoder->fb_intermed[channel], 0, hDecoder->frameLength*sizeof(real_t)); + if (hDecoder->fb_intermed[channel] != NULL) + { + faad_free(hDecoder->fb_intermed[channel]); + hDecoder->fb_intermed[channel] = NULL; + } + + hDecoder->fb_intermed[channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t)); + memset(hDecoder->fb_intermed[channel], 0, hDecoder->frameLength*sizeof(real_t)); #ifdef SSR_DEC if (hDecoder->object_type == SSR) { - uint16_t k; - hDecoder->ssr_overlap[channel] = (real_t*)realloc(hDecoder->ssr_overlap[channel], 2*hDecoder->frameLength*sizeof(real_t)); + if (hDecoder->ssr_overlap[channel] == NULL) + { + hDecoder->ssr_overlap[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); memset(hDecoder->ssr_overlap[channel], 0, 2*hDecoder->frameLength*sizeof(real_t)); - hDecoder->prev_fmd[channel] = (real_t*)realloc(hDecoder->prev_fmd[channel], 2*hDecoder->frameLength*sizeof(real_t)); + } + if (hDecoder->prev_fmd[channel] == NULL) + { + uint16_t k; + hDecoder->prev_fmd[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t)); for (k = 0; k < 2*hDecoder->frameLength; k++) hDecoder->prev_fmd[channel][k] = REAL_CONST(-1); + } } #endif @@ -727,7 +784,7 @@ static uint8_t allocate_single_channel(NeAACDecHandle hDecoder, uint8_t channel, static uint8_t allocate_channel_pair(NeAACDecHandle hDecoder, uint8_t channel, uint8_t paired_channel) { - uint8_t mul = 1; + int mul = 1; #ifdef MAIN_DEC /* MAIN object type prediction */ @@ -832,7 +889,8 @@ static uint8_t allocate_channel_pair(NeAACDecHandle hDecoder, uint8_t reconstruct_single_channel(NeAACDecHandle hDecoder, ic_stream *ics, element *sce, int16_t *spec_data) { - uint8_t retval, output_channels; + uint8_t retval; + int output_channels; ALIGN real_t spec_coef[1024]; #ifdef PROFILE @@ -841,15 +899,38 @@ uint8_t reconstruct_single_channel(NeAACDecHandle hDecoder, ic_stream *ics, /* always allocate 2 channels, PS can always "suddenly" turn up */ -#if (defined(PS_DEC) || defined(DRM_PS)) - output_channels = hDecoder->ps_used[hDecoder->fr_ch_ele] ? 2 : 1; +#if ( (defined(DRM) && defined(DRM_PS)) ) + output_channels = 2; +#elif defined(PS_DEC) + if (hDecoder->ps_used[hDecoder->fr_ch_ele]) + output_channels = 2; + else + output_channels = 1; #else output_channels = 1; #endif - if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] < output_channels) + if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 0) { + /* element_output_channels not set yet */ hDecoder->element_output_channels[hDecoder->fr_ch_ele] = output_channels; + } else if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] != output_channels) { + /* element inconsistency */ + + /* this only happens if PS is actually found but not in the first frame + * this means that there is only 1 bitstream element! + */ + + /* reset the allocation */ + hDecoder->element_alloced[hDecoder->fr_ch_ele] = 0; + + hDecoder->element_output_channels[hDecoder->fr_ch_ele] = output_channels; + + //return 21; + } + + if (hDecoder->element_alloced[hDecoder->fr_ch_ele] == 0) + { retval = allocate_single_channel(hDecoder, sce->channel, output_channels); if (retval > 0) return retval; @@ -870,7 +951,8 @@ uint8_t reconstruct_single_channel(NeAACDecHandle hDecoder, ic_stream *ics, /* pns decoding */ - pns_decode(ics, NULL, spec_coef, NULL, hDecoder->frameLength, 0, hDecoder->object_type); + pns_decode(ics, NULL, spec_coef, NULL, hDecoder->frameLength, 0, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); #ifdef MAIN_DEC /* MAIN object type prediction */ @@ -954,8 +1036,8 @@ uint8_t reconstruct_single_channel(NeAACDecHandle hDecoder, ic_stream *ics, if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) && hDecoder->sbr_alloced[hDecoder->fr_ch_ele]) { - uint8_t ele = hDecoder->fr_ch_ele; - uint8_t ch = sce->channel; + int ele = hDecoder->fr_ch_ele; + int ch = sce->channel; /* following case can happen when forceUpSampling == 1 */ if (hDecoder->sbr[ele] == NULL) @@ -970,9 +1052,9 @@ uint8_t reconstruct_single_channel(NeAACDecHandle hDecoder, ic_stream *ics, } if (sce->ics1.window_sequence == EIGHT_SHORT_SEQUENCE) - hDecoder->sbr[ele]->maxAACLine = 8*sce->ics1.swb_offset[max(sce->ics1.max_sfb-1, 0)]; + hDecoder->sbr[ele]->maxAACLine = 8*min(sce->ics1.swb_offset[max(sce->ics1.max_sfb-1, 0)], sce->ics1.swb_offset_max); else - hDecoder->sbr[ele]->maxAACLine = sce->ics1.swb_offset[max(sce->ics1.max_sfb-1, 0)]; + hDecoder->sbr[ele]->maxAACLine = min(sce->ics1.swb_offset[max(sce->ics1.max_sfb-1, 0)], sce->ics1.swb_offset_max); /* check if any of the PS tools is used */ #if (defined(PS_DEC) || defined(DRM_PS)) @@ -995,20 +1077,21 @@ uint8_t reconstruct_single_channel(NeAACDecHandle hDecoder, ic_stream *ics, { return 23; } +#endif /* copy L to R when no PS is used */ #if (defined(PS_DEC) || defined(DRM_PS)) - if ((hDecoder->ps_used[hDecoder->fr_ch_ele] == 0) && (output_channels == 2)) + if ((hDecoder->ps_used[hDecoder->fr_ch_ele] == 0) && + (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 2)) { - uint8_t ele = hDecoder->fr_ch_ele; - uint8_t ch = sce->channel; - uint16_t frame_size = (hDecoder->sbr_alloced[ele]) ? 2 : 1; + int ele = hDecoder->fr_ch_ele; + int ch = sce->channel; + int frame_size = (hDecoder->sbr_alloced[ele]) ? 2 : 1; frame_size *= hDecoder->frameLength*sizeof(real_t); memcpy(hDecoder->time_out[ch+1], hDecoder->time_out[ch], frame_size); } #endif -#endif return 0; } @@ -1049,10 +1132,13 @@ uint8_t reconstruct_channel_pair(NeAACDecHandle hDecoder, ic_stream *ics1, ic_st /* pns decoding */ if (ics1->ms_mask_present) { - pns_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength, 1, hDecoder->object_type); + pns_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength, 1, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); } else { - pns_decode(ics1, NULL, spec_coef1, NULL, hDecoder->frameLength, 0, hDecoder->object_type); - pns_decode(ics2, NULL, spec_coef2, NULL, hDecoder->frameLength, 0, hDecoder->object_type); + pns_decode(ics1, NULL, spec_coef1, NULL, hDecoder->frameLength, 0, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); + pns_decode(ics2, NULL, spec_coef2, NULL, hDecoder->frameLength, 0, hDecoder->object_type, + &(hDecoder->__r1), &(hDecoder->__r2)); } /* mid/side decoding */ @@ -1204,9 +1290,9 @@ uint8_t reconstruct_channel_pair(NeAACDecHandle hDecoder, ic_stream *ics1, ic_st if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1)) && hDecoder->sbr_alloced[hDecoder->fr_ch_ele]) { - uint8_t ele = hDecoder->fr_ch_ele; - uint8_t ch0 = cpe->channel; - uint8_t ch1 = cpe->paired_channel; + int ele = hDecoder->fr_ch_ele; + int ch0 = cpe->channel; + int ch1 = cpe->paired_channel; /* following case can happen when forceUpSampling == 1 */ if (hDecoder->sbr[ele] == NULL) @@ -1221,9 +1307,9 @@ uint8_t reconstruct_channel_pair(NeAACDecHandle hDecoder, ic_stream *ics1, ic_st } if (cpe->ics1.window_sequence == EIGHT_SHORT_SEQUENCE) - hDecoder->sbr[ele]->maxAACLine = 8*cpe->ics1.swb_offset[max(cpe->ics1.max_sfb-1, 0)]; + hDecoder->sbr[ele]->maxAACLine = 8*min(cpe->ics1.swb_offset[max(cpe->ics1.max_sfb-1, 0)], cpe->ics1.swb_offset_max); else - hDecoder->sbr[ele]->maxAACLine = cpe->ics1.swb_offset[max(cpe->ics1.max_sfb-1, 0)]; + hDecoder->sbr[ele]->maxAACLine = min(cpe->ics1.swb_offset[max(cpe->ics1.max_sfb-1, 0)], cpe->ics1.swb_offset_max); retval = sbrDecodeCoupleFrame(hDecoder->sbr[ele], hDecoder->time_out[ch0], hDecoder->time_out[ch1], diff --git a/src/libfaad/specrec.h b/src/libfaad/specrec.h index da174abe8..f58094cf4 100644 --- a/src/libfaad/specrec.h +++ b/src/libfaad/specrec.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: specrec.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: specrec.h,v 1.32 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SPECREC_H__ diff --git a/src/libfaad/ssr.c b/src/libfaad/ssr.c index 46517d0c8..368112407 100644 --- a/src/libfaad/ssr.c +++ b/src/libfaad/ssr.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ssr.c,v 1.6 2005/10/29 23:57:07 tmmm Exp $ +** $Id: ssr.c,v 1.19 2007/11/01 12:33:36 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/ssr.h b/src/libfaad/ssr.h index d1defdc45..7adcf2a11 100644 --- a/src/libfaad/ssr.h +++ b/src/libfaad/ssr.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ssr.h,v 1.6 2005/10/29 23:57:07 tmmm Exp $ +** $Id: ssr.h,v 1.19 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SSR_H__ diff --git a/src/libfaad/ssr_fb.c b/src/libfaad/ssr_fb.c index fb62c90c6..a977c9411 100644 --- a/src/libfaad/ssr_fb.c +++ b/src/libfaad/ssr_fb.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ssr_fb.c,v 1.6 2005/10/29 23:57:07 tmmm Exp $ +** $Id: ssr_fb.c,v 1.17 2007/11/01 12:33:36 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/ssr_fb.h b/src/libfaad/ssr_fb.h index 739a4dfbb..3ae4eb04b 100644 --- a/src/libfaad/ssr_fb.h +++ b/src/libfaad/ssr_fb.h @@ -1,6 +1,6 @@ /* -** FAAD - Freeware Advanced Audio Decoder -** Copyright (C) 2002 M. Bakker +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -16,7 +16,16 @@ ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** -** $Id: ssr_fb.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_fb.h,v 1.16 2007/11/01 12:33:36 menno Exp $ **/ #ifndef __SSR_FB_H__ diff --git a/src/libfaad/ssr_ipqf.c b/src/libfaad/ssr_ipqf.c index 3064285de..6963427c9 100644 --- a/src/libfaad/ssr_ipqf.c +++ b/src/libfaad/ssr_ipqf.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: ssr_ipqf.c,v 1.6 2005/10/29 23:57:07 tmmm Exp $ +** $Id: ssr_ipqf.c,v 1.18 2007/11/01 12:33:39 menno Exp $ **/ #include "common.h" diff --git a/src/libfaad/ssr_ipqf.h b/src/libfaad/ssr_ipqf.h index 360db978b..47299219c 100644 --- a/src/libfaad/ssr_ipqf.h +++ b/src/libfaad/ssr_ipqf.h @@ -1,6 +1,6 @@ /* -** FAAD - Freeware Advanced Audio Decoder -** Copyright (C) 2002 M. Bakker +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -16,7 +16,16 @@ ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** -** $Id: ssr_ipqf.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_ipqf.h,v 1.17 2007/11/01 12:33:39 menno Exp $ **/ #ifndef __SSR_IPQF_H__ diff --git a/src/libfaad/ssr_win.h b/src/libfaad/ssr_win.h index ddbb3086e..64b0f98bf 100644 --- a/src/libfaad/ssr_win.h +++ b/src/libfaad/ssr_win.h @@ -1,6 +1,6 @@ /* -** FAAD - Freeware Advanced Audio Decoder -** Copyright (C) 2002 M. Bakker +** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding +** Copyright (C) 2003-2005 M. Bakker, Ahead Software AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -16,7 +16,16 @@ ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** -** $Id: ssr_win.h,v 1.5 2005/10/29 23:57:07 tmmm Exp $ +** Any non-GPL usage of this software or parts of this software is strictly +** forbidden. +** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** +** Commercial non-GPL licensing of this software is possible. +** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** +** $Id: ssr_win.h,v 1.16 2007/11/01 12:33:39 menno Exp $ **/ #ifndef __SSR_WIN_H__ diff --git a/src/libfaad/structs.h b/src/libfaad/structs.h index db6361a5c..5d957c59e 100644 --- a/src/libfaad/structs.h +++ b/src/libfaad/structs.h @@ -1,28 +1,31 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com -** +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com +** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. -** +** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. -** +** ** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software +** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ** ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: structs.h,v 1.7 2005/10/29 23:57:07 tmmm Exp $ +** $Id: structs.h,v 1.46 2007/11/01 12:33:40 menno Exp $ **/ #ifndef __STRUCTS_H__ @@ -247,6 +250,7 @@ typedef struct uint8_t scale_factor_grouping; uint16_t sect_sfb_offset[8][15*8]; uint16_t swb_offset[52]; + uint16_t swb_offset_max; uint8_t sect_cb[8][15*8]; uint16_t sect_start[8][15*8]; @@ -261,6 +265,7 @@ typedef struct uint8_t ms_used[MAX_WINDOW_GROUPS][MAX_SFB]; uint8_t noise_used; + uint8_t is_used; uint8_t pulse_data_present; uint8_t tns_data_present; @@ -447,6 +452,14 @@ typedef struct int16_t *lt_pred_stat[MAX_CHANNELS]; #endif +#ifdef DRM + uint8_t error_state; +#endif + + /* RNG states */ + uint32_t __r1; + uint32_t __r2; + /* Program Config Element */ uint8_t pce_set; program_config pce; @@ -463,6 +476,7 @@ typedef struct int64_t scalefac_cycles; int64_t requant_cycles; #endif + const unsigned char *cmes; } NeAACDecStruct, *NeAACDecHandle; diff --git a/src/libfaad/syntax.c b/src/libfaad/syntax.c index 6dc9fc57d..373582b7f 100644 --- a/src/libfaad/syntax.c +++ b/src/libfaad/syntax.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: syntax.c,v 1.10 2006/09/26 17:48:24 dgp85 Exp $ +** $Id: syntax.c,v 1.89 2007/11/01 12:33:40 menno Exp $ **/ /* @@ -93,9 +96,11 @@ static void adts_variable_header(adts_header *adts, bitfile *ld); static void adts_error_check(adts_header *adts, bitfile *ld); static uint8_t dynamic_range_info(bitfile *ld, drc_info *drc); static uint8_t excluded_channels(bitfile *ld, drc_info *drc); -#ifdef SCALABLE_DEC -static int8_t aac_scalable_main_header(NeAACDecHandle hDecoder, ic_stream *ics1, ic_stream *ics2, - bitfile *ld, uint8_t this_layer_stereo); +static uint8_t side_info(NeAACDecHandle hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag); +#ifdef DRM +static int8_t DRM_aac_scalable_main_header(NeAACDecHandle hDecoder, ic_stream *ics1, ic_stream *ics2, + bitfile *ld, uint8_t this_layer_stereo); #endif @@ -323,7 +328,7 @@ static void decode_sce_lfe(NeAACDecHandle hDecoder, uint8_t channels = hDecoder->fr_channels; uint8_t tag = 0; - if (channels+1 >= MAX_CHANNELS) + if (channels+1 > MAX_CHANNELS) { hInfo->error = 12; return; @@ -413,6 +418,7 @@ void raw_data_block(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, bitfile *ld, program_config *pce, drc_info *drc) { uint8_t id_syn_ele; + uint8_t ele_this_frame = 0; hDecoder->fr_channels = 0; hDecoder->fr_ch_ele = 0; @@ -429,36 +435,55 @@ void raw_data_block(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, { switch (id_syn_ele) { case ID_SCE: + ele_this_frame++; if (hDecoder->first_syn_ele == 25) hDecoder->first_syn_ele = id_syn_ele; decode_sce_lfe(hDecoder, hInfo, ld, id_syn_ele); if (hInfo->error > 0) return; break; case ID_CPE: + ele_this_frame++; if (hDecoder->first_syn_ele == 25) hDecoder->first_syn_ele = id_syn_ele; decode_cpe(hDecoder, hInfo, ld, id_syn_ele); if (hInfo->error > 0) return; break; case ID_LFE: +#ifdef DRM + hInfo->error = 32; +#else + ele_this_frame++; hDecoder->has_lfe++; decode_sce_lfe(hDecoder, hInfo, ld, id_syn_ele); +#endif if (hInfo->error > 0) return; break; case ID_CCE: /* not implemented yet, but skip the bits */ +#ifdef DRM + hInfo->error = 32; +#else + ele_this_frame++; #ifdef COUPLING_DEC hInfo->error = coupling_channel_element(hDecoder, ld); #else hInfo->error = 6; #endif +#endif if (hInfo->error > 0) return; break; case ID_DSE: + ele_this_frame++; data_stream_element(hDecoder, ld); break; case ID_PCE: + if (ele_this_frame != 0) + { + hInfo->error = 31; + return; + } + ele_this_frame++; /* 14496-4: 5.6.4.1.2.1.3: */ /* program_configuration_element()'s in access units shall be ignored */ program_config_element(pce, ld); @@ -467,6 +492,7 @@ void raw_data_block(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, //hDecoder->pce_set = 1; break; case ID_FIL: + ele_this_frame++; /* one sbr_info describes a channel_element not a channel! */ /* if we encounter SBR data here: error */ /* SBR data will be read directly in the SCE/LFE/CPE element */ @@ -577,6 +603,10 @@ static uint8_t single_lfe_channel_element(NeAACDecHandle hDecoder, bitfile *ld, if (retval > 0) return retval; + /* IS not allowed in single channel */ + if (ics->is_used) + return 32; + #ifdef SBR_DEC /* check if next bitstream element is a fill element */ /* if so, read it now so SBR decoding can be done in case of a file with SBR */ @@ -627,6 +657,11 @@ static uint8_t channel_pair_element(NeAACDecHandle hDecoder, bitfile *ld, ics1->ms_mask_present = (uint8_t)faad_getbits(ld, 2 DEBUGVAR(1,41,"channel_pair_element(): ms_mask_present")); + if (ics1->ms_mask_present == 3) + { + /* bitstream error */ + return 32; + } if (ics1->ms_mask_present == 1) { uint8_t g, sfb; @@ -730,14 +765,23 @@ static uint8_t ics_info(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld, uint8_t common_window) { uint8_t retval = 0; + uint8_t ics_reserved_bit; - /* ics->ics_reserved_bit = */ faad_get1bit(ld + ics_reserved_bit = faad_get1bit(ld DEBUGVAR(1,43,"ics_info(): ics_reserved_bit")); + if (ics_reserved_bit != 0) + return 32; ics->window_sequence = (uint8_t)faad_getbits(ld, 2 DEBUGVAR(1,44,"ics_info(): window_sequence")); ics->window_shape = faad_get1bit(ld DEBUGVAR(1,45,"ics_info(): window_shape")); +#ifdef LD_DEC + /* No block switching in LD */ + if ((hDecoder->object_type == LD) && (ics->window_sequence != ONLY_LONG_SEQUENCE)) + return 32; +#endif + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) { ics->max_sfb = (uint8_t)faad_getbits(ld, 4 @@ -753,6 +797,7 @@ static uint8_t ics_info(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld, if ((retval = window_grouping_info(hDecoder, ics)) > 0) return retval; + /* should be an error */ /* check the range of max_sfb */ if (ics->max_sfb > ics->num_swb) @@ -922,6 +967,10 @@ static uint8_t coupling_channel_element(NeAACDecHandle hDecoder, bitfile *ld) return result; } + /* IS not allowed in single channel */ + if (ics->is_used) + return 32; + for (c = 1; c < num_gain_element_lists; c++) { uint8_t cge; @@ -1029,7 +1078,8 @@ static uint8_t fill_element(NeAACDecHandle hDecoder, bitfile *ld, drc_info *drc hDecoder->sbr_present_flag = 1; /* parse the SBR data */ - hDecoder->sbr[sbr_ele]->ret = sbr_extension_data(ld, hDecoder->sbr[sbr_ele], count); + hDecoder->sbr[sbr_ele]->ret = sbr_extension_data(ld, hDecoder->sbr[sbr_ele], count, + hDecoder->postSeekResetFlag); #if 0 if (hDecoder->sbr[sbr_ele]->ret > 0) @@ -1049,10 +1099,14 @@ static uint8_t fill_element(NeAACDecHandle hDecoder, bitfile *ld, drc_info *drc #endif } else { #endif +#ifndef DRM while (count > 0) { count -= extension_payload(ld, drc, count); } +#else + return 30; +#endif #ifdef SBR_DEC } #endif @@ -1157,10 +1211,10 @@ static void gain_control_data(bitfile *ld, ic_stream *ics) } #endif -#ifdef SCALABLE_DEC +#ifdef DRM /* Table 4.4.13 ASME */ -void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, - bitfile *ld, program_config *pce, drc_info *drc) +void DRM_aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, + bitfile *ld, program_config *pce, drc_info *drc) { uint8_t retval = 0; uint8_t channels = hDecoder->fr_channels = 0; @@ -1175,7 +1229,7 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo hDecoder->fr_ch_ele = 0; - hInfo->error = aac_scalable_main_header(hDecoder, ics1, ics2, ld, this_layer_stereo); + hInfo->error = DRM_aac_scalable_main_header(hDecoder, ics1, ics2, ld, this_layer_stereo); if (hInfo->error > 0) return; @@ -1189,22 +1243,77 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo hDecoder->element_id[0] = ID_SCE; } - for (ch = 0; ch < (this_layer_stereo ? 2 : 1); ch++) + if (this_layer_stereo) { - ic_stream *ics; - if (ch == 0) - { - ics = ics1; - spec_data = spec_data1; - } else { - ics = ics2; - spec_data = spec_data2; - } + cpe.channel = 0; + cpe.paired_channel = 1; + } + + + /* Stereo2 / Mono1 */ + ics1->tns_data_present = faad_get1bit(ld); - hInfo->error = individual_channel_stream(hDecoder, &cpe, ld, ics, 1, spec_data); +#if defined(LTP_DEC) + ics1->ltp.data_present = faad_get1bit(ld); +#elif defined (DRM) + if(faad_get1bit(ld)) { + hInfo->error = 26; + return; + } +#else + faad_get1bit(ld); +#endif + + hInfo->error = side_info(hDecoder, &cpe, ld, ics1, 1); + if (hInfo->error > 0) + return; + if (this_layer_stereo) + { + /* Stereo3 */ + ics2->tns_data_present = faad_get1bit(ld); +#ifdef LTP_DEC + ics1->ltp.data_present = +#endif + faad_get1bit(ld); + hInfo->error = side_info(hDecoder, &cpe, ld, ics2, 1); if (hInfo->error > 0) return; } + /* Stereo4 / Mono2 */ + if (ics1->tns_data_present) + tns_data(ics1, &(ics1->tns), ld); + if (this_layer_stereo) + { + /* Stereo5 */ + if (ics2->tns_data_present) + tns_data(ics2, &(ics2->tns), ld); + } + +#ifdef DRM + /* CRC check */ + if (hDecoder->object_type == DRM_ER_LC) + { + if ((hInfo->error = (uint8_t)faad_check_CRC(ld, (uint16_t)faad_get_processed_bits(ld) - 8)) > 0) + return; + } +#endif + + /* Stereo6 / Mono3 */ + /* error resilient spectral data decoding */ + if ((hInfo->error = reordered_spectral_data(hDecoder, ics1, ld, spec_data1)) > 0) + { + return; + } + if (this_layer_stereo) + { + /* Stereo7 */ + /* error resilient spectral data decoding */ + if ((hInfo->error = reordered_spectral_data(hDecoder, ics2, ld, spec_data2)) > 0) + { + return; + } + } + #ifdef DRM #ifdef SBR_DEC @@ -1244,6 +1353,7 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo /* Set SBR data */ /* consider 8 bits from AAC-CRC */ + /* SBR buffer size is original buffer size minus AAC buffer size */ count = (uint16_t)bit2byte(buffer_size*8 - bitsconsumed); faad_initbits(&ld_sbr, revbuffer, count); @@ -1252,7 +1362,7 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo faad_getbits(&ld_sbr, 8); /* Skip 8-bit CRC */ - hDecoder->sbr[0]->ret = sbr_extension_data(&ld_sbr, hDecoder->sbr[0], count); + hDecoder->sbr[0]->ret = sbr_extension_data(&ld_sbr, hDecoder->sbr[0], count, hDecoder->postSeekResetFlag); #if (defined(PS_DEC) || defined(DRM_PS)) if (hDecoder->sbr[0]->ps_used) { @@ -1261,6 +1371,11 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo } #endif + if (ld_sbr.error) + { + hDecoder->sbr[0]->ret = 1; + } + /* check CRC */ /* no need to check it if there was already an error */ if (hDecoder->sbr[0]->ret == 0) @@ -1269,7 +1384,7 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo /* SBR data was corrupted, disable it until the next header */ if (hDecoder->sbr[0]->ret != 0) { - hDecoder->sbr[0]->header_count = 0; + hDecoder->sbr[0]->header_count = 0; } faad_endbits(&ld_sbr); @@ -1308,15 +1423,18 @@ void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo } /* Table 4.4.15 */ -static int8_t aac_scalable_main_header(NeAACDecHandle hDecoder, ic_stream *ics1, ic_stream *ics2, - bitfile *ld, uint8_t this_layer_stereo) +static int8_t DRM_aac_scalable_main_header(NeAACDecHandle hDecoder, ic_stream *ics1, ic_stream *ics2, + bitfile *ld, uint8_t this_layer_stereo) { uint8_t retval = 0; uint8_t ch; ic_stream *ics; + uint8_t ics_reserved_bit; - /* ics1->ics_reserved_bit = */ faad_get1bit(ld + ics_reserved_bit = faad_get1bit(ld DEBUGVAR(1,300,"aac_scalable_main_header(): ics_reserved_bits")); + if (ics_reserved_bit != 0) + return 32; ics1->window_sequence = (uint8_t)faad_getbits(ld, 2 DEBUGVAR(1,301,"aac_scalable_main_header(): window_sequence")); ics1->window_shape = faad_get1bit(ld @@ -1346,6 +1464,11 @@ static int8_t aac_scalable_main_header(NeAACDecHandle hDecoder, ic_stream *ics1, { ics1->ms_mask_present = (uint8_t)faad_getbits(ld, 2 DEBUGVAR(1,306,"aac_scalable_main_header(): ms_mask_present")); + if (ics1->ms_mask_present == 3) + { + /* bitstream error */ + return 32; + } if (ics1->ms_mask_present == 1) { uint8_t g, sfb; @@ -1364,70 +1487,12 @@ static int8_t aac_scalable_main_header(NeAACDecHandle hDecoder, ic_stream *ics1, ics1->ms_mask_present = 0; } - if (0) - { - faad_get1bit(ld - DEBUGVAR(1,308,"aac_scalable_main_header(): tns_channel_mono_layer")); - } - - for (ch = 0; ch < (this_layer_stereo ? 2 : 1); ch++) - { - if (ch == 0) - ics = ics1; - else - ics = ics2; - - if ( 1 /*!tvq_layer_pesent || (tns_aac_tvq_en[ch] == 1)*/) - { - if ((ics->tns_data_present = faad_get1bit(ld - DEBUGVAR(1,309,"aac_scalable_main_header(): tns_data_present"))) & 1) - { -#ifdef DRM - /* different order of data units in DRM */ - if (hDecoder->object_type != DRM_ER_LC) -#endif - { - tns_data(ics, &(ics->tns), ld); - } - } - } -#if 0 - if (0 /*core_flag || tvq_layer_pesent*/) - { - if ((ch==0) || ((ch==1) && (core_stereo || tvq_stereo)) - diff_control_data(); - if (mono_stereo_flag) - diff_control_data_lr(); - } else { -#endif - if (( -#ifdef LTP_DEC - ics->ltp.data_present = -#endif - faad_get1bit(ld DEBUGVAR(1,310,"aac_scalable_main_header(): ltp.data_present"))) & 1) - { -#ifdef LTP_DEC - if ((retval = ltp_data(hDecoder, ics, &(ics->ltp), ld)) > 0) - { - return retval; - } -#else - return 26; -#endif - } -#if 0 - } -#endif - } - return 0; } #endif -/* Table 4.4.24 */ -static uint8_t individual_channel_stream(NeAACDecHandle hDecoder, element *ele, - bitfile *ld, ic_stream *ics, uint8_t scal_flag, - int16_t *spec_data) +static uint8_t side_info(NeAACDecHandle hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag) { uint8_t result; @@ -1513,6 +1578,21 @@ static uint8_t individual_channel_stream(NeAACDecHandle hDecoder, element *ele, if ((result = rvlc_decode_scale_factors(ics, ld)) > 0) return result; } +#endif + + return 0; +} + +/* Table 4.4.24 */ +static uint8_t individual_channel_stream(NeAACDecHandle hDecoder, element *ele, + bitfile *ld, ic_stream *ics, uint8_t scal_flag, + int16_t *spec_data) +{ + uint8_t result; + + result = side_info(hDecoder, ele, ld, ics, scal_flag); + if (result > 0) + return result; if (hDecoder->object_type >= ER_OBJECT_START) { @@ -1523,10 +1603,13 @@ static uint8_t individual_channel_stream(NeAACDecHandle hDecoder, element *ele, #ifdef DRM /* CRC check */ if (hDecoder->object_type == DRM_ER_LC) + { if ((result = (uint8_t)faad_check_CRC(ld, (uint16_t)faad_get_processed_bits(ld) - 8)) > 0) return result; + } #endif +#ifdef ERROR_RESILIENCE if (hDecoder->aacSpectralDataResilienceFlag) { /* error resilient spectral data decoding */ @@ -1594,7 +1677,7 @@ static uint8_t section_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld /* if "faad_getbits" detects error and returns "0", "k" is never incremented and we cannot leave the while loop */ - if ((ld->error != 0) || (ld->no_more_reading)) + if (ld->error != 0) return 14; #ifdef ERROR_RESILIENCE @@ -1605,12 +1688,23 @@ static uint8_t section_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld ics->sect_cb[g][i] = (uint8_t)faad_getbits(ld, sect_cb_bits DEBUGVAR(1,71,"section_data(): sect_cb")); + if (ics->sect_cb[g][i] == 12) + return 32; + #if 0 printf("%d\n", ics->sect_cb[g][i]); #endif +#ifndef DRM if (ics->sect_cb[g][i] == NOISE_HCB) ics->noise_used = 1; +#else + /* PNS not allowed in DRM */ + if (ics->sect_cb[g][i] == NOISE_HCB) + return 29; +#endif + if (ics->sect_cb[g][i] == INTENSITY_HCB2 || ics->sect_cb[g][i] == INTENSITY_HCB) + ics->is_used = 1; #ifdef ERROR_RESILIENCE if (hDecoder->aacSectionDataResilienceFlag) @@ -1651,10 +1745,18 @@ static uint8_t section_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld printf("%d\n", ics->sect_end[g][i]); #endif - if (k + sect_len >= 8*15) - return 15; - if (i >= 8*15) - return 15; + if (ics->window_sequence == EIGHT_SHORT_SEQUENCE) + { + if (k + sect_len > 8*15) + return 15; + if (i >= 8*15) + return 15; + } else { + if (k + sect_len > MAX_SFB) + return 15; + if (i >= MAX_SFB) + return 15; + } for (sfb = k; sfb < k + sect_len; sfb++) { @@ -1675,6 +1777,13 @@ static uint8_t section_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld i++; } ics->num_sec[g] = i; + + /* the sum of all sect_len_incr elements for a given window + * group shall equal max_sfb */ + if (k != ics->max_sfb) + { + return 32; + } #if 0 printf("%d\n", ics->num_sec[g]); #endif @@ -1735,6 +1844,7 @@ static uint8_t decode_scale_factors(ic_stream *ics, bitfile *ld) break; case NOISE_HCB: /* noise books */ +#ifndef DRM /* decode noise energy */ if (noise_pcm_flag) { @@ -1750,6 +1860,10 @@ static uint8_t decode_scale_factors(ic_stream *ics, bitfile *ld) #ifdef SF_PRINT printf("%d\n", ics->scale_factors[g][sfb]); #endif +#else + /* PNS not allowed in DRM */ + return 29; +#endif break; default: /* spectral books */ @@ -2048,11 +2162,11 @@ static uint16_t extension_payload(bitfile *ld, drc_info *drc, uint16_t count) return n; case EXT_FILL_DATA: /* fill_nibble = */ faad_getbits(ld, 4 - DEBUGVAR(1,136,"extension_payload(): fill_nibble")); /* must be '0000' */ + DEBUGVAR(1,136,"extension_payload(): fill_nibble")); /* must be ‘0000’ */ for (i = 0; i < count-1; i++) { /* fill_byte[i] = */ faad_getbits(ld, 8 - DEBUGVAR(1,88,"extension_payload(): fill_byte")); /* must be '10100101' */ + DEBUGVAR(1,88,"extension_payload(): fill_byte")); /* must be ‘10100101’ */ } return count; case EXT_DATA_ELEMENT: @@ -2127,7 +2241,7 @@ static uint8_t dynamic_range_info(bitfile *ld, drc_info *drc) n++; drc->num_bands += band_incr; - for (i = 0; i < drc->num_bands; i++); + for (i = 0; i < drc->num_bands; i++) { drc->band_top[i] = (uint8_t)faad_getbits(ld, 8 DEBUGVAR(1,97,"dynamic_range_info(): band_top")); diff --git a/src/libfaad/syntax.h b/src/libfaad/syntax.h index a047dd644..123c4573f 100644 --- a/src/libfaad/syntax.h +++ b/src/libfaad/syntax.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: syntax.h,v 1.10 2005/10/29 23:57:07 tmmm Exp $ +** $Id: syntax.h,v 1.58 2007/11/01 12:33:40 menno Exp $ **/ #ifndef __SYNTAX_H__ @@ -114,9 +117,10 @@ void raw_data_block(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, bitfile *ld, program_config *pce, drc_info *drc); uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld, int16_t *spectral_data); -void aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, - bitfile *ld, program_config *pce, drc_info *drc); - +#ifdef DRM +void DRM_aac_scalable_main_element(NeAACDecHandle hDecoder, NeAACDecFrameInfo *hInfo, + bitfile *ld, program_config *pce, drc_info *drc); +#endif #ifdef __cplusplus } diff --git a/src/libfaad/tns.c b/src/libfaad/tns.c index bb4db731a..611865204 100644 --- a/src/libfaad/tns.c +++ b/src/libfaad/tns.c @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: tns.c,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: tns.c,v 1.40 2007/11/01 12:33:40 menno Exp $ **/ #include "common.h" @@ -106,11 +109,11 @@ void tns_decode_frame(ic_stream *ics, tns_info *tns, uint8_t sr_index, start = min(bottom, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); start = min(start, ics->max_sfb); - start = ics->swb_offset[start]; + start = min(ics->swb_offset[start], ics->swb_offset_max); end = min(top, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); end = min(end, ics->max_sfb); - end = ics->swb_offset[end]; + end = min(ics->swb_offset[end], ics->swb_offset_max); size = end - start; if (size <= 0) @@ -160,11 +163,11 @@ void tns_encode_frame(ic_stream *ics, tns_info *tns, uint8_t sr_index, start = min(bottom, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); start = min(start, ics->max_sfb); - start = ics->swb_offset[start]; + start = min(ics->swb_offset[start], ics->swb_offset_max); end = min(top, max_tns_sfb(sr_index, object_type, (ics->window_sequence == EIGHT_SHORT_SEQUENCE))); end = min(end, ics->max_sfb); - end = ics->swb_offset[end]; + end = min(ics->swb_offset[end], ics->swb_offset_max); size = end - start; if (size <= 0) @@ -292,7 +295,7 @@ static void tns_ma_filter(real_t *spectrum, uint16_t size, int8_t inc, real_t *l y = *spectrum; for (j = 0; j < order; j++) - y += MUL_C(state[j], lpc[j+1]); + y += MUL_C(state[state_index+j], lpc[j+1]); /* double ringbuffer state */ state_index--; diff --git a/src/libfaad/tns.h b/src/libfaad/tns.h index fc77894d8..8848c3f2d 100644 --- a/src/libfaad/tns.h +++ b/src/libfaad/tns.h @@ -1,6 +1,6 @@ /* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding -** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com +** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -19,10 +19,13 @@ ** Any non-GPL usage of this software or parts of this software is strictly ** forbidden. ** +** The "appropriate copyright message" mentioned in section 2c of the GPLv2 +** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com" +** ** Commercial non-GPL licensing of this software is possible. -** For more info contact Ahead Software through Mpeg4AAClicense@nero.com. +** For more info contact Nero AG through Mpeg4AAClicense@nero.com. ** -** $Id: tns.h,v 1.8 2005/10/29 23:57:07 tmmm Exp $ +** $Id: tns.h,v 1.23 2007/11/01 12:33:41 menno Exp $ **/ #ifndef __TNS_H__ diff --git a/src/libfaad/xine_faad_decoder.c b/src/libfaad/xine_faad_decoder.c index 934140a32..086c1daf5 100644 --- a/src/libfaad/xine_faad_decoder.c +++ b/src/libfaad/xine_faad_decoder.c @@ -1,23 +1,27 @@ -/* +/* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> @@ -35,10 +39,14 @@ #include "audio_out.h" #include "buffer.h" #include "xineutils.h" +#ifdef HAVE_FAAD_H +#include <faad.h> +#else #include "common.h" #include "structs.h" #include "decoder.h" #include "syntax.h" +#endif #define FAAD_MIN_STREAMSIZE 768 /* 6144 bits/channel */ @@ -50,30 +58,30 @@ typedef struct faad_decoder_s { audio_decoder_t audio_decoder; xine_stream_t *stream; - + /* faad2 stuff */ NeAACDecHandle faac_dec; NeAACDecConfigurationPtr faac_cfg; NeAACDecFrameInfo faac_finfo; int faac_failed; - + int raw_mode; - + unsigned char *buf; int size; int rec_audio_src_size; int max_audio_src_size; int pts; - + unsigned char *dec_config; int dec_config_size; - + uint32_t rate; - int bits_per_sample; - unsigned char num_channels; + int bits_per_sample; + unsigned char num_channels; int sbr; - uint32_t ao_cap_mode; - + uint32_t ao_cap_mode; + int output_open; unsigned long total_time; @@ -131,7 +139,7 @@ static int faad_open_dec( faad_decoder_t *this ) { if( this->dec_config ) { used = NeAACDecInit2(this->faac_dec, this->dec_config, this->dec_config_size, &this->rate, &this->num_channels); - + if( used < 0 ) { xprintf( this->stream->xine, XINE_VERBOSITY_LOG, _("libfaad: libfaad NeAACDecInit2 failed.\n")); @@ -142,7 +150,7 @@ static int faad_open_dec( faad_decoder_t *this ) { } else { used = NeAACDecInit(this->faac_dec, this->buf, this->size, &this->rate, &this->num_channels); - + if( used < 0 ) { xprintf ( this->stream->xine, XINE_VERBOSITY_LOG, _("libfaad: libfaad NeAACDecInit failed.\n")); @@ -150,16 +158,16 @@ static int faad_open_dec( faad_decoder_t *this ) { } else { lprintf( "NeAACDecInit() returned rate=%"PRId32" channels=%d (used=%d)\n", this->rate, this->num_channels, used); - + this->size -= used; memmove( this->buf, &this->buf[used], this->size ); } } } - + if( !this->bits_per_sample ) this->bits_per_sample = 16; - + if( this->faac_failed ) { if( this->faac_dec ) { NeAACDecClose( this->faac_dec ); @@ -169,16 +177,16 @@ static int faad_open_dec( faad_decoder_t *this ) { } else { faad_meta_info_set(this); } - + return this->faac_failed; } static int faad_open_output( faad_decoder_t *this ) { this->rec_audio_src_size = this->num_channels * FAAD_MIN_STREAMSIZE; - + switch( this->num_channels ) { case 1: - this->ao_cap_mode=AO_CAP_MODE_MONO; + this->ao_cap_mode=AO_CAP_MODE_MONO; break; case 6: if(this->stream->audio_out->get_capabilities(this->stream->audio_out) & @@ -193,11 +201,11 @@ static int faad_open_output( faad_decoder_t *this ) { } case 2: this->ao_cap_mode=AO_CAP_MODE_STEREO; - break; + break; default: return 0; } - + this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, this->bits_per_sample, @@ -212,48 +220,48 @@ static void faad_decode_audio ( faad_decoder_t *this, int end_frame ) { uint8_t *inbuf; audio_buffer_t *audio_buffer; int sample_size = this->size; - + if( !this->faac_dec ) return; inbuf = this->buf; while( (!this->raw_mode && end_frame && this->size >= 10) || (this->raw_mode && this->size >= this->rec_audio_src_size) ) { - - sample_buffer = NeAACDecDecode(this->faac_dec, + + sample_buffer = NeAACDecDecode(this->faac_dec, &this->faac_finfo, inbuf, sample_size); - + if( !sample_buffer ) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libfaad: %s\n", NeAACDecGetErrorMessage(this->faac_finfo.error)); - used = 1; + used = 1; } else { used = this->faac_finfo.bytesconsumed; - + /* raw AAC parameters might only be known after decoding the first frame */ if( !this->dec_config && (this->num_channels != this->faac_finfo.channels || this->rate != this->faac_finfo.samplerate) ) { - + this->num_channels = this->faac_finfo.channels; this->rate = this->faac_finfo.samplerate; - + lprintf("faacDecDecode() returned rate=%"PRId32" channels=%d used=%d\n", this->rate, this->num_channels, used); - + this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = 0; faad_open_output( this ); faad_meta_info_set( this ); } - + /* faad doesn't tell us about sbr until after the first frame */ if (this->sbr != this->faac_finfo.sbr) { this->sbr = this->faac_finfo.sbr; faad_meta_info_set( this ); } - + /* estimate bitrate */ this->total_time += (1000*this->faac_finfo.samples/(this->rate*this->num_channels)); this->total_data += 8*used; @@ -271,28 +279,53 @@ static void faad_decode_audio ( faad_decoder_t *this, int end_frame ) { lprintf("decoded %d/%d output %ld\n", used, this->size, this->faac_finfo.samples ); - + + /* Performing necessary channel reordering because aac uses a different + * layout than alsa: + * + * aac 5.1 channel layout: c l r ls rs lfe + * alsa 5.1 channel layout: l r ls rs c lfe + * + * Reordering is only necessary for 5.0 and above. Currently only 5.0 + * and 5.1 is being taken care of, the rest will stay in the wrong order + * for now. + * + * WARNING: the following needs a output format of 16 bits per sample. + * TODO: - reorder while copying (in the while() loop) and optimizing + */ + if(this->num_channels == 5 || this->num_channels == 6) + { + int i = 0; + uint16_t* buf = (uint16_t*)(sample_buffer); + + for(; i < this->faac_finfo.samples; i += this->num_channels) { + uint16_t center = buf[i]; + *((uint64_t*)(buf + i)) = *((uint64_t*)(buf + i + 1)); + buf[i + 4] = center; + } + } + while( decoded ) { audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); - + if( decoded < audio_buffer->mem_size ) - outsize = decoded; + outsize = decoded; else outsize = audio_buffer->mem_size; - + xine_fast_memcpy( audio_buffer->mem, sample_buffer, outsize ); audio_buffer->num_frames = outsize / (this->num_channels*2); audio_buffer->vpts = this->pts; this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - + this->pts = 0; decoded -= outsize; sample_buffer += outsize; } } - + if(used >= this->size){ this->size = 0; } else { @@ -301,7 +334,7 @@ static void faad_decode_audio ( faad_decoder_t *this, int end_frame ) { } if( !this->raw_mode ) - this->size = 0; + this->size = 0; } if( this->size ) @@ -312,40 +345,40 @@ static void faad_decode_audio ( faad_decoder_t *this, int end_frame ) { static void faad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { faad_decoder_t *this = (faad_decoder_t *) this_gen; - + if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; /* store config information from ESDS mp4/qt atom */ if( !this->faac_dec && (buf->decoder_flags & BUF_FLAG_SPECIAL) && buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG ) { - - this->dec_config = xine_xmalloc(buf->decoder_info[2]); + + this->dec_config = malloc(buf->decoder_info[2]); this->dec_config_size = buf->decoder_info[2]; memcpy(this->dec_config, buf->decoder_info_ptr[2], buf->decoder_info[2]); - + if( faad_open_dec(this) ) return; this->raw_mode = 0; } - /* get audio parameters from file header - (may be overwritten by libfaad returned parameters) */ + /* get audio parameters from file header + (may be overwritten by libfaad returned parameters) */ if (buf->decoder_flags & BUF_FLAG_STDHEADER) { this->rate=buf->decoder_info[1]; - this->bits_per_sample=buf->decoder_info[2] ; - this->num_channels=buf->decoder_info[3] ; - + this->bits_per_sample=buf->decoder_info[2] ; + this->num_channels=buf->decoder_info[3] ; + if( buf->size > sizeof(xine_waveformatex) ) { xine_waveformatex *wavex = (xine_waveformatex *) buf->content; if( wavex->cbSize > 0 ) { - this->dec_config = xine_xmalloc(wavex->cbSize); + this->dec_config = malloc(wavex->cbSize); this->dec_config_size = wavex->cbSize; memcpy(this->dec_config, buf->content + sizeof(xine_waveformatex), wavex->cbSize); - + if( faad_open_dec(this) ) return; @@ -361,15 +394,15 @@ static void faad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if( !this->size ) this->pts = buf->pts; - + if( this->size + buf->size > this->max_audio_src_size ) { this->max_audio_src_size = this->size + 2 * buf->size; this->buf = realloc( this->buf, this->max_audio_src_size ); } - + memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; - + if( !this->faac_dec && faad_open_dec(this) ) return; @@ -387,23 +420,23 @@ static void faad_discontinuity (audio_decoder_t *this_gen) { static void faad_dispose (audio_decoder_t *this_gen) { - faad_decoder_t *this = (faad_decoder_t *) this_gen; + faad_decoder_t *this = (faad_decoder_t *) this_gen; - if (this->output_open) + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = 0; - + if( this->buf ) free(this->buf); this->buf = NULL; this->size = 0; this->max_audio_src_size = 0; - + if( this->dec_config ) free(this->dec_config); this->dec_config = NULL; this->dec_config_size = 0; - + if( this->faac_dec ) NeAACDecClose(this->faac_dec); this->faac_dec = NULL; @@ -417,7 +450,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre faad_decoder_t *this ; - this = (faad_decoder_t *) xine_xmalloc (sizeof (faad_decoder_t)); + this = calloc(1, sizeof (faad_decoder_t)); this->audio_decoder.decode_data = faad_decode_data; this->audio_decoder.reset = faad_reset; @@ -427,7 +460,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre this->stream = stream; this->output_open = 0; this->raw_mode = 1; - this->faac_dec = NULL; + this->faac_dec = NULL; this->faac_failed = 0; this->buf = NULL; this->size = 0; @@ -458,7 +491,7 @@ static void *init_plugin (xine_t *xine, void *data) { faad_class_t *this ; - this = (faad_class_t *) xine_xmalloc (sizeof (faad_class_t)); + this = calloc(1, sizeof (faad_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -468,7 +501,7 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_AAC, 0 }; diff --git a/src/libffmpeg/Makefile.am b/src/libffmpeg/Makefile.am index 61acdd0d1..9af34df26 100644 --- a/src/libffmpeg/Makefile.am +++ b/src/libffmpeg/Makefile.am @@ -1,45 +1,12 @@ include $(top_srcdir)/misc/Makefile.common +DEFAULT_INCLUDES = -I. + if HAVE_FFMPEG -AM_CFLAGS = $(FFMPEG_CFLAGS) $(FFMPEG_POSTPROC_CFLAGS) -link_ffmpeg = $(FFMPEG_LIBS) $(FFMPEG_POSTPROC_LIBS) else -ff_cppflags = -I$(top_srcdir)/src/libffmpeg/libavutil -link_ffmpeg = \ - $(top_builddir)/src/libffmpeg/libavcodec/libavcodec.la \ - $(top_builddir)/src/libffmpeg/libavutil/libavutil.la \ - $(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la SUBDIRS = libavcodec libavutil endif -# ffmpeg_config.h is generated by configure -DISTCLEANFILES = ffmpeg_config.h - -# this must always be included, even if the current machine has no DXR3... -EXTRA_DIST = ffmpeg_encoder.c diff_to_ffmpeg_cvs.txt +EXTRA_DIST = diff_to_ffmpeg_cvs.txt INTERNAL_DOCS = diff_to_ffmpeg_cvs.txt - -xineplug_LTLIBRARIES = xineplug_decode_ff.la xineplug_decode_dvaudio.la - -if HAVE_DXR3 -AM_CPPFLAGS = -I$(top_srcdir)/src/dxr3 $(X_CFLAGS) $(ff_cppflags) \ - $(ZLIB_CPPFLAGS) -xineplug_decode_ff_la_SOURCES = ffmpeg_decoder.c ff_audio_decoder.c ff_video_decoder.c \ - ffmpeg_encoder.c ff_mpeg_parser.c ffmpeg_decoder.h \ - ff_mpeg_parser.h -else -AM_CPPFLAGS = $(ff_cppflags) $(ZLIB_CPPFLAGS) -xineplug_decode_ff_la_SOURCES = ffmpeg_decoder.c ff_audio_decoder.c ff_video_decoder.c \ - ff_mpeg_parser.c ffmpeg_decoder.h ff_mpeg_parser.h -endif - -xineplug_decode_ff_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -xineplug_decode_ff_la_LDFLAGS = $(xineplug_ldflags) $(IMPURE_TEXT_LDFLAGS) -xineplug_decode_ff_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm $(ZLIB_LIBS) \ - $(link_ffmpeg) $(PTHREAD_LIBS) $(LTLIBINTL) - -xineplug_decode_dvaudio_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) -xineplug_decode_dvaudio_la_LDFLAGS = $(xineplug_ldflags) -xineplug_decode_dvaudio_la_SOURCES = ff_dvaudio_decoder.c -xineplug_decode_dvaudio_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) diff --git a/src/libffmpeg/libavcodec/Makefile.am b/src/libffmpeg/libavcodec/Makefile.am index a5e6cd650..09c539b62 100644 --- a/src/libffmpeg/libavcodec/Makefile.am +++ b/src/libffmpeg/libavcodec/Makefile.am @@ -123,7 +123,7 @@ libavcodec_la_SOURCES = \ wnv1.c \ xan.c \ xl.c \ - zmbv.c + zmbv.c libavcodec_la_LDFLAGS = \ $(top_builddir)/src/libffmpeg/libavcodec/armv4l/libavcodec_armv4l.la \ diff --git a/src/libffmpeg/libavcodec/armv4l/Makefile.am b/src/libffmpeg/libavcodec/armv4l/Makefile.am index 33e0882c9..38979bc95 100644 --- a/src/libffmpeg/libavcodec/armv4l/Makefile.am +++ b/src/libffmpeg/libavcodec/armv4l/Makefile.am @@ -18,6 +18,6 @@ EXTRA_DIST = $(libavcodec_armv4l_src) $(libavcodec_armv4l_dummy) #if HAVE_ARMV4L #armv4l_modules = $(libavcodec_armv4l_src) #endif -armv4l_modules = +armv4l_modules = libavcodec_armv4l_la_SOURCES = $(armv4l_modules) $(libavcodec_armv4l_dummy) diff --git a/src/libffmpeg/libavcodec/i386/Makefile.am b/src/libffmpeg/libavcodec/i386/Makefile.am index b9d33c3a7..039c50d61 100644 --- a/src/libffmpeg/libavcodec/i386/Makefile.am +++ b/src/libffmpeg/libavcodec/i386/Makefile.am @@ -10,6 +10,9 @@ AM_CPPFLAGS = $(LIBFFMPEG_CPPFLAGS) -I$(top_srcdir)/src/libffmpeg/libavutil -I$( # Avoid "can't find register" failures with -O1 and higher dsputil_mmx.o dsputil_mmx.lo: CFLAGS=$(shell echo @CFLAGS@ | sed -e 's/-funroll-loops//g; s/$$/ -Os/') +if ARCH_X86_32 +dsputil_mmx.o dsputil_mmx.lo: CFLAGS+=-prefer-non-pic +endif # Avoid errors on (at least) amd64 with -O0 fdct_mmx.o fdct_mmx.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/^/-Os /; s/-O0\?\s/-Os /g'` diff --git a/src/libffmpeg/libavcodec/i386/dsputil_mmx.c b/src/libffmpeg/libavcodec/i386/dsputil_mmx.c index 673e749c4..27c0c678c 100644 --- a/src/libffmpeg/libavcodec/i386/dsputil_mmx.c +++ b/src/libffmpeg/libavcodec/i386/dsputil_mmx.c @@ -2566,17 +2566,17 @@ static void gmc_mmx(uint8_t *dst, uint8_t *src, int stride, int h, int ox, int o "psrlw %5, %%mm0 \n\t" "packuswb %%mm0, %%mm0 \n\t" - : + : : "m"(src[0]), "m"(src[1]), "m"(src[stride]), "m"(src[stride+1]), "m"(*r4), "m"(shift2) ); - + asm volatile( "movd %%mm0, %0 \n\t" : "=m"(dst[x+y*stride]) - : + : ); src += stride; } diff --git a/src/libffmpeg/libavcodec/libpostproc/Makefile.am b/src/libffmpeg/libavcodec/libpostproc/Makefile.am index 66bd17e53..a047bb8cd 100644 --- a/src/libffmpeg/libavcodec/libpostproc/Makefile.am +++ b/src/libffmpeg/libavcodec/libpostproc/Makefile.am @@ -3,7 +3,7 @@ include $(top_srcdir)/misc/Makefile.common # -fomit-frame-pointer is always needed. it might cause debug to not # work, but at least it compiles. AM_CFLAGS = -fomit-frame-pointer -fno-strict-aliasing -AM_CPPFLAGS = $(LIBFFMPEG_CPPFLAGS) -I$(top_srcdir)/src/libffmpeg/libavcodec +AM_CPPFLAGS = $(LIBFFMPEG_CPPFLAGS) -I$(top_srcdir)/src/libffmpeg/libavcodec # Avoid errors with -O0 postprocess.o postprocess.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/-O0\?\s/-Os /g'` diff --git a/src/libffmpeg/libavcodec/swscale.h b/src/libffmpeg/libavcodec/swscale.h index 06088b8e4..d3b430f84 100644 --- a/src/libffmpeg/libavcodec/swscale.h +++ b/src/libffmpeg/libavcodec/swscale.h @@ -23,7 +23,7 @@ /** * @file swscale.h - * @brief + * @brief * external api for the swscale stuff */ @@ -76,12 +76,12 @@ extern "C" { #define SWS_MAX_REDUCE_CUTOFF 0.002 #define SWS_CS_ITU709 1 -#define SWS_CS_FCC 4 +#define SWS_CS_FCC 4 #define SWS_CS_ITU601 5 #define SWS_CS_ITU624 5 -#define SWS_CS_SMPTE170M 5 -#define SWS_CS_SMPTE240M 7 -#define SWS_CS_DEFAULT 5 +#define SWS_CS_SMPTE170M 5 +#define SWS_CS_SMPTE240M 7 +#define SWS_CS_DEFAULT 5 @@ -128,7 +128,7 @@ SwsVector *sws_cloneVec(SwsVector *a); void sws_printVec(SwsVector *a); void sws_freeVec(SwsVector *a); -SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, +SwsFilter *sws_getDefaultFilter(float lumaGBlur, float chromaGBlur, float lumaSarpen, float chromaSharpen, float chromaHShift, float chromaVShift, int verbose); diff --git a/src/libmad/Makefile.am b/src/libmad/Makefile.am index c879645c5..56339cc72 100644 --- a/src/libmad/Makefile.am +++ b/src/libmad/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = -DOPT_SPEED diff --git a/src/libmad/bit.c b/src/libmad/bit.c index 8d9571e8f..cd0fe4904 100644 --- a/src/libmad/bit.c +++ b/src/libmad/bit.c @@ -27,7 +27,8 @@ # ifdef HAVE_LIMITS_H # include <limits.h> -# else +# endif +# ifndef CHAR_BIT # define CHAR_BIT 8 # endif diff --git a/src/libmad/fixed.h b/src/libmad/fixed.h index 658b3399e..d1465fd57 100644 --- a/src/libmad/fixed.h +++ b/src/libmad/fixed.h @@ -241,7 +241,7 @@ mad_fixed_t mad_f_mul_inline(mad_fixed_t x, mad_fixed_t y) # elif defined(FPM_ARM) -/* +/* * This ARM V4 version is as accurate as FPM_64BIT but much faster. The * least significant bit is properly rounded at no CPU cycle cost! */ diff --git a/src/libmad/layer12.c b/src/libmad/layer12.c index 25fd04d70..76def1189 100644 --- a/src/libmad/layer12.c +++ b/src/libmad/layer12.c @@ -27,7 +27,8 @@ # ifdef HAVE_LIMITS_H # include <limits.h> -# else +# endif +#ifndef CHAR_BIT # define CHAR_BIT 8 # endif diff --git a/src/libmad/layer3.c b/src/libmad/layer3.c index c5d46e8d1..899102e0d 100644 --- a/src/libmad/layer3.c +++ b/src/libmad/layer3.c @@ -34,7 +34,8 @@ # ifdef HAVE_LIMITS_H # include <limits.h> -# else +#endif +# ifndef CHAR_BIT # define CHAR_BIT 8 # endif diff --git a/src/libmad/synth.h b/src/libmad/synth.h index d5a63589e..64a8278d7 100644 --- a/src/libmad/synth.h +++ b/src/libmad/synth.h @@ -34,7 +34,7 @@ struct mad_pcm { struct mad_synth { mad_fixed_t filter[2][2][2][16][8]; /* polyphase filterbank outputs */ - /* [ch][eo][peo][s][v] */ + /* [ch][eo][peo][s][v] */ unsigned int phase; /* current processing phase */ diff --git a/src/libmad/xine_mad_decoder.c b/src/libmad/xine_mad_decoder.c index 2f6d7cfe3..c9067a676 100644 --- a/src/libmad/xine_mad_decoder.c +++ b/src/libmad/xine_mad_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA @@ -22,7 +22,7 @@ #include <stdlib.h> #include <string.h> -#include <config.h> +#include "config.h" #ifdef HAVE_MAD_H #include <mad.h> @@ -48,6 +48,20 @@ #define INPUT_BUF_SIZE 16384 +/* According to Rob Leslie (libmad author) : + * The absolute theoretical maximum frame size is 2881 bytes: MPEG 2.5 Layer II, + * 8000 Hz @ 160 kbps, with a padding slot. (Such a frame is unlikely, but it was + * a useful exercise to compute all possible frame sizes.) Add to this an 8 byte + * MAD_BUFFER_GUARD, and the minimum buffer size you should be streaming to + * libmad in the general case is 2889 bytes. + + * Theoretical frame sizes for Layer III range from 24 to 1441 bytes, but there + * is a "soft" limit imposed by the standard of 960 bytes. Nonetheless MAD can + * decode frames of any size as long as they fit entirely in the buffer you pass, + * not including the MAD_BUFFER_GUARD bytes. + */ +#define MAD_MIN_SIZE 2889 + typedef struct { audio_decoder_class_t decoder_class; } mad_class_t; @@ -59,7 +73,7 @@ typedef struct mad_decoder_s { int64_t pts; - struct mad_synth synth; + struct mad_synth synth; struct mad_stream stream; struct mad_frame frame; @@ -70,6 +84,9 @@ typedef struct mad_decoder_s { uint8_t buffer[INPUT_BUF_SIZE]; int bytes_in_buffer; int preview_mode; + int start_padding; + int end_padding; + int needs_more_data; } mad_decoder_t; @@ -84,6 +101,9 @@ static void mad_reset (audio_decoder_t *this_gen) { this->pts = 0; this->bytes_in_buffer = 0; this->preview_mode = 0; + this->start_padding = 0; + this->end_padding = 0; + this->needs_more_data = 0; mad_synth_init (&this->synth); mad_stream_init (&this->stream); @@ -95,7 +115,7 @@ static void mad_reset (audio_decoder_t *this_gen) { static void mad_discontinuity (audio_decoder_t *this_gen) { mad_decoder_t *this = (mad_decoder_t *) this_gen; - + this->pts = 0; } @@ -135,16 +155,17 @@ static int head_check(mad_decoder_t *this) { static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_decoder_t *this = (mad_decoder_t *) this_gen; + int bytes_in_buffer_at_pts; + + lprintf ("decode data, size: %d, decoder_flags: %d\n", buf->size, buf->decoder_flags); - lprintf ("decode data, decoder_flags: %d\n", buf->decoder_flags); - if (buf->size>(INPUT_BUF_SIZE-this->bytes_in_buffer)) { xprintf (this->xstream->xine, XINE_VERBOSITY_DEBUG, "libmad: ALERT input buffer too small (%d bytes, %d avail)!\n", buf->size, INPUT_BUF_SIZE-this->bytes_in_buffer); buf->size = INPUT_BUF_SIZE-this->bytes_in_buffer; } - + if ((buf->decoder_flags & BUF_FLAG_HEADER) == 0) { /* reset decoder on leaving preview mode */ @@ -156,17 +177,33 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->preview_mode = 1; } - xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], + bytes_in_buffer_at_pts = this->bytes_in_buffer; + + xine_fast_memcpy (&this->buffer[this->bytes_in_buffer], buf->content, buf->size); this->bytes_in_buffer += buf->size; - + /* printf ("libmad: decode data - doing it\n"); */ - mad_stream_buffer (&this->stream, this->buffer, + mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); + if (this->bytes_in_buffer < MAD_MIN_SIZE) + return; + + if (!this->needs_more_data) { + this->pts = buf->pts; + if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { + this->start_padding = buf->decoder_info[1]; + this->end_padding = buf->decoder_info[2]; + } else { + this->start_padding = 0; + this->end_padding = 0; + } + } + while (1) { if (mad_frame_decode (&this->frame, &this->stream) != 0) { @@ -174,7 +211,7 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (this->stream.next_frame) { int num_bytes = this->buffer + this->bytes_in_buffer - this->stream.next_frame; - + /* printf("libmad: MAD_ERROR_BUFLEN\n"); */ memmove(this->buffer, this->stream.next_frame, num_bytes); @@ -184,17 +221,20 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { switch (this->stream.error) { case MAD_ERROR_BUFLEN: + /* libmad wants more data */ + this->needs_more_data = 1; return; - default: - mad_stream_buffer (&this->stream, this->buffer, + default: + lprintf ("error 0x%04X, mad_stream_buffer %d bytes\n", this->stream.error, this->bytes_in_buffer); + mad_stream_buffer (&this->stream, this->buffer, this->bytes_in_buffer); } } else { int mode = (this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? AO_CAP_MODE_MONO : AO_CAP_MODE_STEREO; - if (!this->output_open + if (!this->output_open || (this->output_sampling_rate != this->frame.header.samplerate) || (this->output_mode != mode)) { @@ -210,23 +250,23 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (! _x_meta_info_get(this->xstream, XINE_META_INFO_AUDIOCODEC)) { switch (this->frame.header.layer) { case MAD_LAYER_I: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 1 (lib: MAD)"); break; case MAD_LAYER_II: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 2 (lib: MAD)"); break; case MAD_LAYER_III: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio layer 3 (lib: MAD)"); break; default: - _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->xstream, XINE_META_INFO_AUDIOCODEC, "MPEG audio (lib: MAD)"); } } - + if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; @@ -234,7 +274,7 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (!this->output_open) { this->output_open = (this->xstream->audio_out->open) (this->xstream->audio_out, this->xstream, 16, - this->frame.header.samplerate, + this->frame.header.samplerate, mode) ; } if (!this->output_open) { @@ -247,12 +287,14 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { mad_synth_frame (&this->synth, &this->frame); if ( (buf->decoder_flags & BUF_FLAG_PREVIEW) == 0 ) { - + unsigned int nchannels, nsamples; mad_fixed_t const *left_ch, *right_ch; struct mad_pcm *pcm = &this->synth.pcm; audio_buffer_t *audio_buffer; uint16_t *output; + int bitrate; + int pts_offset; audio_buffer = this->xstream->audio_out->get_buffer (this->xstream->audio_out); output = audio_buffer->mem; @@ -261,42 +303,81 @@ static void mad_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { nsamples = pcm->length; left_ch = pcm->samples[0]; right_ch = pcm->samples[1]; - + + /* padding */ + if (this->start_padding || this->end_padding) { + /* check padding validity */ + if (nsamples < (this->start_padding + this->end_padding)) { + lprintf("invalid padding data"); + this->start_padding = 0; + this->end_padding = 0; + } + lprintf("nsamples=%d, start_padding=%d, end_padding=%d\n", + nsamples, this->start_padding, this->end_padding); + nsamples -= this->start_padding + this->end_padding; + left_ch += this->start_padding; + right_ch += this->start_padding; + } + audio_buffer->num_frames = nsamples; + audio_buffer->vpts = this->pts; + while (nsamples--) { /* output sample(s) in 16-bit signed little-endian PCM */ - + *output++ = scale(*left_ch++); - - if (nchannels == 2) + + if (nchannels == 2) *output++ = scale(*right_ch++); } audio_buffer->num_frames = pcm->length; - audio_buffer->vpts = buf->pts; + + /* pts computing */ + if (this->frame.header.bitrate > 0) { + bitrate = this->frame.header.bitrate; + } else { + bitrate = _x_stream_info_get(this->xstream, XINE_STREAM_INFO_AUDIO_BITRATE); + lprintf("offset %d bps\n", bitrate); + } + audio_buffer->vpts = buf->pts; + if (audio_buffer->vpts && (bitrate > 0)) { + pts_offset = (bytes_in_buffer_at_pts * 8 * 90) / (bitrate / 1000); + lprintf("pts: %"PRId64", offset: %d pts, %d bytes\n", buf->pts, pts_offset, bytes_in_buffer_at_pts); + if (audio_buffer->vpts < pts_offset) + pts_offset = audio_buffer->vpts; + audio_buffer->vpts -= pts_offset; + } this->xstream->audio_out->put_buffer (this->xstream->audio_out, audio_buffer, this->xstream); + this->pts = buf->pts; buf->pts = 0; - + if (buf->decoder_flags & BUF_FLAG_AUDIO_PADDING) { + this->start_padding = buf->decoder_info[1]; + this->end_padding = buf->decoder_info[2]; + buf->decoder_info[1] = 0; + buf->decoder_info[2] = 0; + } else { + this->start_padding = 0; + this->end_padding = 0; + } } - - lprintf ("decode worked\n"); + lprintf ("decode worked\n"); } - } - + } } } static void mad_dispose (audio_decoder_t *this_gen) { - mad_decoder_t *this = (mad_decoder_t *) this_gen; + mad_decoder_t *this = (mad_decoder_t *) this_gen; mad_synth_finish (&this->synth); mad_frame_finish (&this->frame); mad_stream_finish(&this->stream); - if (this->output_open) { + if (this->output_open) { this->xstream->audio_out->close (this->xstream->audio_out, this->xstream); this->output_open = 0; } @@ -308,7 +389,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre mad_decoder_t *this ; - this = (mad_decoder_t *) xine_xmalloc (sizeof (mad_decoder_t)); + this = (mad_decoder_t *) calloc(1, sizeof(mad_decoder_t)); this->audio_decoder.decode_data = mad_decode_data; this->audio_decoder.reset = mad_reset; @@ -327,7 +408,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre this->stream.options = MAD_OPTION_IGNORECRC; - lprintf ("init\n"); + lprintf ("init\n"); return &this->audio_decoder; } @@ -351,8 +432,8 @@ static void dispose_class (audio_decoder_class_t *this) { static void *init_plugin (xine_t *xine, void *data) { mad_class_t *this; - - this = (mad_class_t *) xine_xmalloc (sizeof (mad_class_t)); + + this = (mad_class_t *) calloc(1, sizeof(mad_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -362,17 +443,17 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_MPEG, 0 }; static const decoder_info_t dec_info_audio = { audio_types, /* supported types */ - 7 /* priority */ + 8 /* priority */ }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 15, "mad", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libmpeg2/Makefile.am b/src/libmpeg2/Makefile.am index 9895aa5d7..849e56363 100644 --- a/src/libmpeg2/Makefile.am +++ b/src/libmpeg2/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_mpeg2.la @@ -22,7 +23,7 @@ xineplug_decode_mpeg2_la_SOURCES = \ xine_mpeg2_decoder.c \ libmpeg2_accel.c -xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) -lm +xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(LTLIBINTL) -lm xineplug_decode_mpeg2_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBMPEG2_CFLAGS) xineplug_decode_mpeg2_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libmpeg2/decode.c b/src/libmpeg2/decode.c index 58f34ccbc..c66b18691 100644 --- a/src/libmpeg2/decode.c +++ b/src/libmpeg2/decode.c @@ -461,9 +461,10 @@ static inline int parse_chunk (mpeg2dec_t * mpeg2dec, int code, break; case 0xb7: /* sequence end code */ -#ifdef LOG_PAN_SCAN - printf ("libmpeg2: sequence end code not handled\n"); -#endif + mpeg2_flush(mpeg2dec); + mpeg2dec->is_sequence_needed = 1; + break; + case 0xb8: /* group of pictures start code */ if (mpeg2_header_group_of_pictures (picture, buffer)) { printf ("libmpeg2: bad group of pictures\n"); diff --git a/src/libmpeg2/motion_comp.c b/src/libmpeg2/motion_comp.c index 8779c1296..f8faa3ee5 100644 --- a/src/libmpeg2/motion_comp.c +++ b/src/libmpeg2/motion_comp.c @@ -68,7 +68,7 @@ void mpeg2_mc_init (uint32_t mm_accel) mpeg2_mc = mpeg2_mc_altivec; } else #endif -#ifdef ARCH_SPARC +#if defined(ARCH_SPARC) && defined(ENABLE_VIS) if (mm_accel & MM_ACCEL_SPARC_VIS) { #ifdef LOG fprintf (stderr, "Using VIS for motion compensation\n"); diff --git a/src/libmpeg2/mpeg2.h b/src/libmpeg2/mpeg2.h index 253f300a2..ae69688f5 100644 --- a/src/libmpeg2/mpeg2.h +++ b/src/libmpeg2/mpeg2.h @@ -31,7 +31,8 @@ typedef struct mpeg2dec_s { uint32_t frame_format; /* this is where we keep the state of the decoder */ - struct picture_s * picture, *picture_base; + struct picture_s * picture; + void *picture_base; uint32_t shift; int new_sequence; @@ -45,7 +46,8 @@ typedef struct mpeg2dec_s { /* which is 224K for MP@ML streams. */ /* (we make no pretenses of decoding anything more than that) */ /* allocated in init - gcc has problems allocating such big structures */ - uint8_t * chunk_buffer, *chunk_base; + uint8_t * chunk_buffer; + void *chunk_base; /* pointer to current position in chunk_buffer */ uint8_t * chunk_ptr; /* last start code ? */ diff --git a/src/libmpeg2/slice_xvmc_vld.c b/src/libmpeg2/slice_xvmc_vld.c index 7e370a519..cd4eca0a2 100644 --- a/src/libmpeg2/slice_xvmc_vld.c +++ b/src/libmpeg2/slice_xvmc_vld.c @@ -17,6 +17,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "video_out.h" #include "mpeg2.h" diff --git a/src/libmpeg2/xine_mpeg2_decoder.c b/src/libmpeg2/xine_mpeg2_decoder.c index 4c4cc8654..75bc829c9 100644 --- a/src/libmpeg2/xine_mpeg2_decoder.c +++ b/src/libmpeg2/xine_mpeg2_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,10 @@ * stuff needed to turn libmpeg2 into a xine decoder plugin */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -69,11 +73,11 @@ static void mpeg2dec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) } return; } - + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { mpeg2_find_sequence_header (&this->mpeg2, buf->content, buf->content + buf->size); } else { - + mpeg2_decode_data (&this->mpeg2, buf->content, buf->content + buf->size, buf->pts); } @@ -117,7 +121,7 @@ static void mpeg2dec_dispose (video_decoder_t *this_gen) { static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { mpeg2dec_decoder_t *this ; - this = (mpeg2dec_decoder_t *) xine_xmalloc (sizeof (mpeg2dec_decoder_t)); + this = (mpeg2dec_decoder_t *) calloc(1, sizeof(mpeg2dec_decoder_t)); this->video_decoder.decode_data = mpeg2dec_decode_data; this->video_decoder.flush = mpeg2dec_flush; @@ -155,7 +159,7 @@ static void *init_plugin (xine_t *xine, void *data) { mpeg2_class_t *this; - this = (mpeg2_class_t *) xine_xmalloc (sizeof (mpeg2_class_t)); + this = (mpeg2_class_t *) calloc(1, sizeof(mpeg2_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -176,7 +180,7 @@ static const decoder_info_t dec_info_mpeg2 = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "mpeg2", XINE_VERSION_CODE, &dec_info_mpeg2, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libmpeg2new/Makefile.am b/src/libmpeg2new/Makefile.am index 49959da86..924a9c661 100644 --- a/src/libmpeg2new/Makefile.am +++ b/src/libmpeg2new/Makefile.am @@ -1,13 +1,18 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common -SUBDIRS = libmpeg2 +SUBDIRS = include libmpeg2 -xineplug_LTLIBRARIES = xineplug_decode_mpeg2.la +if ENABLE_MPEG2NEW +mpeg2new_module = xineplug_decode_mpeg2new.la +endif -xineplug_decode_mpeg2_la_SOURCES = \ - xine_mpeg2_decoder.c +xineplug_LTLIBRARIES = $(mpeg2new_module) -xineplug_decode_mpeg2_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBMPEG2_CFLAGS) -xineplug_decode_mpeg2_la_LIBADD = $(XINE_LIB) ./libmpeg2/libmpeg2.la -xineplug_decode_mpeg2_la_LDFLAGS = $(xineplug_ldflags) +xineplug_decode_mpeg2new_la_SOURCES = \ + xine_mpeg2new_decoder.c + +xineplug_decode_mpeg2new_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBMPEG2_CFLAGS) +xineplug_decode_mpeg2new_la_LIBADD = $(XINE_LIB) libmpeg2/libmpeg2.la +xineplug_decode_mpeg2new_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libmpeg2new/include/Makefile.am b/src/libmpeg2new/include/Makefile.am index 302d01cb1..91d5575ee 100644 --- a/src/libmpeg2new/include/Makefile.am +++ b/src/libmpeg2new/include/Makefile.am @@ -1,3 +1,4 @@ -pkginclude_HEADERS = mpeg2.h mpeg2convert.h +include $(top_builddir)/misc/Makefile.plugins +include $(top_srcdir)/misc/Makefile.common -EXTRA_DIST = video_out.h mmx.h alpha_asm.h vis.h attributes.h tendra.h +EXTRA_DIST = video_out.h mmx.h alpha_asm.h vis.h attributes.h tendra.h mpeg2.h mpeg2convert.h diff --git a/src/libmpeg2new/include/attributes.h b/src/libmpeg2new/include/attributes.h index eefbc0dd1..92db86e7e 100644 --- a/src/libmpeg2new/include/attributes.h +++ b/src/libmpeg2new/include/attributes.h @@ -22,11 +22,7 @@ */ /* use gcc attribs to align critical data structures */ -#ifdef ATTRIBUTE_ALIGNED_MAX -#define ATTR_ALIGN(align) __attribute__ ((__aligned__ ((ATTRIBUTE_ALIGNED_MAX < align) ? ATTRIBUTE_ALIGNED_MAX : align))) -#else -#define ATTR_ALIGN(align) -#endif +#include "../../xine-utils/attributes.h" #ifdef HAVE_BUILTIN_EXPECT #define likely(x) __builtin_expect ((x) != 0, 1) diff --git a/src/libmpeg2new/libmpeg2/Makefile.am b/src/libmpeg2new/libmpeg2/Makefile.am index f99894f12..0bfeda1ce 100644 --- a/src/libmpeg2new/libmpeg2/Makefile.am +++ b/src/libmpeg2new/libmpeg2/Makefile.am @@ -1,13 +1,20 @@ include $(top_srcdir)/misc/Makefile.common -noinst_LTLIBRARIES = libmpeg2.la libmpeg2arch.la +if ENABLE_MPEG2NEW +mpeg2new_libs = libmpeg2.la libmpeg2arch.la +endif + +noinst_LTLIBRARIES = $(mpeg2new_libs) libmpeg2_la_SOURCES = alloc.c header.c decode.c slice.c motion_comp.c idct.c libmpeg2_la_LIBADD = libmpeg2arch.la +AM_CPPFLAGS = -I$(srcdir)/../include + libmpeg2arch_la_SOURCES = motion_comp_mmx.c idct_mmx.c \ motion_comp_altivec.c idct_altivec.c \ motion_comp_alpha.c idct_alpha.c \ motion_comp_vis.c \ cpu_accel.c cpu_state.c +EXTRA_DIST = mpeg2_internal.h vlc.h diff --git a/src/libmpeg2new/libmpeg2/motion_comp_alpha.c b/src/libmpeg2new/libmpeg2/motion_comp_alpha.c index 05cd55084..73f6625d2 100644 --- a/src/libmpeg2new/libmpeg2/motion_comp_alpha.c +++ b/src/libmpeg2new/libmpeg2/motion_comp_alpha.c @@ -26,10 +26,10 @@ #include <inttypes.h> -#include "mpeg2.h" -#include "attributes.h" +#include "../include/mpeg2.h" +#include "../include/attributes.h" #include "mpeg2_internal.h" -#include "alpha_asm.h" +#include "../include/alpha_asm.h" static inline uint64_t avg2 (uint64_t a, uint64_t b) { diff --git a/src/libmpeg2new/libmpeg2/motion_comp_altivec.c b/src/libmpeg2new/libmpeg2/motion_comp_altivec.c index 4356aa6e7..cc1b72f56 100644 --- a/src/libmpeg2new/libmpeg2/motion_comp_altivec.c +++ b/src/libmpeg2new/libmpeg2/motion_comp_altivec.c @@ -30,8 +30,8 @@ #endif #include <inttypes.h> -#include "mpeg2.h" -#include "attributes.h" +#include "../include/mpeg2.h" +#include "../include/attributes.h" #include "mpeg2_internal.h" typedef vector signed char vector_s8_t; diff --git a/src/libmpeg2new/libmpeg2/motion_comp_vis.c b/src/libmpeg2new/libmpeg2/motion_comp_vis.c index 54c0f7e75..e4b61aaa7 100644 --- a/src/libmpeg2new/libmpeg2/motion_comp_vis.c +++ b/src/libmpeg2new/libmpeg2/motion_comp_vis.c @@ -22,14 +22,14 @@ #include "config.h" -#ifdef ARCH_SPARC +#if defined(ARCH_SPARC) && defined(ENABLE_VIS) #include <inttypes.h> -#include "mpeg2.h" -#include "attributes.h" +#include "../include/mpeg2.h" +#include "../include/attributes.h" #include "mpeg2_internal.h" -#include "vis.h" +#include "../include/vis.h" /* The trick used in some of this file is the formula from the MMX * motion comp code, which is: @@ -2058,4 +2058,4 @@ static void MC_avg_xy_8_vis (uint8_t * dest, const uint8_t * _ref, MPEG2_MC_EXTERN(vis); -#endif /* !(ARCH_SPARC) */ +#endif /* defined(ARCH_SPARC) && defined(ENABLE_VIS) */ diff --git a/src/libmpeg2new/xine_mpeg2new_decoder.c b/src/libmpeg2new/xine_mpeg2new_decoder.c index 7ceac9178..252cfcc54 100644 --- a/src/libmpeg2new/xine_mpeg2new_decoder.c +++ b/src/libmpeg2new/xine_mpeg2new_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA @@ -20,6 +20,10 @@ * stuff needed to turn libmpeg2 into a xine decoder plugin */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -35,13 +39,14 @@ #include "video_out.h" #include "buffer.h" - - +/* #define LOG #define LOG_FRAME_ALLOC_FREE #define LOG_ENTRY #define LOG_FRAME_COUNTER +*/ +#define _x_abort() do {} while (0) typedef struct { video_decoder_class_t decoder_class; @@ -63,10 +68,12 @@ typedef struct mpeg2_video_decoder_s { img_state_t img_state[30]; uint32_t frame_number; uint32_t rff_pattern; - -} mpeg2_video_decoder_t; +} mpeg2_video_decoder_t; +#ifndef LOG_FRAME_ALLOC_FREE +inline static void mpeg2_video_print_bad_state(img_state_t * img_state) {} +#else static void mpeg2_video_print_bad_state(img_state_t * img_state) { int32_t n,m; m=0; @@ -78,7 +85,8 @@ static void mpeg2_video_print_bad_state(img_state_t * img_state) { } if (m > 3) _x_abort(); if (m == 0) printf("NO FRAMES\n"); -} +} +#endif static void mpeg2_video_free_all(img_state_t * img_state) { int32_t n,m; @@ -91,7 +99,7 @@ static void mpeg2_video_free_all(img_state_t * img_state) { img_state[n].id = 0; } } -} +} static void mpeg2_video_print_fbuf(const mpeg2_fbuf_t * fbuf) { @@ -130,7 +138,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b else this->force_pan_scan = 0; } - + return; } @@ -143,7 +151,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b mpeg2_buffer (this->mpeg2dec, current, end); info = mpeg2_info (this->mpeg2dec); - + while ((state = mpeg2_parse (this->mpeg2dec)) != STATE_BUFFER) { switch (state) { case STATE_SEQUENCE: @@ -153,7 +161,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, info->sequence->picture_width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, info->sequence->picture_height); _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, info->sequence->frame_period / 300); - if (this->force_aspect) info->sequence->pixel_width = this->force_aspect; + if (this->force_aspect) ((mpeg2_sequence_t *)info->sequence)->pixel_width = this->force_aspect; /* ugly... */ switch (info->sequence->pixel_width) { case 3: this->ratio = 16.0 / 9.0; @@ -186,7 +194,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b } else { picture_structure = VO_BOTH_FIELDS; } - + img = this->stream->video_out->get_frame (this->stream->video_out, info->sequence->picture_width, info->sequence->picture_height, @@ -206,7 +214,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b img->duration += img->duration/4; } else { if( img->repeat_first_field ) { - img->duration = (img->duration * info->current_picture->nb_fields) / 2; + img->duration = (img->duration * info->current_picture->nb_fields) / 2; } } @@ -216,7 +224,7 @@ static void mpeg2_video_decode_data (video_decoder_t *this_gen, buf_element_t *b img->pts=0; } - + #ifdef LOG_FRAME_ALLOC_FREE printf ("libmpeg2:decode_data:get_frame xine=%p (id=%d)\n", img,img->id); #endif @@ -449,7 +457,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre mpeg2_video_decoder_t *this ; int32_t n; - this = (mpeg2_video_decoder_t *) xine_xmalloc (sizeof (mpeg2_video_decoder_t)); + this = (mpeg2_video_decoder_t *) calloc(1, sizeof(mpeg2_video_decoder_t)); this->video_decoder.decode_data = mpeg2_video_decode_data; this->video_decoder.flush = mpeg2_video_flush; @@ -490,7 +498,7 @@ static void *init_plugin (xine_t *xine, void *data) { mpeg2_class_t *this; - this = (mpeg2_class_t *) xine_xmalloc (sizeof (mpeg2_class_t)); + this = (mpeg2_class_t *) calloc(1, sizeof(mpeg2_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -503,15 +511,15 @@ static void *init_plugin (xine_t *xine, void *data) { * exported plugin catalog entry */ -static uint32_t supported_types[] = { BUF_VIDEO_MPEG, 0 }; +static const uint32_t supported_types[] = { BUF_VIDEO_MPEG, 0 }; -static decoder_info_t dec_info_mpeg2 = { +static const decoder_info_t dec_info_mpeg2 = { supported_types, /* supported types */ 6 /* priority */ }; -plugin_info_t xine_plugin_info[] = { - /* type, API, "name", version, special_info, init_function */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "mpeg2new", XINE_VERSION_CODE, &dec_info_mpeg2, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libmusepack/Makefile.am b/src/libmusepack/Makefile.am index 01875bdad..252e3d6ad 100644 --- a/src/libmusepack/Makefile.am +++ b/src/libmusepack/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = musepack @@ -9,7 +10,7 @@ xineplug_LTLIBRARIES = xineplug_decode_mpc.la endif if EXTERNAL_MPCDEC -internal_sources = +internal_sources = else internal_sources = huffsv46.c huffsv7.c idtag.c mpc_decoder.c \ mpc_reader.c requant.c streaminfo.c synth_filter.c diff --git a/src/libmusepack/xine_musepack_decoder.c b/src/libmusepack/xine_musepack_decoder.c index 7a2d30a06..41b90b080 100644 --- a/src/libmusepack/xine_musepack_decoder.c +++ b/src/libmusepack/xine_musepack_decoder.c @@ -24,6 +24,10 @@ * Seeking?? */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,6 +47,8 @@ #ifdef HAVE_MPCDEC_MPCDEC_H # include <mpcdec/mpcdec.h> +#elif defined(HAVE_MPC_MPCDEC_H) +# include <mpc/mpcdec.h> #else # include "musepack/musepack.h" #endif @@ -74,11 +80,15 @@ typedef struct mpc_decoder_s { mpc_reader reader; mpc_streaminfo streaminfo; +#ifndef HAVE_MPC_MPCDEC_H mpc_decoder decoder; - +#else + mpc_demux *decoder; +#endif + int decoder_ok; unsigned int current_frame; - + int32_t file_size; } mpc_decoder_t; @@ -87,61 +97,91 @@ typedef struct mpc_decoder_s { /************************************************************************** * musepack specific functions *************************************************************************/ - + /* Reads size bytes of data into buffer at ptr. */ +#ifndef HAVE_MPC_MPCDEC_H static int32_t mpc_reader_read(void *data, void *ptr, int size) { mpc_decoder_t *this = (mpc_decoder_t *) data; - +#else +static int32_t mpc_reader_read(mpc_reader *data, void *ptr, int size) { + mpc_decoder_t *this = (mpc_decoder_t *) data->data; +#endif + lprintf("mpc_reader_read: size=%d\n", size); - + /* Don't try to read more data than we have */ if (size > (this->size - this->read)) size = this->size - this->read; /* Copy the data */ xine_fast_memcpy(ptr, &this->buf[this->read], size); - + /* Update our position in the data buffer */ this->read += size; - + return size; } - + /* Seeks to byte position offset. */ +#ifndef HAVE_MPC_MPCDEC_H static mpc_bool_t mpc_reader_seek(void *data, int32_t offset) { mpc_decoder_t *this = (mpc_decoder_t *) data; - +#else +static mpc_bool_t mpc_reader_seek(mpc_reader *data, int32_t offset) { + mpc_decoder_t *this = (mpc_decoder_t *) data->data; +#endif + lprintf("mpc_reader_seek: offset=%d\n", offset); - + /* seek is only called when reading the header so we can assume * that the buffer starts at the start of the file */ this->read = offset; - + +#ifndef HAVE_MPC_MPCDEC_H return TRUE; +#else + return MPC_TRUE; +#endif } /* Returns the current byte offset in the stream. */ +#ifndef HAVE_MPC_MPCDEC_H static int32_t mpc_reader_tell(void *data) { +#else +static int32_t mpc_reader_tell(mpc_reader *data) { +#endif lprintf("mpc_reader_tell\n"); - + /* Tell isn't used so just return 0 */ return 0; } /* Returns the total length of the source stream, in bytes. */ +#ifndef HAVE_MPC_MPCDEC_H static int32_t mpc_reader_get_size(void *data) { mpc_decoder_t *this = (mpc_decoder_t *) data; - +#else +static int32_t mpc_reader_get_size(mpc_reader *data) { + mpc_decoder_t *this = (mpc_decoder_t *) data->data; +#endif + lprintf("mpc_reader_get_size\n"); - + return this->file_size; } /* True if the stream is a seekable stream. */ +#ifndef HAVE_MPC_MPCDEC_H static mpc_bool_t mpc_reader_canseek(void *data) { lprintf("mpc_reader_canseek\n"); - + return TRUE; +#else +static mpc_bool_t mpc_reader_canseek(mpc_reader *data) { + + lprintf("mpc_reader_canseek\n"); + return MPC_TRUE; +#endif } /* Convert 32bit float samples into 16bit int samples */ @@ -161,30 +201,39 @@ static inline void float_to_int(float *_f, int16_t *s16, int samples) { static int mpc_decode_frame (mpc_decoder_t *this) { float buffer[MPC_DECODER_BUFFER_LENGTH]; uint32_t frames; - +#ifdef HAVE_MPC_MPCDEC_H + mpc_frame_info frame; +#endif + lprintf("mpd_decode_frame\n"); - + +#ifndef HAVE_MPC_MPCDEC_H frames = mpc_decoder_decode(&this->decoder, buffer, 0, 0); - +#else + frame.buffer = buffer; + mpc_demux_decode(this->decoder, &frame); + frames = frame.samples; +#endif + if (frames > 0) { - audio_buffer_t *audio_buffer; + audio_buffer_t *audio_buffer; int16_t *int_samples; - + lprintf("got %d samples\n", frames); - + /* Get audio buffer */ audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); audio_buffer->vpts = 0; audio_buffer->num_frames = frames; - + /* Convert samples */ int_samples = (int16_t *) audio_buffer->mem; float_to_int(buffer, int_samples, frames*this->channels); - + /* Output converted samples */ this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); } - + return frames; } @@ -197,28 +246,28 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { int err; lprintf("mpc_decode_data\n"); - + if (!_x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED)) return; - + /* We don't handle special buffers */ if (buf->decoder_flags & BUF_FLAG_SPECIAL) return; - + /* Read header */ if (buf->decoder_flags & BUF_FLAG_HEADER) { - + lprintf("header\n"); - + /* File size is in decoder_info[0] */ this->file_size = buf->decoder_info[0]; - + /* Initialise the data accumulation buffer */ - this->buf = xine_xmalloc(INIT_BUFSIZE); + this->buf = calloc(1, INIT_BUFSIZE); this->buf_max = INIT_BUFSIZE; this->read = 0; this->size = 0; - + /* Initialise the reader */ this->reader.read = mpc_reader_read; this->reader.seek = mpc_reader_seek; @@ -226,49 +275,62 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->reader.get_size = mpc_reader_get_size; this->reader.canseek = mpc_reader_canseek; this->reader.data = this; - + /* Copy header to buffer */ xine_fast_memcpy(this->buf, buf->content, buf->size); this->size = buf->size; - + +#ifdef HAVE_MPC_MPCDEC_H + this->decoder = mpc_demux_init(&this->reader); + if (!this->decoder) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("libmusepack: mpc_demux_init failed.\n")); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); + return; + } + mpc_demux_get_info(this->decoder, &this->streaminfo); +#else /* Initialise and read stream info */ mpc_streaminfo_init(&this->streaminfo); - + if ((err = mpc_streaminfo_read(&this->streaminfo, &this->reader))) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("libmusepack: mpc_streaminfo_read failed: %d\n"), err); - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); return; } - +#endif + this->sample_rate = this->streaminfo.sample_freq; this->channels = this->streaminfo.channels; this->bits_per_sample = 16; - + /* After the header the demuxer starts sending data from an offset * of 28 bytes */ this->size = 28; - + /* We need to keep track of the current frame so we now when we've * reached the end of the stream */ this->current_frame = 0; - + /* Setup the decoder */ +#ifndef HAVE_MPC_MPCDEC_H mpc_decoder_setup(&this->decoder, &this->reader); +#endif this->decoder_ok = 0; /* Take this opportunity to initialize stream/meta information */ - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Musepack (libmusepack)"); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, (int) this->streaminfo.average_bitrate); return; } lprintf("data: %u size=%u read=%u\n", buf->size, this->size, this->read); - + /* if the audio output is not open yet, open the audio output */ if (!this->output_open) { this->output_open = (this->stream->audio_out->open) ( @@ -282,7 +344,7 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { /* if the audio still isn't open, do not go any further with the decode */ if (!this->output_open) return; - + /* If we run out of space in our internal buffer we discard what's * already been read */ if (((this->size + buf->size) > this->buf_max) && this->read) { @@ -291,7 +353,7 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { memmove(this->buf, &this->buf[this->read], this->size); this->read = 0; } - + /* If there still isn't space we have to increase the size of the * internal buffer */ if ((this->size + buf->size) > this->buf_max) { @@ -300,66 +362,78 @@ static void mpc_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->buf_max += 2*buf->size; this->buf = realloc(this->buf, this->buf_max); } - + /* Copy data */ xine_fast_memcpy(&this->buf[this->size], buf->content, buf->size); this->size += buf->size; - + /* Time to decode */ if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* Increment frame count */ +#ifndef HAVE_MPC_MPCDEC_H if (this->current_frame++ == this->streaminfo.frames) { +#else + if (this->current_frame++ == this->streaminfo.samples) { +#endif xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("libmusepack: data after last frame ignored\n")); return; } - + if (!this->decoder_ok) { /* We require MPC_DECODER_MEMSIZE bytes to initialise the decoder */ if ((this->size - this->read) >= MPC_DECODER_MEMSIZE) { lprintf("initialise"); - + +#ifndef HAVE_MPC_MPCDEC_H if (!mpc_decoder_initialize(&this->decoder, &this->streaminfo)) { +#else + if (!this->decoder) { +#endif xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_decoder_initialise failed\n")); - + _("libmusepack: mpc_decoder_initialise failed\n")); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); return; } - + this->decoder_ok = 1; } else { /* Not enough data yet */ return; } } - + /* mpc_decoder_decode may cause a read of MPC_DECODER_MEMSIZE/2 bytes so * make sure we have enough data available */ if ((this->size - this->read) >= MPC_DECODER_MEMSIZE2) { lprintf("decoding\n"); - + if ((err = mpc_decode_frame(this)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - _("libmusepack: mpc_decoder_decode failed: %d\n"), err); - + _("libmusepack: mpc_decoder_decode failed: %d\n"), err); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); return; } } - + /* If we are at the end of the stream we decode the remaining frames as we * know we'll have enough data */ +#ifndef HAVE_MPC_MPCDEC_H if (this->current_frame == this->streaminfo.frames) { +#else + if (this->current_frame == this->streaminfo.samples) { +#endif lprintf("flushing buffers\n"); - + do { if ((err = mpc_decode_frame(this)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("libmusepack: mpc_decoder_decode failed: %d\n"), err); } } while (err > 0); - + lprintf("buffers flushed\n"); } } @@ -388,7 +462,11 @@ static void mpc_dispose (audio_decoder_t *this_gen) { /* free anything that was allocated during operation */ if (this->buf) free(this->buf); - +#ifdef HAVE_MPC_MPCDEC_H + if (this->decoder) + mpc_demux_exit(this->decoder); +#endif + free(this); } @@ -396,7 +474,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre mpc_decoder_t *this ; - this = (mpc_decoder_t *) xine_xmalloc (sizeof (mpc_decoder_t)); + this = (mpc_decoder_t *) calloc(1, sizeof(mpc_decoder_t)); /* connect the member functions */ this->audio_decoder.decode_data = mpc_decode_data; @@ -409,7 +487,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre /* audio output is not open at the start */ this->output_open = 0; - + /* no buffer yet */ this->buf = NULL; @@ -441,7 +519,7 @@ static void *init_plugin (xine_t *xine, void *data) { mpc_class_t *this ; - this = (mpc_class_t *) xine_xmalloc (sizeof (mpc_class_t)); + this = (mpc_class_t *) calloc(1, sizeof(mpc_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -451,7 +529,7 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_MPC, 0 }; diff --git a/src/libreal/Makefile.am b/src/libreal/Makefile.am index 6e76d6279..90e47a63c 100644 --- a/src/libreal/Makefile.am +++ b/src/libreal/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common if ENABLE_REAL diff --git a/src/libreal/real_common.c b/src/libreal/real_common.c index fcd0fac8f..6eedb009a 100644 --- a/src/libreal/real_common.c +++ b/src/libreal/real_common.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2007 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -77,8 +77,8 @@ void _x_real_codecs_init(xine_t *const xine) { default_real_codecs_path[0] = 0; -#define UL64 0x05 /* /usr/{,local/}lib64 */ -#define UL 0x0A /* /usr/{,local/}lib */ +#define UL64 0x03 /* /usr/{,local/}lib64 */ +#define UL 0x0C /* /usr/{,local/}lib */ #define O 0x10 /* /opt */ #define OL64 0x20 /* /opt/lib64 */ #define OL 0x40 /* /opt/lib */ @@ -132,8 +132,8 @@ void _x_real_codecs_init(xine_t *const xine) { #endif - real_codecs_path = - xine->config->register_filename (xine->config, "decoder.external.real_codecs_path", + real_codecs_path = + xine->config->register_filename (xine->config, "decoder.external.real_codecs_path", default_real_codecs_path, XINE_CONFIG_STRING_IS_DIRECTORY_NAME, _("path to RealPlayer codecs"), @@ -154,7 +154,7 @@ void *_x_real_codec_open(xine_stream_t *const stream, const char *const path, const char *const codec_alternate) { char *codecpath = NULL; void *codecmodule = NULL; - + asprintf(&codecpath, "%s/%s", path, codec_name); if ( (codecmodule = dlopen(codecpath, RTLD_NOW)) ) { free(codecpath); @@ -178,12 +178,12 @@ void *_x_real_codec_open(xine_stream_t *const stream, const char *const path, } _x_message(stream, XINE_MSG_LIBRARY_LOAD_ERROR, codec_name, NULL); - + return NULL; } const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER | PLUGIN_MUST_PRELOAD, 18, "realvdec", XINE_VERSION_CODE, &dec_info_realvideo, init_realvdec }, { PLUGIN_AUDIO_DECODER | PLUGIN_MUST_PRELOAD, 15, "realadec", XINE_VERSION_CODE, &dec_info_realaudio, init_realadec }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/libreal/real_common.h b/src/libreal/real_common.h index 1e3d8c264..3c77eda5f 100644 --- a/src/libreal/real_common.h +++ b/src/libreal/real_common.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2007 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -26,7 +26,7 @@ #include "xine_internal.h" /* - * some fake functions to make real codecs happy + * some fake functions to make real codecs happy * These are, on current date (20070316) needed only for Alpha * codecs. * As they are far from being proper replacements, define them only there diff --git a/src/libreal/xine_real_audio_decoder.c b/src/libreal/xine_real_audio_decoder.c index 1b21de2d0..aa53bbb8d 100644 --- a/src/libreal/xine_real_audio_decoder.c +++ b/src/libreal/xine_real_audio_decoder.c @@ -1,27 +1,31 @@ -/* - * Copyright (C) 2000-2003 the xine project - * +/* + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * thin layer to use real binary-only codecs in xine * - * code inspired by work from Florian Schneider for the MPlayer Project + * code inspired by work from Florian Schneider for the MPlayer Project */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -51,6 +55,8 @@ typedef struct { /* empty so far */ } real_class_t; +typedef void * ra_codec_t; + typedef struct realdec_decoder_s { audio_decoder_t audio_decoder; @@ -60,18 +66,18 @@ typedef struct realdec_decoder_s { void *ra_handle; - unsigned long (*raCloseCodec)(void*); - unsigned long (*raDecode)(void*, char*,unsigned long,char*,unsigned int*,long); - unsigned long (*raFlush)(unsigned long,unsigned long,unsigned long); - unsigned long (*raFreeDecoder)(void*); - void* (*raGetFlavorProperty)(void*,unsigned long,unsigned long,int*); - unsigned long (*raInitDecoder)(void*, void*); - unsigned long (*raOpenCodec2)(void*); - unsigned long (*raSetFlavor)(void*,unsigned long); - void (*raSetDLLAccessPath)(char*); - void (*raSetPwd)(char*,char*); + uint32_t (*raCloseCodec)(ra_codec_t); + uint32_t (*raDecode)(ra_codec_t, char *, uint32_t, char *, uint32_t *, uint32_t); + uint32_t (*raFlush)(ra_codec_t, char *, uint32_t *); + uint32_t (*raFreeDecoder)(ra_codec_t); + void * (*raGetFlavorProperty)(ra_codec_t, uint16_t, uint16_t, uint16_t *); + uint32_t (*raInitDecoder)(ra_codec_t, void *); + uint32_t (*raOpenCodec2)(ra_codec_t *, const char *); + uint32_t (*raSetFlavor)(ra_codec_t, uint16_t); + void (*raSetDLLAccessPath)(char *); + void (*raSetPwd)(ra_codec_t, char *); - void *context; + ra_codec_t context; int sps, w, h; int block_align; @@ -86,20 +92,20 @@ typedef struct realdec_decoder_s { uint64_t pts; int output_open; - + int decoder_ok; } realdec_decoder_t; typedef struct { - int samplerate; - short bits; - short channels; - int unk1; - int subpacket_size; - int coded_frame_size; - int codec_data_length; - void *extras; + uint32_t samplerate; + uint16_t bits; + uint16_t channels; + uint16_t quality; + uint32_t subpacket_size; + uint32_t coded_frame_size; + uint32_t codec_data_length; + void *extras; } ra_init_t; static int load_syms_linux (realdec_decoder_t *this, const char *const codec_name, const char *const codec_alternate) { @@ -124,7 +130,7 @@ static int load_syms_linux (realdec_decoder_t *this, const char *const codec_nam if (!this->raCloseCodec || !this->raDecode || !this->raFlush || !this->raFreeDecoder || !this->raGetFlavorProperty || !this->raOpenCodec2 || !this->raSetFlavor || /*!raSetDLLAccessPath ||*/ !this->raInitDecoder){ - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("libareal: (audio) Cannot resolve symbols - incompatible dll: %s\n"), codec_name); return 0; } @@ -156,7 +162,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { int coded_frame_size2, data_len, flavor; int mode; void *extras; - + /* * extract header data */ @@ -167,13 +173,13 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { #ifdef LOG xine_hexdump (buf->content, buf->size); #endif - + flavor = _X_BE_16 (buf->content+22); coded_frame_size = _X_BE_32 (buf->content+24); codec_data_length= _X_BE_16 (buf->content+40); coded_frame_size2= _X_BE_16 (buf->content+42); subpacket_size = _X_BE_16 (buf->content+44); - + this->sps = subpacket_size; this->w = coded_frame_size2; this->h = codec_data_length; @@ -185,8 +191,8 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { /* FIXME: */ if (buf->type==BUF_AUDIO_COOK) { - - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libareal: audio header version 4 for COOK audio not supported.\n"); return 0; } @@ -204,7 +210,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { this->block_align= coded_frame_size2; lprintf ("0x%04x 0x%04x 0x%04x 0x%04x data_len 0x%04x\n", - subpacket_size, coded_frame_size, codec_data_length, + subpacket_size, coded_frame_size, codec_data_length, coded_frame_size2, data_len); lprintf ("%d samples/sec, %d bits/sample, %d channels\n", samples_per_sec, bits_per_sample, num_channels); @@ -216,13 +222,14 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Cook"); if (!load_syms_linux (this, "cook.so", "cook.so.6.0")) return 0; + this->block_align = subpacket_size; break; - + case BUF_AUDIO_ATRK: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Atrac"); if (!load_syms_linux (this, "atrc.so", "atrc.so.6.0")) return 0; - this->block_align = 384; + this->block_align = subpacket_size; break; case BUF_AUDIO_14_4: @@ -245,7 +252,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { break; default: - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libareal: error, i don't handle buf type 0x%08x\n", buf->type); return 0; } @@ -254,19 +261,19 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { * init codec */ - result = this->raOpenCodec2 (&this->context); + result = this->raOpenCodec2 (&this->context, NULL); if (result) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libareal: error in raOpenCodec2: %d\n", result); return 0; } - { + { ra_init_t init_data; init_data.samplerate = samples_per_sec; init_data.bits = bits_per_sample; init_data.channels = num_channels; - init_data.unk1 = 100; /* ??? */ + init_data.quality = 100; /* ??? */ init_data.subpacket_size = subpacket_size; /* subpacket size */ init_data.coded_frame_size = coded_frame_size; /* coded frame size */ init_data.codec_data_length = data_len; /* codec data length */ @@ -278,10 +285,10 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { printf ("libareal: extras :\n"); xine_hexdump (init_data.extras, data_len); #endif - + result = this->raInitDecoder (this->context, &init_data); if(result){ - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("libareal: decoder init failed, error code: 0x%x\n"), result); return 0; } @@ -307,14 +314,14 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { if (this->sps) { this->frame_size = this->w/this->sps*this->h*this->sps; - this->frame_buffer = xine_xmalloc (this->frame_size); - this->frame_reordered = xine_xmalloc (this->frame_size); + this->frame_buffer = calloc (1, this->frame_size); + this->frame_reordered = calloc (1, this->frame_size); this->frame_num_bytes = 0; } else { this->frame_size = this->w*this->h; - this->frame_buffer = xine_xmalloc (this->frame_size); + this->frame_buffer = calloc (this->w, this->h); this->frame_reordered = this->frame_buffer; this->frame_num_bytes = 0; @@ -337,7 +344,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { return 0; } - (this->stream->audio_out->open) (this->stream->audio_out, + (this->stream->audio_out->open) (this->stream->audio_out, this->stream, bits_per_sample, samples_per_sec, @@ -350,17 +357,10 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { return 1; } -static unsigned char sipr_swaps[38][2]={ - {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68}, - {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46}, - {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56}, - {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83}, - {77,80} }; - static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; - lprintf ("decode_data %d bytes, flags=0x%08x, pts=%"PRId64" ...\n", + lprintf ("decode_data %d bytes, flags=0x%08x, pts=%"PRId64" ...\n", buf->size, buf->decoder_flags, buf->pts); if (buf->decoder_flags & BUF_FLAG_PREVIEW) { @@ -383,130 +383,46 @@ static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->pts = buf->pts; size = buf->size; - while (size) { + int need; - int needed; - - needed = this->frame_size - this->frame_num_bytes; - - if (needed>size) { - - memcpy (this->frame_buffer+this->frame_num_bytes, buf->content, size); + need = this->frame_size - this->frame_num_bytes; + if (size < need) { + memcpy (this->frame_buffer + this->frame_num_bytes, + buf->content + buf->size - size, size); this->frame_num_bytes += size; - - lprintf ("buffering %d/%d bytes\n", this->frame_num_bytes, this->frame_size); - size = 0; - } else { - - int result; - int len =-1; - int n; - int sps = this->sps; - int w = this->w; - int h = this->h; audio_buffer_t *audio_buffer; + int n, len; + int result; - lprintf ("buffering %d bytes\n", needed); - - memcpy (this->frame_buffer+this->frame_num_bytes, buf->content, needed); - - size -= needed; + memcpy (this->frame_buffer + this->frame_num_bytes, + buf->content + buf->size - size, need); + size -= need; this->frame_num_bytes = 0; - lprintf ("frame completed. reordering...\n"); - lprintf ("bs=%d sps=%d w=%d h=%d \n",/*sh->wf->nBlockAlign*/-1,sps,w,h); - - if (!sps) { - - int j,n; - int bs=h*w*2/96; /* nibbles per subpacket */ - unsigned char *p=this->frame_buffer; - - /* 'sipr' way */ - /* demux_read_data(sh->ds, p, h*w); */ - for (n=0;n<38;n++){ - int i=bs*sipr_swaps[n][0]; - int o=bs*sipr_swaps[n][1]; - /* swap nibbles of block 'i' with 'o' TODO: optimize */ - for (j=0;j<bs;j++) { - int x=(i&1) ? (p[(i>>1)]>>4) : (p[(i>>1)]&15); - int y=(o&1) ? (p[(o>>1)]>>4) : (p[(o>>1)]&15); - if (o&1) - p[(o>>1)]=(p[(o>>1)]&0x0F)|(x<<4); - else - p[(o>>1)]=(p[(o>>1)]&0xF0)|x; - - if (i&1) - p[(i>>1)]=(p[(i>>1)]&0x0F)|(y<<4); - else - p[(i>>1)]=(p[(i>>1)]&0xF0)|y; - - ++i; - ++o; - } - } - /* - sh->a_in_buffer_size= - sh->a_in_buffer_len=w*h; - */ - - } else { - int x, y; - uint8_t *s; - - /* 'cook' way */ - - w /= sps; s = this->frame_buffer; - - for (y=0; y<h; y++) - - for (x=0; x<w; x++) { - - lprintf ("x=%d, y=%d, off %d\n", - x, y, sps*(h*x+((h+1)/2)*(y&1)+(y>>1))); - - memcpy (this->frame_reordered+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), - s, sps); - s+=sps; - - /* demux_read_data(sh->ds, sh->a_in_buffer+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), - sps); */ - - } - /* - sh->a_in_buffer_size= - sh->a_in_buffer_len=w*h*sps; - */ - } - -#ifdef LOG - xine_hexdump (this->frame_reordered, buf->size); -#endif - n = 0; - while (n<this->frame_size) { + while (n < this->frame_size) { audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); - result = this->raDecode (this->context, - this->frame_reordered+n, + result = this->raDecode (this->context, + this->frame_buffer + n, this->block_align, (char *) audio_buffer->mem, &len, -1); lprintf ("raDecode result %d, len=%d\n", result, len); - audio_buffer->vpts = this->pts; + audio_buffer->vpts = this->pts; this->pts = 0; audio_buffer->num_frames = len/this->sample_size;; - - this->stream->audio_out->put_buffer (this->stream->audio_out, + + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - n+=this->block_align; + n += this->block_align; } } } @@ -517,13 +433,13 @@ static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) static void realdec_reset (audio_decoder_t *this_gen) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; - + this->frame_num_bytes = 0; } static void realdec_discontinuity (audio_decoder_t *this_gen) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; - + this->pts = 0; } @@ -559,13 +475,13 @@ static void realdec_dispose (audio_decoder_t *this_gen) { lprintf ("dispose done\n"); } -static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { real_class_t *cls = (real_class_t *) class_gen; realdec_decoder_t *this ; - this = (realdec_decoder_t *) xine_xmalloc (sizeof (realdec_decoder_t)); + this = (realdec_decoder_t *) calloc(1, sizeof(realdec_decoder_t)); this->audio_decoder.decode_data = realdec_decode_data; this->audio_decoder.reset = realdec_reset; @@ -598,9 +514,8 @@ static void dispose_class (audio_decoder_class_t *this) { void *init_realadec (xine_t *xine, void *data) { real_class_t *this; - config_values_t *config = xine->config; - this = (real_class_t *) xine_xmalloc (sizeof (real_class_t)); + this = (real_class_t *) calloc(1, sizeof(real_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -616,11 +531,11 @@ void *init_realadec (xine_t *xine, void *data) { * exported plugin catalog entry */ -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_COOK, BUF_AUDIO_ATRK, /* BUF_AUDIO_14_4, BUF_AUDIO_28_8, */ BUF_AUDIO_SIPRO, 0 }; const decoder_info_t dec_info_realaudio = { audio_types, /* supported types */ - 7 /* priority */ + 6 /* priority */ }; diff --git a/src/libreal/xine_real_video_decoder.c b/src/libreal/xine_real_video_decoder.c index d68c7390e..4977ee889 100644 --- a/src/libreal/xine_real_video_decoder.c +++ b/src/libreal/xine_real_video_decoder.c @@ -1,27 +1,31 @@ /* - * Copyright (C) 2000-2004 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * thin layer to use real binary-only codecs in xine * - * code inspired by work from Florian Schneider for the MPlayer Project + * code inspired by work from Florian Schneider for the MPlayer Project */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -63,9 +67,9 @@ typedef struct realdec_decoder_s { uint32_t (*rvyuv_custom_message)(void*, void*); uint32_t (*rvyuv_free)(void*); - uint32_t (*rvyuv_hive_message)(uint32_t, uint32_t); + uint32_t (*rvyuv_hive_message)(uint32_t, void*); uint32_t (*rvyuv_init)(void*, void*); /* initdata,context */ - uint32_t (*rvyuv_transform)(char*, char*, void*, uint32_t*,void*); + uint32_t (*rvyuv_transform)(char*, char*, void*, void*, void*); void *context; @@ -113,13 +117,21 @@ typedef struct cmsg_data_s { typedef struct transform_in_s { uint32_t len; - uint32_t unknown1; - uint32_t chunks; - uint32_t* extra; - uint32_t unknown2; + uint32_t interpolate; + uint32_t nsegments; + void *segments; + uint32_t flags; uint32_t timestamp; } transform_in_t; +typedef struct { + uint32_t frames; + uint32_t notes; + uint32_t timestamp; + uint32_t width; + uint32_t height; +} transform_out_t; + /* * real codec loader */ @@ -137,12 +149,12 @@ static int load_syms_linux (realdec_decoder_t *this, const char *codec_name, con this->rvyuv_hive_message = dlsym (this->rv_handle, "RV20toYUV420HiveMessage"); this->rvyuv_init = dlsym (this->rv_handle, "RV20toYUV420Init"); this->rvyuv_transform = dlsym (this->rv_handle, "RV20toYUV420Transform"); - + if (this->rvyuv_custom_message && this->rvyuv_free && this->rvyuv_hive_message && this->rvyuv_init && - this->rvyuv_transform) + this->rvyuv_transform) return 1; this->rvyuv_custom_message = dlsym (this->rv_handle, "RV40toYUV420CustomMessage"); @@ -150,15 +162,15 @@ static int load_syms_linux (realdec_decoder_t *this, const char *codec_name, con this->rvyuv_hive_message = dlsym (this->rv_handle, "RV40toYUV420HiveMessage"); this->rvyuv_init = dlsym (this->rv_handle, "RV40toYUV420Init"); this->rvyuv_transform = dlsym (this->rv_handle, "RV40toYUV420Transform"); - + if (this->rvyuv_custom_message && this->rvyuv_free && this->rvyuv_hive_message && this->rvyuv_init && - this->rvyuv_transform) + this->rvyuv_transform) return 1; - xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, _("libreal: Error resolving symbols! (version incompatibility?)\n")); return 0; } @@ -169,7 +181,6 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { int result; rv_init_t init_data = {11, 0, 0, 0, 0, 0, 1, 0}; /* rv30 */ - switch (buf->type) { case BUF_VIDEO_RV20: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Real Video 2.0"); @@ -187,17 +198,17 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { return 0; break; default: - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libreal: error, i don't handle buf type 0x%08x\n", buf->type); _x_abort(); } init_data.w = _X_BE_16(&buf->content[12]); init_data.h = _X_BE_16(&buf->content[14]); - + this->width = (init_data.w + 1) & (~1); this->height = (init_data.h + 1) & (~1); - + if(buf->decoder_flags & BUF_FLAG_ASPECT) this->ratio = (double)buf->decoder_info[1] / (double)buf->decoder_info[2]; else @@ -205,15 +216,15 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { /* While the framerate is stored in the header it sometimes doesn't bear * much resemblence to the actual frequency of frames in the file. Hence - * it's better to just let the engine estimate the frame duration for us */ + * it's better to just let the engine estimate the frame duration for us */ #if 0 - this->fps = (double) _X_BE_16(&buf->content[22]) + + this->fps = (double) _X_BE_16(&buf->content[22]) + ((double) _X_BE_16(&buf->content[24]) / 65536.0); this->duration = 90000.0 / this->fps; #endif - + lprintf("this->ratio=%f\n", this->ratio); - + lprintf ("init_data.w=%d(0x%x), init_data.h=%d(0x%x)," "this->width=%d(0x%x), this->height=%d(0x%x)\n", init_data.w, init_data.w, @@ -227,22 +238,22 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { init_data.subformat = _X_BE_32(&buf->content[26]); init_data.format = _X_BE_32(&buf->content[30]); - + #ifdef LOG printf ("libreal: init_data for rvyuv_init:\n"); xine_hexdump ((char *) &init_data, sizeof (init_data)); - + printf ("libreal: buf->content\n"); xine_hexdump (buf->content, buf->size); -#endif - lprintf ("init codec %dx%d... %x %x\n", +#endif + lprintf ("init codec %dx%d... %x %x\n", init_data.w, init_data.h, init_data.subformat, init_data.format ); - + this->context = NULL; - - result = this->rvyuv_init (&init_data, &this->context); - + + result = this->rvyuv_init (&init_data, &this->context); + lprintf ("init result: %d\n", result); /* setup rv30 codec (codec sub-type and image dimensions): */ @@ -255,42 +266,42 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { cmsg24[1] = this->height; for(i = 2, j = 34; j < buf->size; i++, j++) cmsg24[i] = 4 * buf->content[j]; - + #ifdef LOG printf ("libreal: CustomMessage cmsg_data:\n"); - xine_hexdump ((uint8_t *) cmsg_data, sizeof (cmsg_data)); + xine_hexdump ((uint8_t *) &cmsg_data, sizeof (cmsg_data)); printf ("libreal: cmsg24:\n"); xine_hexdump ((uint8_t *) cmsg24, (buf->size - 34 + 2) * sizeof(uint32_t)); #endif - + this->rvyuv_custom_message (&cmsg_data, this->context); } - + (this->stream->video_out->open) (this->stream->video_out, this->stream); - + this->frame_size = this->width * this->height; this->frame_buffer = xine_xmalloc (this->width * this->height * 3 / 2); - - this->chunk_buffer = xine_xmalloc (BUF_SIZE); + + this->chunk_buffer = calloc(1, BUF_SIZE); this->chunk_buffer_max = BUF_SIZE; - + return 1; } static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; - lprintf ("decode_data, flags=0x%08x, len=%d, pts=%"PRId64" ...\n", + lprintf ("decode_data, flags=0x%08x, len=%d, pts=%"PRId64" ...\n", buf->decoder_flags, buf->size, buf->pts); if (buf->decoder_flags & BUF_FLAG_PREVIEW) { /* real_find_sequence_header (&this->real, buf->content, buf->content + buf->size);*/ return; } - + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->duration = buf->decoder_info[0]; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->duration); } @@ -301,14 +312,14 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0); } else if (this->decoder_ok && this->context) { - + /* Each frame starts with BUF_FLAG_FRAME_START and ends with * BUF_FLAG_FRAME_END. * The last buffer contains the chunk offset table. */ if (!(buf->decoder_flags & BUF_FLAG_SPECIAL)) { - + lprintf ("buffer (%d bytes)\n", buf->size); if (buf->decoder_flags & BUF_FLAG_FRAME_START) { @@ -318,10 +329,10 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) this->pts = buf->pts; lprintf ("new frame starting, pts=%"PRId64"\n", this->pts); } - + if ((this->chunk_buffer_size + buf->size) > this->chunk_buffer_max) { lprintf("increasing chunk buffer size\n"); - + this->chunk_buffer_max *= 2; this->chunk_buffer = realloc(this->chunk_buffer, this->chunk_buffer_max); } @@ -334,15 +345,15 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) } else { /* end of frame, chunk table */ - + lprintf ("special buffer (%d bytes)\n", buf->size); - + if (buf->decoder_info[1] == BUF_SPECIAL_RV_CHUNK_TABLE) { int result; vo_frame_t *img; - uint32_t transform_out[5]; + transform_out_t transform_out; transform_in_t transform_in = { this->chunk_buffer_size, /* length of the packet (sub-packets appended) */ @@ -369,31 +380,31 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) xine_hexdump (this->chunk_buffer, this->chunk_buffer_size); printf ("libreal: transform_in:\n"); - xine_hexdump ((uint8_t *) transform_in, 6 * 4); + xine_hexdump ((uint8_t *) &transform_in, sizeof(rv_xform_in_t)); printf ("libreal: chunk_table:\n"); - xine_hexdump ((uint8_t *) buf->decoder_info_ptr[2], + xine_hexdump ((uint8_t *) buf->decoder_info_ptr[2], 2*(buf->decoder_info[2]+1)*sizeof(uint32_t)); #endif result = this->rvyuv_transform (this->chunk_buffer, this->frame_buffer, &transform_in, - transform_out, + &transform_out, this->context); lprintf ("transform result: %08x\n", result); lprintf ("transform_out:\n"); - #ifdef LOG - xine_hexdump ((uint8_t *) transform_out, 5 * 4); - #endif +#ifdef LOG + xine_hexdump ((uint8_t *) &transform_out, 5 * 4); +#endif /* Sometimes the stream contains video of a different size * to that specified in the realmedia header */ - if(transform_out[0] && ((transform_out[3] != this->width) || - (transform_out[4] != this->height))) { - this->width = transform_out[3]; - this->height = transform_out[4]; + if(transform_out.frames && ((transform_out.width != this->width) || + (transform_out.height != this->height))) { + this->width = transform_out.width; + this->height = transform_out.height; this->frame_size = this->width * this->height; @@ -447,13 +458,13 @@ static void realdec_flush (video_decoder_t *this_gen) { static void realdec_reset (video_decoder_t *this_gen) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; - + this->chunk_buffer_size = 0; } static void realdec_discontinuity (video_decoder_t *this_gen) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; - + this->pts = 0; } @@ -469,27 +480,27 @@ static void realdec_dispose (video_decoder_t *this_gen) { if (this->rvyuv_free && this->context) this->rvyuv_free (this->context); - if (this->rv_handle) + if (this->rv_handle) dlclose (this->rv_handle); if (this->frame_buffer) free (this->frame_buffer); - + if (this->chunk_buffer) free (this->chunk_buffer); - + free (this); lprintf ("dispose done\n"); } -static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { real_class_t *cls = (real_class_t *) class_gen; realdec_decoder_t *this ; - this = (realdec_decoder_t *) xine_xmalloc (sizeof (realdec_decoder_t)); + this = (realdec_decoder_t *) calloc(1, sizeof(realdec_decoder_t)); this->video_decoder.decode_data = realdec_decode_data; this->video_decoder.flush = realdec_flush; @@ -526,9 +537,8 @@ static void dispose_class (video_decoder_class_t *this) { void *init_realvdec (xine_t *xine, void *data) { real_class_t *this; - config_values_t *config = xine->config; - this = (real_class_t *) xine_xmalloc (sizeof (real_class_t)); + this = (real_class_t *) calloc(1, sizeof(real_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -544,8 +554,7 @@ void *init_realvdec (xine_t *xine, void *data) { * exported plugin catalog entry */ -static uint32_t supported_types[] = { BUF_VIDEO_RV20, - BUF_VIDEO_RV30, +static uint32_t supported_types[] = { BUF_VIDEO_RV30, BUF_VIDEO_RV40, 0 }; diff --git a/src/libspucc/Makefile.am b/src/libspucc/Makefile.am index a8af8632e..1e170cdd5 100644 --- a/src/libspucc/Makefile.am +++ b/src/libspucc/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spucc.la diff --git a/src/libspucc/cc_decoder.c b/src/libspucc/cc_decoder.c index 8d666e847..00300adc2 100644 --- a/src/libspucc/cc_decoder.c +++ b/src/libspucc/cc_decoder.c @@ -1,21 +1,21 @@ /* * Copyright (C) 2000-2003 the xine project - * - * Copyright (C) Christian Vogler + * + * Copyright (C) Christian Vogler * cvogler@gradient.cis.upenn.edu - December 2001 * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -27,6 +27,10 @@ * available at http://sourceforge.net/projects/ccdecoder/. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -79,7 +83,7 @@ static const int text_colormap[NUM_FG_COL] = { /* FIXME: The colors look fine on an XShm display, but they look *terrible* with the Xv display on the NVidia driver on a GeForce 3. The colors bleed into each other more than I'd expect from the downsampling into YUV - colorspace. + colorspace. At this moment, it looks like a problem in the Xv YUV blending functions. */ typedef struct colorinfo_s { @@ -213,16 +217,14 @@ static const uint8_t *const cc_alpha_palettes[NUM_CC_PALETTES] = { /* --------------------- misc. EIA 608 definitions -------------------*/ -#define TRANSP_SPACE 0x19 /* code for transparent space, essentially +#define TRANSP_SPACE 0x19 /* code for transparent space, essentially arbitrary */ -#define MAX(a, b) ((a) > (b)? (a) : (b)) - /* mapping from PAC row code to actual CC row */ static const int rowdata[] = {10, -1, 0, 1, 2, 3, 11, 12, 13, 14, 4, 5, 6, 7, 8, 9}; /* FIXME: do real â„¢ (U+2122) */ -/* Code 182 must be mapped as a musical note ('♪', U+266A) in the caption font */ +/* Code 182 must be mapped as a musical note ('♪', U+266A) in the caption font */ static const char specialchar[] = { 174 /* ® */, 176 /* ° */, 189 /* ½ */, 191 /* ¿ */, 'T' /* â„¢ */, 162 /* ¢ */, 163 /* £ */, 182 /* ¶ => ♪ */, @@ -269,11 +271,11 @@ struct cc_renderer_s { If this happens, the vpts of a hide caption event can actually be slightly higher than the vpts of the following show caption event. For this reason, we remember the vpts of the hide event and force - the next show event's vpts to be at least equal to the hide event's + the next show event's vpts to be at least equal to the hide event's vpts. */ int64_t last_hide_vpts; - + /* caption palette and alpha channel */ uint32_t cc_palette[OVL_PALETTE_SIZE]; uint8_t cc_trans[OVL_PALETTE_SIZE]; @@ -359,7 +361,7 @@ struct cc_decoder_s { /*---------------- general utility functions ---------------------*/ -static void get_font_metrics(osd_renderer_t *renderer, +static void get_font_metrics(osd_renderer_t *renderer, const char *fontname, int font_size, int *maxw, int *maxh) { @@ -373,7 +375,7 @@ static void get_font_metrics(osd_renderer_t *renderer, renderer->set_encoding(testc, "iso-8859-1"); for (c = 32; c < 256; c++) { int tw, th; - char buf[2]; + char buf[2]; buf[0] = (char)c; buf[1] = '\0'; @@ -528,8 +530,8 @@ static void ccrow_set_attributes(cc_renderer_t *renderer, cc_row_t *this, fontname = cap_info->italic_font; else fontname = cap_info->font; - renderer->osd_renderer->set_font(renderer->cap_display, (char *) fontname, - cap_info->font_size); + renderer->osd_renderer->set_font(renderer->cap_display, (char *) fontname, + cap_info->font_size); } @@ -608,7 +610,7 @@ static void ccrow_render(cc_renderer_t *renderer, cc_row_t *this, int rownum) x = renderer->width * pos / CC_COLUMNS; y = base_y; } - + #ifdef LOG_DEBUG printf("text_w, text_h = %d, %d\n", text_w, text_h); printf("cc from %d to %d; text plotting from %d, %d (basey = %d)\n", pos, endpos, x, y, base_y); @@ -619,7 +621,7 @@ static void ccrow_render(cc_renderer_t *renderer, cc_row_t *this, int rownum) int textcol = text_colormap[this->cells[seg_attr[seg]].attributes.foreground]; int box_x1 = x + cumulative_seg_width[seg]; int box_x2 = x + cumulative_seg_width[seg + 1]; - + #ifdef LOG_DEBUG printf("ccrow_render: rendering segment %d from %d to %d / %d to %d\n", seg, seg_pos[seg], seg_pos[seg + 1], @@ -644,7 +646,7 @@ static void ccrow_render(cc_renderer_t *renderer, cc_row_t *this, int rownum) /* text is already mapped from EIA-608 into iso-8859-1 */ osd_renderer->render_text(renderer->cap_display, - x + cumulative_seg_width[seg], y, buf, + x + cumulative_seg_width[seg], y, buf, textcol); } @@ -710,7 +712,7 @@ static void ccbuf_add_char(cc_buffer_t *this, uint8_t c) } -static void ccbuf_set_cursor(cc_buffer_t *this, int row, int column, +static void ccbuf_set_cursor(cc_buffer_t *this, int row, int column, int underline, int italics, int color) { cc_row_t *rowbuf = &this->rows[row]; @@ -724,7 +726,7 @@ static void ccbuf_set_cursor(cc_buffer_t *this, int row, int column, rowbuf->pac_attr = attr; rowbuf->pac_attr_chg = 1; - this->rowpos = row; + this->rowpos = row; rowbuf->pos = column; rowbuf->attr_chg = 0; } @@ -734,7 +736,7 @@ static void ccbuf_apply_attribute(cc_buffer_t *this, cc_attribute_t *attr) { cc_row_t *rowbuf = &this->rows[this->rowpos]; int pos = rowbuf->pos; - + rowbuf->attr_chg = 1; rowbuf->cells[pos].attributes = *attr; /* A midrow attribute always counts as a space */ @@ -802,7 +804,7 @@ static void cc_renderer_build_palette(cc_renderer_t *this) int i, j; const colorinfo_t *cc_text = cc_text_palettes[this->cc_state->cc_cfg->cc_scheme]; const uint8_t *cc_alpha = cc_alpha_palettes[this->cc_state->cc_cfg->cc_scheme]; - + memset(this->cc_palette, 0, sizeof (this->cc_palette)); memset(this->cc_trans, 0, sizeof (this->cc_trans)); for (i = 0; i < NUM_FG_COL; i++) { @@ -877,12 +879,12 @@ static void cc_renderer_show_caption(cc_renderer_t *this, cc_buffer_t *buf, this->osd_renderer->clear(this->cap_display); ccbuf_render(this, buf); - this->osd_renderer->set_position(this->cap_display, + this->osd_renderer->set_position(this->cap_display, this->x, this->y); vpts = MAX(vpts, this->last_hide_vpts); this->osd_renderer->show(this->cap_display, vpts); - + this->displayed = 1; this->display_vpts = vpts; } @@ -922,7 +924,7 @@ cc_renderer_t *cc_renderer_open(osd_renderer_t *osd_renderer, metronom_t *metronom, cc_state_t *cc_state, int video_width, int video_height) { - cc_renderer_t *this = (cc_renderer_t *) xine_xmalloc(sizeof (cc_renderer_t)); + cc_renderer_t *this = calloc(1, sizeof (cc_renderer_t)); this->osd_renderer = osd_renderer; this->metronom = metronom; @@ -930,7 +932,7 @@ cc_renderer_t *cc_renderer_open(osd_renderer_t *osd_renderer, cc_renderer_update_cfg(this, video_width, video_height); #ifdef LOG_DEBUG printf("spucc: cc_renderer: open\n"); -#endif +#endif return this; } @@ -942,7 +944,7 @@ void cc_renderer_close(cc_renderer_t *this_obj) #ifdef LOG_DEBUG printf("spucc: cc_renderer: close\n"); -#endif +#endif } @@ -977,7 +979,7 @@ void cc_renderer_update_cfg(cc_renderer_t *this_obj, int video_width, #ifdef LOG_DEBUG printf("spucc: cc_renderer: update config: max text extents: %d, %d\n", this_obj->max_char_width, this_obj->max_char_height); -#endif +#endif /* need to adjust captioning area to accommodate font? */ required_w = CC_COLUMNS * (this_obj->max_char_width + 1); @@ -999,7 +1001,7 @@ void cc_renderer_update_cfg(cc_renderer_t *this_obj, int video_width, this_obj->y = (this_obj->video_height - required_h) / 2; } - if (required_w <= this_obj->video_width && + if (required_w <= this_obj->video_width && required_h <= this_obj->video_height) { this_obj->cc_state->can_cc = 1; cc_renderer_adjust_osd_object(this_obj); @@ -1010,7 +1012,7 @@ void cc_renderer_update_cfg(cc_renderer_t *this_obj, int video_width, printf("spucc: required captioning area %dx%d exceeds screen %dx%d!\n" " Captions disabled. Perhaps you should choose a smaller" " font?\n", - required_w, required_h, this_obj->video_width, + required_w, required_h, this_obj->video_width, this_obj->video_height); } } @@ -1048,10 +1050,10 @@ static void cc_hide_displayed(cc_decoder_t *this) if (cc_renderer_on_display(this->cc_state->renderer)) { int64_t vpts = cc_renderer_calc_vpts(this->cc_state->renderer, this->pts, - this->f_offset); + this->f_offset); #ifdef LOG_DEBUG printf("cc_decoder: cc_hide_displayed: hiding caption %u at vpts %u\n", this->capid, vpts); -#endif +#endif cc_renderer_hide_caption(this->cc_state->renderer, vpts); } } @@ -1068,7 +1070,7 @@ static void cc_show_displayed(cc_decoder_t *this) this->f_offset); #ifdef LOG_DEBUG printf("cc_decoder: cc_show_displayed: showing caption %u at vpts %u\n", this->capid, vpts); -#endif +#endif this->capid++; cc_renderer_show_caption(this->cc_state->renderer, &this->on_buf->channel[this->on_buf->channel_no], @@ -1291,7 +1293,7 @@ static void cc_decode_EIA608(cc_decoder_t *this, uint16_t data) } else { switch (c1) { - + case 0x10: /* extended background attribute code */ cc_decode_ext_attribute(this, channel, c1, c2); break; @@ -1319,7 +1321,7 @@ static void cc_decode_EIA608(cc_decoder_t *this, uint16_t data) } } } - + this->lastcode = data; } @@ -1345,13 +1347,13 @@ void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, * 0x00 is padding, followed by 2 more 0x00. * * 0x01 always seems to appear at the beginning, always seems to - * be followed by 0xf8, 8-bit number. + * be followed by 0xf8, 8-bit number. * The lower 7 bits of this 8-bit number seem to denote the * number of code triplets that follow. - * The most significant bit denotes whether the Line 21 field 1 + * The most significant bit denotes whether the Line 21 field 1 * captioning information is at odd or even triplet offsets from this * beginning triplet. 1 denotes odd offsets, 0 denotes even offsets. - * + * * Most captions are encoded with odd offsets, so this is what we * will assume. * @@ -1376,31 +1378,31 @@ void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, } printf("\n"); } -#endif +#endif while (curbytes < buf_len) { int skip = 2; cc_code = *current++; curbytes++; - + if (buf_len - curbytes < 2) { #ifdef LOG_DEBUG fprintf(stderr, "Not enough data for 2-byte CC encoding\n"); #endif break; } - + data1 = *current; data2 = *(current + 1); - + switch (cc_code) { case 0xfe: /* expect 2 byte encoding (perhaps CC3, CC4?) */ /* ignore for time being */ skip = 2; break; - + case 0xff: /* expect EIA-608 CC1/CC2 encoding */ if (good_parity(data1 | (data2 << 8))) { @@ -1409,12 +1411,12 @@ void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, } skip = 5; break; - + case 0x00: /* This seems to be just padding */ skip = 2; break; - + case 0x01: odd_offset = data2 & 0x80; if (odd_offset) @@ -1422,7 +1424,7 @@ void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, else skip = 5; break; - + default: #ifdef LOG_DEBUG fprintf(stderr, "Unknown CC encoding: %x\n", cc_code); @@ -1439,7 +1441,7 @@ void decode_cc(cc_decoder_t *this, uint8_t *buffer, uint32_t buf_len, cc_decoder_t *cc_decoder_open(cc_state_t *cc_state) { - cc_decoder_t *this = (cc_decoder_t *) xine_xmalloc(sizeof (cc_decoder_t)); + cc_decoder_t *this = calloc(1, sizeof (cc_decoder_t)); /* configfile stuff */ this->cc_state = cc_state; diff --git a/src/libspucc/cc_decoder.h b/src/libspucc/cc_decoder.h index 8698189a6..6ee6d860b 100644 --- a/src/libspucc/cc_decoder.h +++ b/src/libspucc/cc_decoder.h @@ -1,21 +1,21 @@ /* - * Copyright (C) 2000-2003 the xine project - * - * Copyright (C) Christian Vogler + * Copyright (C) 2000-2008 the xine project + * + * Copyright (C) Christian Vogler * cvogler@gradient.cis.upenn.edu - December 2001 * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -31,11 +31,7 @@ typedef struct cc_decoder_s cc_decoder_t; typedef struct cc_renderer_s cc_renderer_t; #define NUM_CC_PALETTES 2 -static const char *cc_schemes[NUM_CC_PALETTES + 1] = { - "White/Gray/Translucent", - "White/Black/Solid", - NULL -}; +extern const char *cc_schemes[]; #define CC_FONT_MAX 256 @@ -47,7 +43,7 @@ typedef struct cc_config_s { int center; /* true if captions should be centered */ /* according to text width */ int cc_scheme; /* which captioning scheme to use */ - + int config_version; /* the decoder should be updated when this is increased */ } cc_config_t; diff --git a/src/libspucc/xine_cc_decoder.c b/src/libspucc/xine_cc_decoder.c index 9cdb4c4ea..47c1d1f2f 100644 --- a/src/libspucc/xine_cc_decoder.c +++ b/src/libspucc/xine_cc_decoder.c @@ -1,25 +1,29 @@ /* - * Copyright (C) 2000-2003 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * closed caption spu decoder. receive data by events. + * closed caption spu decoder. receive data by events. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -33,11 +37,17 @@ #define LOG_DEBUG 1 */ +const char *cc_schemes[NUM_CC_PALETTES + 1] = { + "White/Gray/Translucent", + "White/Black/Solid", + NULL +}; + typedef struct spucc_decoder_s { spu_decoder_t spu_decoder; xine_stream_t *stream; - + /* closed captioning decoder state */ cc_decoder_t *ccdec; /* true if ccdec has been initialized */ @@ -54,7 +64,7 @@ typedef struct spucc_decoder_s { /* events will be sent here */ xine_event_queue_t *queue; - + } spucc_decoder_t; @@ -147,7 +157,7 @@ static void spucc_font_change(void *this_gen, xine_cfg_entry_t *value) spucc_class_t *this = (spucc_class_t *) this_gen; cc_config_t *cc_cfg = &this->cc_cfg; char *font; - + if (strcmp(value->key, "subtitles.closedcaption.font") == 0) font = cc_cfg->font; else @@ -166,7 +176,7 @@ static void spucc_num_change(void *this_gen, xine_cfg_entry_t *value) spucc_class_t *this = (spucc_class_t *) this_gen; cc_config_t *cc_cfg = &this->cc_cfg; int *num; - + if (strcmp(value->key, "subtitles.closedcaption.font_size") == 0) num = &cc_cfg->font_size; else @@ -190,35 +200,35 @@ static void spucc_register_cfg_vars(spucc_class_t *this, _("Closed Captions are subtitles mostly meant " "to help the hearing impaired."), 0, spucc_cfg_enable_change, this); - + cc_vars->cc_scheme = xine_cfg->register_enum(xine_cfg, "subtitles.closedcaption.scheme", 0, - cc_schemes, + (char **)cc_schemes, _("closed-captioning foreground/background scheme"), _("Choose your favourite rendering of the closed " "captions."), 10, spucc_cfg_scheme_change, this); - - copy_str(cc_vars->font, + + copy_str(cc_vars->font, xine_cfg->register_string(xine_cfg, "subtitles.closedcaption.font", "cc", _("standard closed captioning font"), _("Choose the font for standard closed captions text."), 20, spucc_font_change, this), CC_FONT_MAX); - + copy_str(cc_vars->italic_font, xine_cfg->register_string(xine_cfg, "subtitles.closedcaption.italic_font", "cci", _("italic closed captioning font"), _("Choose the font for italic closed captions text."), 20, spucc_font_change, this), CC_FONT_MAX); - + cc_vars->font_size = xine_cfg->register_num(xine_cfg, "subtitles.closedcaption.font_size", 24, _("closed captioning font size"), _("Choose the font size for closed captions text."), 10, spucc_num_change, this); - + cc_vars->center = xine_cfg->register_bool(xine_cfg, "subtitles.closedcaption.center", 1, _("center-adjust closed captions"), _("When enabled, closed captions will be positioned " @@ -228,7 +238,7 @@ static void spucc_register_cfg_vars(spucc_class_t *this, /* called when the video frame size changes */ -static void spucc_notify_frame_change(spucc_decoder_t *this, +static void spucc_notify_frame_change(spucc_decoder_t *this, int width, int height) { #ifdef LOG_DEBUG printf("spucc: new frame size: %dx%d\n", width, height); @@ -245,14 +255,14 @@ static void spucc_notify_frame_change(spucc_decoder_t *this, static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { spucc_decoder_t *this = (spucc_decoder_t *) this_gen; xine_event_t *event; - + while ((event = xine_event_get(this->queue))) { switch (event->type) { case XINE_EVENT_FRAME_FORMAT_CHANGE: { - xine_format_change_data_t *frame_change = + xine_format_change_data_t *frame_change = (xine_format_change_data_t *)event->data; - + spucc_notify_frame_change(this, frame_change->width, frame_change->height); } @@ -260,17 +270,17 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } xine_event_free(event); } - + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { } else { - + if (this->cc_state.cc_cfg->config_version > this->config_version) { spucc_update_intrinsics(this); if (!this->cc_state.cc_cfg->cc_enabled) spucc_do_close(this); this->config_version = this->cc_state.cc_cfg->config_version; } - + if (this->cc_state.cc_cfg->cc_enabled) { if( !this->cc_open ) spucc_do_init (this); @@ -280,7 +290,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } } } -} +} static void spudec_reset (spu_decoder_t *this_gen) { } @@ -301,7 +311,7 @@ static spu_decoder_t *spudec_open_plugin (spu_decoder_class_t *class, xine_strea spucc_decoder_t *this ; - this = (spucc_decoder_t *) xine_xmalloc (sizeof (spucc_decoder_t)); + this = (spucc_decoder_t *) calloc(1, sizeof(spucc_decoder_t)); this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -317,7 +327,7 @@ static spu_decoder_t *spudec_open_plugin (spu_decoder_class_t *class, xine_strea this->cc_open = 0; cc_decoder_init(); - + return &this->spu_decoder; } @@ -338,7 +348,7 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { spucc_class_t *this ; - this = (spucc_class_t *) xine_xmalloc (sizeof (spucc_class_t)); + this = (spucc_class_t *) calloc(1, sizeof(spucc_class_t)); this->spu_class.open_plugin = spudec_open_plugin; this->spu_class.get_identifier = spudec_get_identifier; @@ -347,7 +357,7 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { spucc_register_cfg_vars(this, xine->config); this->cc_cfg.config_version = 0; - + return &this->spu_class; } @@ -360,7 +370,7 @@ static const decoder_info_t spudec_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_SPU_DECODER, 16, "spucc", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libspucmml/Makefile.am b/src/libspucmml/Makefile.am index 81e8d3623..53a980b57 100644 --- a/src/libspucmml/Makefile.am +++ b/src/libspucmml/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spucmml.la diff --git a/src/libspucmml/xine_cmml_decoder.c b/src/libspucmml/xine_cmml_decoder.c index b684d21cb..ed7e99ae1 100644 --- a/src/libspucmml/xine_cmml_decoder.c +++ b/src/libspucmml/xine_cmml_decoder.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2003 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -88,14 +88,13 @@ static void video_frame_format_change_callback (void *user_data, const xine_even static void update_font_size (spucmml_decoder_t *this) { - static int sizes[SUBTITLE_SIZE_NUM][4] = { + static const int sizes[SUBTITLE_SIZE_NUM][4] = { { 16, 16, 16, 20 }, /* SUBTITLE_SIZE_SMALL */ { 16, 16, 20, 24 }, /* SUBTITLE_SIZE_NORMAL */ { 16, 20, 24, 32 }, /* SUBTITLE_SIZE_LARGE */ }; - int *vec = sizes[this->subtitle_size]; - int y; + const int *const vec = sizes[this->subtitle_size]; if( this->cached_width >= 512 ) this->font_size = vec[3]; @@ -105,11 +104,11 @@ static void update_font_size (spucmml_decoder_t *this) { this->font_size = vec[1]; else this->font_size = vec[0]; - + this->line_height = this->font_size + 10; - y = this->cached_height - (SUB_MAX_TEXT * this->line_height) - 5; - + int y = this->cached_height - (SUB_MAX_TEXT * this->line_height) - 5; + if(((y - this->vertical_offset) >= 0) && ((y - this->vertical_offset) <= this->cached_height)) y -= this->vertical_offset; @@ -125,7 +124,7 @@ static void update_font_size (spucmml_decoder_t *this) { this->cached_width, SUB_MAX_TEXT * this->line_height); - this->osd = this->stream->osd_renderer->new_object (this->stream->osd_renderer, + this->osd = this->stream->osd_renderer->new_object (this->stream->osd_renderer, this->cached_width, SUB_MAX_TEXT * this->line_height); llprintf (LOG_OSD, "post new_object: osd is %p\n", this->osd); @@ -137,83 +136,80 @@ static void update_font_size (spucmml_decoder_t *this) { } static int get_width(spucmml_decoder_t *this, char* text) { - size_t i=0; - int width=0,w,dummy; - char letter[2]={0, 0}; + int width=0; + + while (1) + switch (*text) { + case '\0': + llprintf(LOG_WIDTH, "get_width returning width of %d\n", width); + return width; - while (i<=strlen(text)) { - switch (text[i]) { case '<': - if (!strncmp("<b>", text+i, 3)) { + if (!strncmp("<b>", text, 3)) { /*Do somethink to enable BOLD typeface*/ - i=i+3; + text += 3; break; - } else if (!strncmp("</b>", text+i, 3)) { + } else if (!strncmp("</b>", text, 3)) { /*Do somethink to disable BOLD typeface*/ - i=i+4; + text += 4; break; - } else if (!strncmp("<i>", text+i, 3)) { + } else if (!strncmp("<i>", text, 3)) { /*Do somethink to enable italics typeface*/ - i=i+3; + text += 3; break; - } else if (!strncmp("</i>", text+i, 3)) { + } else if (!strncmp("</i>", text, 3)) { /*Do somethink to disable italics typeface*/ - i=i+4; + text += 4; break; - } else if (!strncmp("<font>", text+i, 3)) { + } else if (!strncmp("<font>", text, 3)) { /*Do somethink to disable typing fixme - no teststreams*/ - i=i+6; + text += 6; break; - } else if (!strncmp("</font>", text+i, 3)) { + } else if (!strncmp("</font>", text, 3)) { /*Do somethink to enable typing fixme - no teststreams*/ - i=i+7; + text += 7; break; - } + } default: - letter[0]=text[i]; - this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); - width=width+w; - i++; + { + int w, dummy; + const char letter[2] = { *text, '\0' }; + this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); + width += w; + text++; + } } - } - - llprintf(LOG_WIDTH, "get_width returning width of %d\n", width); - - return width; } static void render_line(spucmml_decoder_t *this, int x, int y, char* text) { - size_t i=0; - int w,dummy; - char letter[2]={0,0}; + while (*text != '\0') { + int w, dummy; + const char letter[2] = { *text, '\0' }; - while (i<=strlen(text)) { - letter[0]=text[i]; this->stream->osd_renderer->render_text(this->osd, x, y, letter, OSD_TEXT1); this->stream->osd_renderer->get_text_size(this->osd, letter, &w, &dummy); - x=x+w; - i++; + x += w; + text++; } } static void draw_subtitle(spucmml_decoder_t *this, int64_t sub_start) { - int line, y; - int font_size; - this->stream->osd_renderer->filled_rect (this->osd, 0, 0, this->cached_width-1, this->line_height * SUB_MAX_TEXT - 1, 0); - y = (SUB_MAX_TEXT - this->lines) * this->line_height; - font_size = this->font_size; + const int y = (SUB_MAX_TEXT - this->lines) * this->line_height; + int font_size = this->font_size; this->stream->osd_renderer->set_encoding(this->osd, this->class->src_encoding); + int line; + for (line=0; line<this->lines; line++) { - int w,x; + int x; while(1) { - w=get_width( this, this->text[line]); + const int w = get_width( this, this->text[line]); x = (this->cached_width - w) / 2; if( w > this->cached_width && font_size > 16 ) { @@ -228,11 +224,11 @@ static void draw_subtitle(spucmml_decoder_t *this, int64_t sub_start) { if( font_size != this->font_size ) this->stream->osd_renderer->set_font (this->osd, this->font, this->font_size); - + this->stream->osd_renderer->set_text_palette (this->osd, -1, OSD_TEXT1); this->stream->osd_renderer->show (this->osd, sub_start); - + llprintf (LOG_SCHEDULING, "spucmml: scheduling subtitle >%s< at %"PRId64", current time is %"PRId64"\n", this->text[0], sub_start, @@ -242,23 +238,26 @@ static void draw_subtitle(spucmml_decoder_t *this, int64_t sub_start) { static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; - char *str; + xml_parser_t *xml_parser; xml_node_t *packet_xml_root; char * anchor_text = NULL; lprintf("CMML packet seen\n"); - str = (char *) buf->content; + char *str = (char *) buf->content; /* parse the CMML */ - xml_parser_init (str, strlen (str), XML_PARSER_CASE_INSENSITIVE); - if (xml_parser_build_tree(&packet_xml_root) != XML_PARSER_OK) { + xml_parser = xml_parser_init_r (str, strlen (str), XML_PARSER_CASE_INSENSITIVE); + if (xml_parser_build_tree_r(xml_parser, &packet_xml_root) != XML_PARSER_OK) { lprintf ("warning: invalid XML packet detected in CMML track\n"); + xml_parser_finalize_r(xml_parser); return; } + xml_parser_finalize_r(xml_parser); + if (strcasecmp(packet_xml_root->name, "head") == 0) { /* found a <head>...</head> packet: need to parse the title */ @@ -268,36 +267,30 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { for (title_node = packet_xml_root->child; title_node != NULL; title_node = title_node->next) { - if (strcasecmp (title_node->name, "title") == 0) { + if (title_node->data && + strcasecmp (title_node->name, "title") == 0) { /* found a title node */ - xine_event_t uevent; - char *title; - int title_len; - - title = title_node->data; - - if (title) - { - xine_ui_data_t data; - /* found a non-empty title */ - lprintf ("found title: \"%s\"\n", title); - - /* set xine meta-info */ - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, strdup(title)); - - /* and push out a new event signifying the title update on the event - * queue */ - title_len = strlen(title) + 1; - memcpy(data.str, title, title_len); - data.str_len = title_len; - - uevent.type = XINE_EVENT_UI_SET_TITLE; - uevent.stream = this->stream; - uevent.data = &data; - uevent.data_length = sizeof(data); - xine_event_send(this->stream, &uevent); - } + xine_ui_data_t data = { + .str_len = strlen(title_node->data) + 1 + }; + xine_event_t uevent = { + .type = XINE_EVENT_UI_SET_TITLE, + .stream = this->stream, + .data = &data, + .data_length = sizeof(data), + }; + strncpy(data.str, title_node->data, sizeof(data.str)-1); + + /* found a non-empty title */ + lprintf ("found title: \"%s\"\n", data.str); + + /* set xine meta-info */ + _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, strdup(data.str)); + + /* and push out a new event signifying the title update on the event + * queue */ + xine_event_send(this->stream, &uevent); } } } else if (strcasecmp(packet_xml_root->name, "clip") == 0) { @@ -406,7 +399,7 @@ static void video_frame_format_change_callback (void *user_data, const xine_even static void spudec_reset (spu_decoder_t *this_gen) { spucmml_decoder_t *this = (spucmml_decoder_t *) this_gen; - + this->cached_width = this->cached_height = 0; } @@ -446,11 +439,8 @@ static void update_osd_font(void *this_gen, xine_cfg_entry_t *entry) } static spu_decoder_t *spucmml_class_open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) { - spucmml_class_t *class = (spucmml_class_t *)class_gen; - spucmml_decoder_t *this ; - - this = (spucmml_decoder_t *) xine_xmalloc (sizeof (spucmml_decoder_t)); + spucmml_decoder_t *this = (spucmml_decoder_t *) calloc(1, sizeof(spucmml_decoder_t)); this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -471,16 +461,16 @@ static spu_decoder_t *spucmml_class_open_plugin (spu_decoder_class_t *class_gen, this->font_size = 24; this->subtitle_size = 1; - this->font = class->xine->config->register_string(class->xine->config, - "subtitles.separate.font", - "sans", - _("font for external subtitles"), + this->font = class->xine->config->register_string(class->xine->config, + "subtitles.separate.font", + "sans", + _("font for external subtitles"), NULL, 0, update_osd_font, this); this->vertical_offset = class->xine->config->register_num(class->xine->config, - "subtitles.separate.vertical_offset", + "subtitles.separate.vertical_offset", 0, - _("subtitle vertical offset (relative window size)"), + _("subtitle vertical offset (relative window size)"), NULL, 0, update_vertical_offset, this); this->current_anchor.href = NULL; @@ -511,10 +501,7 @@ static void update_src_encoding(void *this_gen, xine_cfg_entry_t *entry) } static void *init_spu_decoder_plugin (xine_t *xine, void *data) { - - spucmml_class_t *this ; - - this = (spucmml_class_t *) xine_xmalloc (sizeof (spucmml_class_t)); + spucmml_class_t *this = (spucmml_class_t *) calloc(1, sizeof(spucmml_class_t)); this->class.open_plugin = spucmml_class_open_plugin; this->class.get_identifier = spucmml_class_get_identifier; @@ -523,10 +510,10 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { this->xine = xine; - this->src_encoding = xine->config->register_string(xine->config, - "subtitles.separate.src_encoding", - "iso-8859-1", - _("encoding of subtitles"), + this->src_encoding = xine->config->register_string(xine->config, + "subtitles.separate.src_encoding", + "iso-8859-1", + _("encoding of subtitles"), NULL, 10, update_src_encoding, this); return &this->class; @@ -542,7 +529,7 @@ static const decoder_info_t spudec_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_SPU_DECODER, 16, "spucmml", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libspudec/Makefile.am b/src/libspudec/Makefile.am index 208d994f5..061bd7731 100644 --- a/src/libspudec/Makefile.am +++ b/src/libspudec/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spu.la @@ -7,7 +8,7 @@ if HAVE_DVDNAV xineplug_decode_spu_la_SOURCES = \ spu.c \ xine_spu_decoder.c -xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(DVDNAV_LIBS) $(PTHREAD_LIBS) +xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(DVDNAV_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) else @@ -16,7 +17,7 @@ xineplug_decode_spu_la_SOURCES = \ spu.c \ xine_spu_decoder.c AM_CPPFLAGS = -I$(top_srcdir)/src/input/libdvdnav -xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) +xineplug_decode_spu_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) endif diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c index ce3497ef0..a9319f103 100644 --- a/src/libspudec/spu.c +++ b/src/libspudec/spu.c @@ -17,13 +17,13 @@ * cleaner implementation of SPU are saving * overlaying (proof of concept for now) * ... and yes, it works now with oms - * added tranparency (provided by the SPU hdr) + * added tranparency (provided by the SPU hdr) * changed structures for easy porting to MGAs DVD mode * This file is part of xine * This file was originally part of the OMS program. * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * @@ -37,6 +37,10 @@ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <errno.h> @@ -85,7 +89,7 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { p = buf->content; if (p[0] || p[1] || (p[2] != 1)) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libspudec:spudec_decode_nav:nav demux error! %02x %02x %02x (should be 0x000001) \n",p[0],p[1],p[2]); return; } @@ -122,7 +126,7 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { printf("btngr%d_dsp_ty 0x%02x\n", 1, pci.hli.hl_gi.btngr1_dsp_ty); printf("btngr%d_dsp_ty 0x%02x\n", 2, pci.hli.hl_gi.btngr2_dsp_ty); printf("btngr%d_dsp_ty 0x%02x\n", 3, pci.hli.hl_gi.btngr3_dsp_ty); - //navPrint_PCI(&pci); + //navPrint_PCI(&pci); //navPrint_PCI_GI(&pci.pci_gi); //navPrint_NSML_AGLI(&pci.nsml_agli); //navPrint_HLI(&pci.hli); @@ -138,7 +142,7 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { packet_len = p[4] << 8 | p[5]; p += 6; #ifdef LOG_NAV - printf("NAV DSI packet\n"); + printf("NAV DSI packet\n"); #endif navRead_DSI(&dsi, p+1); @@ -146,7 +150,7 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { // self->vobu_length = self->dsi.dsi_gi.vobu_ea; } } - + /* NAV packets contain start and end presentation timestamps, which tell the * application, when the highlight information in the NAV is supposed to be valid. * We handle these timestamps only in a very stripped-down way: We keep a list @@ -188,18 +192,18 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { /* we possibly had buttons before, so we update the UI info */ xine_event_t event; xine_ui_data_t data; - + event.type = XINE_EVENT_UI_NUM_BUTTONS; event.data = &data; event.data_length = sizeof(data); data.num_buttons = 0; - + xine_event_send(this->stream, &event); } this->button_filter=0; break; - case 1: + case 1: /* All New Highlight information for this VOBU */ if (this->pci_cur.pci.hli.hl_gi.hli_ss != 0 && pci.hli.hl_gi.hli_s_ptm > this->pci_cur.pci.hli.hl_gi.hli_s_ptm) { @@ -209,7 +213,7 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { #endif /* append PCI at the end of the list */ while (node->next) node = node->next; - node->next = (pci_node_t *)xine_xmalloc(sizeof(pci_node_t)); + node->next = malloc(sizeof(pci_node_t)); node->next->vpts = this->stream->metronom->got_spu_packet(this->stream->metronom, pci.hli.hl_gi.hli_s_ptm); node->next->next = NULL; xine_fast_memcpy(&node->next->pci, &pci, sizeof(pci_t)); @@ -255,7 +259,7 @@ void spudec_decode_nav(spudec_decoder_t *this, buf_element_t *buf) { } break; default: - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libspudec: unknown pci.hli.hl_gi.hli_ss = %d\n", pci.hli.hl_gi.hli_ss ); break; } @@ -277,7 +281,7 @@ void spudec_clear_nav_list(spudec_decoder_t *this) void spudec_update_nav(spudec_decoder_t *this) { metronom_clock_t *clock = this->stream->xine->clock; - + if (this->pci_cur.next && this->pci_cur.next->vpts <= clock->get_current_time(clock)) { pci_node_t *node = this->pci_cur.next; xine_fast_memcpy(&this->pci_cur, this->pci_cur.next, sizeof(pci_node_t)); @@ -294,12 +298,12 @@ void spudec_process_nav(spudec_decoder_t *this) /* we possibly entered a menu, so we update the UI button info */ xine_event_t event; xine_ui_data_t data; - + event.type = XINE_EVENT_UI_NUM_BUTTONS; event.data = &data; event.data_length = sizeof(data); data.num_buttons = this->pci_cur.pci.hli.hl_gi.btn_ns; - + xine_event_send(this->stream, &event); } this->button_filter=1; @@ -318,7 +322,7 @@ void spudec_reassembly (xine_t *xine, spudec_seq_t *seq, uint8_t *pkt_data, u_in if (seq->complete) { seq->seq_len = (((uint32_t)pkt_data[0])<<8) | pkt_data[1]; seq->cmd_offs = (((uint32_t)pkt_data[2])<<8) | pkt_data[3]; - if (seq->cmd_offs >= seq->seq_len) { + if (seq->cmd_offs >= seq->seq_len) { xprintf(xine, XINE_VERBOSITY_DEBUG, "libspudec:faulty stream\n"); seq->broken = 1; } @@ -338,7 +342,7 @@ void spudec_reassembly (xine_t *xine, spudec_seq_t *seq, uint8_t *pkt_data, u_in } seq->ra_offs = 0; - + #ifdef LOG_DEBUG printf ("spu: buf_len: %d\n", seq->buf_len); printf ("spu: cmd_off: %d\n", seq->cmd_offs); @@ -360,7 +364,7 @@ void spudec_reassembly (xine_t *xine, spudec_seq_t *seq, uint8_t *pkt_data, u_in } else { xprintf(xine, XINE_VERBOSITY_DEBUG, "libspudec:faulty stream\n"); seq->broken = 1; - } + } if (seq->ra_offs == seq->seq_len) { seq->finished = 0; @@ -378,9 +382,9 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { cur_seq = &this->spudec_stream_state[stream_id].ra_seq; #ifdef LOG_DEBUG - printf ("spu: Found SPU from stream %d pts=%lli vpts=%lli\n",stream_id, + printf ("spu: Found SPU from stream %d pts=%lli vpts=%lli\n",stream_id, this->spudec_stream_state[stream_id].pts, - this->spudec_stream_state[stream_id].vpts); + this->spudec_stream_state[stream_id].vpts); #endif this->state.cmd_ptr = cur_seq->buf + cur_seq->cmd_offs; this->state.modified = 1; /* Only draw picture if = 1 on first event of SPU */ @@ -388,14 +392,14 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { this->state.forced_display = 0; /* 0 - No value, 1 - Forced Display. */ this->state.delay = 0; cur_seq->finished=0; - + do { if (!(cur_seq->finished) ) { pci_node_t *node; - + /* spu_channel is now set based on whether we are in the menu or not. */ /* Bit 7 is set if only forced display SPUs should be shown */ - if ( (this->stream->spu_channel & 0x1f) != stream_id ) { + if ( (this->stream->spu_channel & 0x1f) != stream_id ) { #ifdef LOG_DEBUG printf ("spu: Dropping SPU channel %d. Not selected stream_id\n", stream_id); #endif @@ -413,7 +417,7 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { cur_seq->broken = 0; return; } - if ( (this->state.forced_display == 0) && (this->stream->spu_channel & 0x80) ) { + if ( (this->state.forced_display == 0) && (this->stream->spu_channel & 0x80) ) { #ifdef LOG_DEBUG printf ("spu: Dropping SPU channel %d. Only allow forced display SPUs\n", stream_id); #endif @@ -422,7 +426,7 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { #ifdef LOG_DEBUG spudec_print_overlay( &this->overlay ); - printf ("spu: forced display:%s\n", this->state.forced_display ? "Yes" : "No" ); + printf ("spu: forced display:%s\n", this->state.forced_display ? "Yes" : "No" ); #endif pthread_mutex_lock(&this->nav_pci_lock); /* search for a PCI that matches this SPU's PTS */ @@ -440,7 +444,7 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { } if (node->pci.hli.hl_gi.fosl_btnn > 0) { xine_event_t event; - + this->buttonN = node->pci.hli.hl_gi.fosl_btnn; event.type = XINE_EVENT_INPUT_BUTTON_FORCE; event.stream = this->stream; @@ -451,12 +455,12 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { #ifdef LOG_BUTTON fprintf(stderr, "libspudec:Full Overlay\n"); #endif - if (!spudec_copy_nav_to_overlay(this->stream->xine, - &node->pci, this->state.clut, + if (!spudec_copy_nav_to_overlay(this->stream->xine, + &node->pci, this->state.clut, this->buttonN, 0, &this->overlay, &this->overlay)) { /* current button does not exist -> use another one */ xine_event_t event; - + if (this->buttonN > node->pci.hli.hl_gi.btn_ns) this->buttonN = node->pci.hli.hl_gi.btn_ns; else @@ -466,8 +470,8 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { event.data = &this->buttonN; event.data_length = sizeof(this->buttonN); xine_event_send(this->stream, &event); - spudec_copy_nav_to_overlay(this->stream->xine, - &node->pci, this->state.clut, + spudec_copy_nav_to_overlay(this->stream->xine, + &node->pci, this->state.clut, this->buttonN, 0, &this->overlay, &this->overlay); } } else { @@ -480,44 +484,44 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { } pthread_mutex_unlock(&this->nav_pci_lock); - if ((this->state.modified) ) { + if ((this->state.modified) ) { spudec_draw_picture(this->stream->xine, &this->state, cur_seq, &this->overlay); } - + if (this->state.need_clut) { spudec_discover_clut(this->stream->xine, &this->state, &this->overlay); } - + if (this->state.vobsub) { int width, height; int64_t duration; - + /* * vobsubs are usually played with a scaled-down stream (not full DVD * resolution), therefore we should try to realign it. */ - + this->stream->video_out->status(this->stream->video_out, NULL, &width, &height, &duration ); this->overlay.x = (width - this->overlay.width) / 2; this->overlay.y = height - this->overlay.height; } - + /* Subtitle */ if( this->menu_handle < 0 ) { this->menu_handle = ovl_manager->get_handle(ovl_manager,1); } - + if( this->menu_handle < 0 ) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libspudec: No video_overlay handles left for menu\n"); return; } this->event.object.handle = this->menu_handle; this->event.object.pts = this->spudec_stream_state[stream_id].pts; - xine_fast_memcpy(this->event.object.overlay, + xine_fast_memcpy(this->event.object.overlay, &this->overlay, sizeof(vo_overlay_t)); this->overlay.rle=NULL; @@ -525,15 +529,15 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { //if ( !(this->state.visible) ) { // this->state.visible = OVERLAY_EVENT_SHOW; //} - + this->event.event_type = this->state.visible; /* printf("spu event %d handle: %d vpts: %lli\n", this->event.event_type, - this->event.object.handle, this->event.vpts ); + this->event.object.handle, this->event.vpts ); */ - - this->event.vpts = this->spudec_stream_state[stream_id].vpts+(this->state.delay*1000); - + + this->event.vpts = this->spudec_stream_state[stream_id].vpts+(this->state.delay*1000); + /* Keep all the events in the correct order. */ /* This corrects for errors during estimation around discontinuity */ if( this->event.vpts < this->last_event_vpts ) { @@ -546,7 +550,7 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { this->event.event_type, this->stream->xine->clock->get_current_time(this->stream->xine->clock), this->event.vpts); -#endif +#endif ovl_manager->add_event(ovl_manager, (void *)&this->event); } else { pending = 0; @@ -574,7 +578,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t #ifdef LOG_DEBUG printf ("spu: SPU DO COMMANDS\n"); #endif - + state->delay = (buf[0] << 8) + buf[1]; #ifdef LOG_DEBUG printf ("spu: \tdelay=%d\n",state->delay); @@ -591,7 +595,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t next_seq = seq->buf + seq->seq_len; /* allow to run until end */ state->cmd_ptr = next_seq; - + while (buf < next_seq && *buf != CMD_SPU_EOF) { switch (*buf) { case CMD_SPU_SHOW: /* show subpicture */ @@ -601,7 +605,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t state->visible = OVERLAY_EVENT_SHOW; buf++; break; - + case CMD_SPU_HIDE: /* hide subpicture */ #ifdef LOG_DEBUG printf ("spu: \thide subpicture\n"); @@ -609,17 +613,17 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t state->visible = OVERLAY_EVENT_HIDE; buf++; break; - + case CMD_SPU_SET_PALETTE: { /* CLUT */ spudec_clut_t *clut = (spudec_clut_t *) (buf+1); - + state->cur_colors[3] = clut->entry0; state->cur_colors[2] = clut->entry1; state->cur_colors[1] = clut->entry2; state->cur_colors[0] = clut->entry3; /* This is a bit out of context for now */ - ovl->color[3] = state->clut[clut->entry0]; + ovl->color[3] = state->clut[clut->entry0]; ovl->color[2] = state->clut[clut->entry1]; ovl->color[1] = state->clut[clut->entry2]; ovl->color[0] = state->clut[clut->entry3]; @@ -633,11 +637,11 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t state->modified = 1; buf += 3; break; - } + } case CMD_SPU_SET_ALPHA: { /* transparency palette */ spudec_clut_t *trans = (spudec_clut_t *) (buf+1); /* This should go into state for now */ - + ovl->trans[3] = trans->entry0; ovl->trans[2] = trans->entry1; ovl->trans[1] = trans->entry2; @@ -651,7 +655,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t buf += 3; break; } - + case CMD_SPU_SET_SIZE: /* image coordinates */ /* state->o_left = (buf[1] << 4) | (buf[2] >> 4); state->o_right = (((buf[2] & 0x0f) << 8) | buf[3]); @@ -661,7 +665,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t */ ovl->x = (buf[1] << 4) | (buf[2] >> 4); ovl->y = (buf[4] << 4) | (buf[5] >> 4); - ovl->width = (((buf[2] & 0x0f) << 8) | buf[3]) - ovl->x + 1; + ovl->width = (((buf[2] & 0x0f) << 8) | buf[3]) - ovl->x + 1; ovl->height = (((buf[5] & 0x0f) << 8) | buf[6]) - ovl->y + 1; ovl->hili_top = -1; ovl->hili_bottom = -1; @@ -675,7 +679,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t state->modified = 1; buf += 7; break; - + case CMD_SPU_SET_PXD_OFFSET: /* image top[0] field / image bottom[1] field*/ state->field_offs[0] = (((u_int)buf[1]) << 8) | buf[2]; state->field_offs[1] = (((u_int)buf[3]) << 8) | buf[4]; @@ -693,13 +697,13 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t state->modified = 1; buf += 5; break; - + case CMD_SPU_WIPE: #ifdef LOG_DEBUG printf ("libspudec: \tSPU_WIPE not implemented yet\n"); #endif param_length = (buf[1] << 8) | (buf[2]); - buf += 1 + param_length; + buf += 1 + param_length; break; case CMD_SPU_FORCE_DISPLAY: @@ -718,7 +722,7 @@ static void spudec_do_commands(xine_t *xine, spudec_state_t *state, spudec_seq_t break; } } - + if (next_seq >= seq->buf + seq->seq_len) seq->finished = 1; /* last sub-sequence */ } @@ -759,11 +763,11 @@ static u_int get_bits (u_int bits) static int spudec_next_line (vo_overlay_t *spu) { get_bits (0); // byte align rle data - + put_x = 0; put_y++; field ^= 1; // Toggle fields - + if (put_y >= spu->height) { #ifdef LOG_DEBUG printf ("spu: put_y >= spu->height\n"); @@ -797,11 +801,11 @@ static void spudec_draw_picture (xine_t *xine, spudec_state_t *state, spudec_seq * - both fields running to the very end * - 2 RLE elements per byte meaning single pixel RLE */ - ovl->data_size = ((seq->cmd_offs - state->field_offs[0]) + + ovl->data_size = ((seq->cmd_offs - state->field_offs[0]) + (seq->cmd_offs - state->field_offs[1])) * 2 * sizeof(rle_elem_t); if (ovl->rle) { - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (xine, XINE_VERBOSITY_DEBUG, "libspudec: spudec_draw_picture: ovl->rle is not empty!!!! It should be!!! " "You should never see this message.\n"); free(ovl->rle); @@ -886,7 +890,7 @@ static void spudec_discover_clut(xine_t *xine, spudec_state_t *state, vo_overlay why rle is null? */ if( !rle ) return; - + /* suppose the first and last pixels are bg */ if( rle[0].color != rle[ovl->num_rle-1].color ) return; @@ -972,9 +976,9 @@ int spudec_copy_nav_to_overlay(xine_t *xine, pci_t* nav_pci, uint32_t* clut, if((button <= 0) || (button > nav_pci->hli.hl_gi.btn_ns)) return 0; - + btns_per_group = 36 / nav_pci->hli.hl_gi.btngr_ns; - + /* choose button group: we can always use a normal 4:3 or widescreen button group * as long as xine blends the overlay before scaling the image to its aspect */ if (!button_ptr && nav_pci->hli.hl_gi.btngr_ns >= 1 && !(nav_pci->hli.hl_gi.btngr1_dsp_ty & 6)) @@ -984,11 +988,11 @@ int spudec_copy_nav_to_overlay(xine_t *xine, pci_t* nav_pci, uint32_t* clut, if (!button_ptr && nav_pci->hli.hl_gi.btngr_ns >= 3 && !(nav_pci->hli.hl_gi.btngr3_dsp_ty & 6)) button_ptr = &nav_pci->hli.btnit[2 * btns_per_group + button - 1]; if (!button_ptr) { - xprintf(xine, XINE_VERBOSITY_DEBUG, + xprintf(xine, XINE_VERBOSITY_DEBUG, "libspudec: No suitable menu button group found, using group 1.\n"); button_ptr = &nav_pci->hli.btnit[button - 1]; } - + /* button areas in the nav packet are in screen coordinates, * overlay clipping areas are in overlay coordinates; * therefore we must subtract the display coordinates of the underlying overlay */ @@ -1021,6 +1025,6 @@ int spudec_copy_nav_to_overlay(xine_t *xine, pci_t* nav_pci, uint32_t* clut, #ifdef LOG_BUTTON printf("libspudec:xine_decoder.c:NAV to SPU pts match!\n"); #endif - + return 1; } diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h index 8d92146f0..54efe1968 100644 --- a/src/libspudec/spu.h +++ b/src/libspudec/spu.h @@ -4,17 +4,17 @@ * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -26,7 +26,7 @@ #define __SPU_H__ #ifdef HAVE_CONFIG_H -#include <config.h> +#include "config.h" #endif #include <inttypes.h> @@ -112,11 +112,11 @@ typedef struct spudec_decoder_s { spudec_class_t *class; xine_stream_t *stream; spudec_stream_state_t spudec_stream_state[MAX_STREAMS]; - + video_overlay_event_t event; - video_overlay_object_t object; + video_overlay_object_t object; int32_t menu_handle; - + spudec_state_t state; vo_overlay_t overlay; diff --git a/src/libspudec/xine_spu_decoder.c b/src/libspudec/xine_spu_decoder.c index 0ab91d906..1f40dbb27 100644 --- a/src/libspudec/xine_spu_decoder.c +++ b/src/libspudec/xine_spu_decoder.c @@ -1,20 +1,20 @@ /* - * Copyright (C) 2000-2004 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -22,6 +22,10 @@ * stuff needed to turn libspu into a xine decoder plugin */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> @@ -68,11 +72,8 @@ static const clut_t default_clut[] = { }; static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { - uint32_t stream_id; - spudec_seq_t *cur_seq; spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - stream_id = buf->type & 0x1f ; - cur_seq = &this->spudec_stream_state[stream_id].ra_seq; + const uint8_t stream_id = buf->type & 0x1f ; #ifdef LOG_DEBUG printf("libspudec:got buffer type = %x\n", buf->type); @@ -84,7 +85,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { pthread_mutex_unlock(&this->nav_pci_lock); if ( (buf->type & 0xffff0000) != BUF_SPU_DVD || - !(buf->decoder_flags & BUF_FLAG_SPECIAL) || + !(buf->decoder_flags & BUF_FLAG_SPECIAL) || buf->decoder_info[1] != BUF_SPECIAL_SPU_DVD_SUBTYPE ) return; @@ -103,7 +104,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { this->state.need_clut = 0; return; } - + if ( buf->decoder_info[2] == SPU_DVD_SUBTYPE_NAV ) { #ifdef LOG_DEBUG printf("libspudec:got nav packet 1\n"); @@ -111,11 +112,11 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { spudec_decode_nav(this,buf); return; } - + if ( buf->decoder_info[2] == SPU_DVD_SUBTYPE_VOBSUB_PACKAGE ) { this->state.vobsub = 1; } - + #ifdef LOG_DEBUG printf("libspudec:got buffer type = %x\n", buf->type); #endif @@ -125,14 +126,14 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if (buf->pts) { metronom_t *metronom = this->stream->metronom; int64_t vpts = metronom->got_spu_packet(metronom, buf->pts); - + this->spudec_stream_state[stream_id].vpts = vpts; /* Show timer */ this->spudec_stream_state[stream_id].pts = buf->pts; /* Required to match up with NAV packets */ } spudec_reassembly(this->stream->xine, &this->spudec_stream_state[stream_id].ra_seq, buf->content, buf->size); - if(this->spudec_stream_state[stream_id].ra_seq.complete == 1) { + if(this->spudec_stream_state[stream_id].ra_seq.complete == 1) { if(this->spudec_stream_state[stream_id].ra_seq.broken) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libspudec: dropping broken SPU\n"); this->spudec_stream_state[stream_id].ra_seq.broken = 0; @@ -145,12 +146,12 @@ static void spudec_reset (spu_decoder_t *this_gen) { spudec_decoder_t *this = (spudec_decoder_t *) this_gen; video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out); int i; - + if( this->menu_handle >= 0 ) ovl_manager->free_handle(ovl_manager, this->menu_handle); this->menu_handle = -1; - + for (i=0; i < MAX_STREAMS; i++) { if( this->spudec_stream_state[i].overlay_handle >= 0 ) ovl_manager->free_handle(ovl_manager, @@ -159,7 +160,7 @@ static void spudec_reset (spu_decoder_t *this_gen) { this->spudec_stream_state[i].ra_seq.complete = 1; this->spudec_stream_state[i].ra_seq.broken = 0; } - + pthread_mutex_lock(&this->nav_pci_lock); spudec_clear_nav_list(this); pthread_mutex_unlock(&this->nav_pci_lock); @@ -167,7 +168,7 @@ static void spudec_reset (spu_decoder_t *this_gen) { static void spudec_discontinuity (spu_decoder_t *this_gen) { spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - + pthread_mutex_lock(&this->nav_pci_lock); spudec_clear_nav_list(this); pthread_mutex_unlock(&this->nav_pci_lock); @@ -177,7 +178,6 @@ static void spudec_discontinuity (spu_decoder_t *this_gen) { static void spudec_dispose (spu_decoder_t *this_gen) { spudec_decoder_t *this = (spudec_decoder_t *) this_gen; - int i; video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out); if( this->menu_handle >= 0 ) @@ -185,6 +185,7 @@ static void spudec_dispose (spu_decoder_t *this_gen) { this->menu_handle); this->menu_handle = -1; + int i; for (i=0; i < MAX_STREAMS; i++) { if( this->spudec_stream_state[i].overlay_handle >= 0 ) ovl_manager->free_handle(ovl_manager, @@ -192,7 +193,7 @@ static void spudec_dispose (spu_decoder_t *this_gen) { this->spudec_stream_state[i].overlay_handle = -1; free (this->spudec_stream_state[i].ra_seq.buf); } - + spudec_clear_nav_list(this); pthread_mutex_destroy(&this->nav_pci_lock); @@ -207,9 +208,9 @@ static void spudec_dispose (spu_decoder_t *this_gen) { static int spudec_get_interact_info (spu_decoder_t *this_gen, void *data) { spudec_decoder_t *this = (spudec_decoder_t *) this_gen; /*printf("get_interact_info() called\n");*/ - if (!this || !data) + if (!this || !data) return 0; - + /*printf("get_interact_info() coping nav_pci\n");*/ pthread_mutex_lock(&this->nav_pci_lock); spudec_update_nav(this); @@ -225,11 +226,9 @@ static void spudec_set_button (spu_decoder_t *this_gen, int32_t button, int32_t * when video_overlay does menus */ video_overlay_manager_t *ovl_manager; - video_overlay_event_t *overlay_event = NULL; - vo_overlay_t *overlay = NULL; - overlay_event = xine_xmalloc (sizeof(video_overlay_event_t)); + video_overlay_event_t *overlay_event = calloc(1, sizeof(video_overlay_event_t)); + vo_overlay_t *overlay = calloc(1, sizeof(vo_overlay_t)); - overlay = xine_xmalloc (sizeof(vo_overlay_t)); /* FIXME: Watch out for threads. We should really put a lock on this * because events is a different thread than decode_data */ @@ -244,14 +243,14 @@ static void spudec_set_button (spu_decoder_t *this_gen, int32_t button, int32_t printf ("libspudec:xine_decoder.c:spudec_event_listener:this->menu_handle=%d\n",this->menu_handle); #endif if(this->menu_handle < 0) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "Menu handle alloc failed. No more overlays objects available. Only %d at once please.", MAX_OBJECTS); free(overlay_event); free(overlay); return; } - + if (show > 0) { #ifdef LOG_NAV fprintf (stderr,"libspudec:xine_decoder.c:spudec_event_listener:buttonN = %u show=%d\n", @@ -284,7 +283,7 @@ static void spudec_set_button (spu_decoder_t *this_gen, int32_t button, int32_t this->buttonN, show-1, overlay, &this->overlay ); pthread_mutex_unlock(&this->nav_pci_lock); } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libspudec:xine_decoder.c:spudec_event_listener:HIDE ????\n"); printf("We dropped out here for some reason"); _x_abort(); @@ -313,9 +312,8 @@ static void spudec_set_button (spu_decoder_t *this_gen, int32_t button, int32_t static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) { spudec_decoder_t *this ; - int i; - this = (spudec_decoder_t *) xine_xmalloc (sizeof (spudec_decoder_t)); + this = (spudec_decoder_t *) calloc(1, sizeof (spudec_decoder_t)); this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -328,8 +326,8 @@ static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t this->menu_handle = -1; this->buttonN = 1; - this->event.object.overlay = xine_xmalloc(sizeof(vo_overlay_t)); - + this->event.object.overlay = calloc(1, sizeof(vo_overlay_t)); + pthread_mutex_init(&this->nav_pci_lock, NULL); this->pci_cur.pci.hli.hl_gi.hli_ss = 0; this->pci_cur.next = NULL; @@ -337,6 +335,8 @@ static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t this->ovl_caps = stream->video_out->get_capabilities(stream->video_out); this->output_open = 0; this->last_event_vpts = 0; + + int i; for (i=0; i < MAX_STREAMS; i++) { this->spudec_stream_state[i].ra_seq.complete = 1; this->spudec_stream_state[i].overlay_handle = -1; @@ -376,7 +376,7 @@ static void *init_plugin (xine_t *xine, void *data) { spudec_class_t *this; - this = (spudec_class_t *) xine_xmalloc (sizeof (spudec_class_t)); + this = calloc(1, sizeof (spudec_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -396,7 +396,7 @@ static const decoder_info_t dec_info_data = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_SPU_DECODER, 16, "spudec", XINE_VERSION_CODE, &dec_info_data, &init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libspudvb/Makefile.am b/src/libspudvb/Makefile.am index 310c02f0b..8187346aa 100644 --- a/src/libspudvb/Makefile.am +++ b/src/libspudvb/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xineplug_LTLIBRARIES = xineplug_decode_spudvb.la diff --git a/src/libspudvb/xine_spudvb_decoder.c b/src/libspudvb/xine_spudvb_decoder.c index 602723fcb..694227122 100644 --- a/src/libspudvb/xine_spudvb_decoder.c +++ b/src/libspudvb/xine_spudvb_decoder.c @@ -1,18 +1,18 @@ -/* - * Copyright (C) 2004 the xine project - * +/* + * Copyright (C) 2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -28,59 +28,61 @@ #include "pthread.h" #include <errno.h> #include "xine_internal.h" +#include "bswap.h" #include "osd.h" #define MAX_REGIONS 7 /*#define LOG 1*/ typedef struct { - int x, y; - unsigned char is_visible; + int x, y; + unsigned char is_visible; } visible_region_t; typedef struct { int page_time_out; - int page_version_number; - int page_state; - int page_id; - visible_region_t regions[MAX_REGIONS]; + int page_version_number; + int page_state; + int page_id; + visible_region_t regions[MAX_REGIONS]; } page_t; typedef struct { - int width, height; + int version_number; + int width, height; int empty; - int depth; - int CLUT_id; - int objects_start; + int depth; + int CLUT_id; + int objects_start; int objects_end; - unsigned int object_pos[65536]; - unsigned char *img; + unsigned int object_pos[65536]; + unsigned char *img; osd_object_t *osd; } region_t; typedef struct { /* dvbsub stuff */ - int x; - int y; - unsigned int curr_obj; - unsigned int curr_reg[64]; - uint8_t *buf; - int i; - int nibble_flag; - int in_scanline; - page_t page; - region_t regions[MAX_REGIONS]; + int x; + int y; + unsigned int curr_obj; + unsigned int curr_reg[64]; + uint8_t *buf; + int i; + int nibble_flag; + int in_scanline; + page_t page; + region_t regions[MAX_REGIONS]; clut_t colours[MAX_REGIONS*256]; unsigned char trans[MAX_REGIONS*256]; } dvbsub_func_t; -typedef struct dvb_spu_class_s { - spu_decoder_class_t class; - xine_t *xine; +typedef struct dvb_spu_class_s { + spu_decoder_class_t class; + xine_t *xine; } dvb_spu_class_t; typedef struct dvb_spu_decoder_s { - spu_decoder_t spu_decoder; + spu_decoder_t spu_decoder; dvb_spu_class_t *class; xine_stream_t *stream; @@ -89,21 +91,21 @@ typedef struct dvb_spu_decoder_s { /* dvbsub_osd_mutex should be locked around all calls to this->osd_renderer->show() and this->osd_renderer->hide() */ - pthread_mutex_t dvbsub_osd_mutex; - - char *pes_pkt; + pthread_mutex_t dvbsub_osd_mutex; + + char *pes_pkt; char *pes_pkt_wrptr; - unsigned int pes_pkt_size; - - uint64_t pts; - uint64_t vpts; + unsigned int pes_pkt_size; + + uint64_t pts; + uint64_t vpts; uint64_t end_vpts; - pthread_t dvbsub_timer_thread; + pthread_t dvbsub_timer_thread; struct timespec dvbsub_hide_timeout; pthread_cond_t dvbsub_restart_timeout; dvbsub_func_t *dvbsub; - int show; + int show; } dvb_spu_decoder_t; @@ -140,36 +142,30 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w dvbsub_func_t *dvbsub = this->dvbsub; region_t *reg = &dvbsub->regions[region_id]; - page_t *page = &dvbsub->page; /* reject invalid sizes and set some limits ! */ if ( region_width<=0 || region_height<=0 || region_width>720 || region_height>576 ) { - if ( reg->img ) { - free( reg->img ); - reg->img = NULL; - } + free( reg->img ); + reg->img = NULL; #ifdef LOG printf("SPUDVB: rejected region %d = %dx%d\n", region_id, region_width, region_height ); #endif return; } - if ( reg->width*reg->height<region_width*region_height ) { + if ( (reg->width*reg->height) < (region_width*region_height) ) { #ifdef LOG printf("SPUDVB: update size of region %d = %dx%d\n", region_id, region_width, region_height); #endif - if ( reg->img ) { - free( reg->img ); - reg->img = NULL; - } + free( reg->img ); + reg->img = NULL; } if ( !reg->img ) { - if ( !(reg->img=xine_xmalloc(region_width*region_height)) ) { + if ( !(reg->img=malloc(region_width*region_height)) ) { lprintf( "can't allocate mem for region %d\n", region_id ); return; } - fill_color = 15; fill = 1; } @@ -177,21 +173,19 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w memset( reg->img, fill_color, region_width*region_height ); reg->empty = 1; #ifdef LOG - printf("SPUDVB : FILL REGION %d\n", region_id); + printf("SPUDVB : FILL REGION %d\n", region_id); #endif } reg->width = region_width; reg->height = region_height; - page->regions[region_id].is_visible = 1; } static void do_plot (dvb_spu_decoder_t * this, int r, int x, int y, unsigned char pixel) { - int i; - dvbsub_func_t *dvbsub = this->dvbsub; + dvbsub_func_t *const dvbsub = this->dvbsub; - i = (y * dvbsub->regions[r].width) + x; + const int i = (y * dvbsub->regions[r].width) + x; /* do some clipping */ if ( i<(dvbsub->regions[r].width*dvbsub->regions[r].height) ) { dvbsub->regions[r].img[i] = pixel; @@ -204,7 +198,7 @@ static void plot (dvb_spu_decoder_t * this, int r, int run_length, unsigned char dvbsub_func_t *dvbsub = this->dvbsub; - int x2 = dvbsub->x + run_length; + const int x2 = dvbsub->x + run_length; while (dvbsub->x < x2) { do_plot (this, r, dvbsub->x, dvbsub->y, pixel); @@ -212,97 +206,90 @@ static void plot (dvb_spu_decoder_t * this, int r, int run_length, unsigned char } } -static unsigned char next_nibble (dvb_spu_decoder_t * this) +static uint8_t next_nibble (dvb_spu_decoder_t * this) { - unsigned char x; dvbsub_func_t *dvbsub = this->dvbsub; - if (dvbsub->nibble_flag == 0) { - x = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; - dvbsub->nibble_flag = 1; - } - else { - x = (dvbsub->buf[dvbsub->i++] & 0x0f); - dvbsub->nibble_flag = 0; - } - return (x); + dvbsub->nibble_flag = !dvbsub->nibble_flag; + + if (dvbsub->nibble_flag) /* Inverted! */ + return (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + else + return (dvbsub->buf[dvbsub->i++] & 0x0f); } static void decode_4bit_pixel_code_string (dvb_spu_decoder_t * this, int r, int object_id, int ofs, int n) { - int next_bits, switch_1, switch_2, switch_3, run_length, pixel_code; - - dvbsub_func_t *dvbsub = this->dvbsub; - - int bits; - unsigned int data; - int j; + dvbsub_func_t *const dvbsub = this->dvbsub; if (dvbsub->in_scanline == 0) { dvbsub->in_scanline = 1; } dvbsub->nibble_flag = 0; - j = dvbsub->i + n; + const int j = dvbsub->i + n; while (dvbsub->i < j) { - bits = 0; - pixel_code = 0; - next_bits = next_nibble (this); + int bits = 0; + const uint8_t next_bits = next_nibble (this); if (next_bits != 0) { - pixel_code = next_bits; + const uint8_t pixel_code = next_bits; plot (this, r, 1, pixel_code); bits += 4; } else { bits += 4; - data = next_nibble (this); - switch_1 = (data & 0x08) >> 3; + const uint8_t data = next_nibble (this); + const uint8_t switch_1 = (data & 0x08) >> 3; bits++; if (switch_1 == 0) { - run_length = (data & 0x07); + const uint8_t run_length = (data & 0x07); bits += 3; if (run_length != 0) { - plot (this, r, run_length + 2, pixel_code); + plot (this, r, run_length + 2, 0); } else { break; } } else { - switch_2 = (data & 0x04) >> 2; + const uint8_t switch_2 = (data & 0x04) >> 2; bits++; if (switch_2 == 0) { - run_length = (data & 0x03); + const uint8_t run_length = (data & 0x03); bits += 2; - pixel_code = next_nibble (this); + const uint8_t pixel_code = next_nibble (this); bits += 4; plot (this, r, run_length + 4, pixel_code); } else { - switch_3 = (data & 0x03); + const uint8_t switch_3 = (data & 0x03); bits += 2; switch (switch_3) { case 0: - plot (this, r, 1, pixel_code); + plot (this, r, 1, 0); break; case 1: - plot (this, r, 2, pixel_code); + plot (this, r, 2, 0); break; case 2: - run_length = next_nibble (this); - bits += 4; - pixel_code = next_nibble (this); - bits += 4; - plot (this, r, run_length + 9, pixel_code); + { + const uint8_t run_length = next_nibble (this); + bits += 4; + const uint8_t pixel_code = next_nibble (this); + bits += 4; + plot (this, r, run_length + 9, pixel_code); + } break; case 3: - run_length = next_nibble (this); - run_length = (run_length << 4) | next_nibble (this); - bits += 8; - pixel_code = next_nibble (this); - bits += 4; - plot (this, r, run_length + 25, pixel_code); + { + uint8_t run_length = next_nibble (this); + run_length = (run_length << 4) | next_nibble (this); + bits += 8; + const uint8_t pixel_code = next_nibble (this); + bits += 4; + plot (this, r, run_length + 25, pixel_code); + } } } } @@ -317,7 +304,7 @@ static void decode_4bit_pixel_code_string (dvb_spu_decoder_t * this, int r, int static void set_clut(dvb_spu_decoder_t *this,int CLUT_id,int CLUT_entry_id,int Y_value, int Cr_value, int Cb_value, int T_value) { - + dvbsub_func_t *dvbsub = this->dvbsub; if ((CLUT_id>=MAX_REGIONS) || (CLUT_entry_id>15)) { @@ -337,41 +324,36 @@ static void set_clut(dvb_spu_decoder_t *this,int CLUT_id,int CLUT_entry_id,int Y } static void process_CLUT_definition_segment(dvb_spu_decoder_t *this) { - int page_id, - segment_length, - CLUT_id, - CLUT_version_number; - - int CLUT_entry_id, - CLUT_flag_8_bit, - CLUT_flag_4_bit, - CLUT_flag_2_bit, - full_range_flag, - Y_value, - Cr_value, - Cb_value, - T_value; dvbsub_func_t *dvbsub = this->dvbsub; - int j; - - page_id=(dvbsub->buf[dvbsub->i]<<8)|dvbsub->buf[dvbsub->i+1]; dvbsub->i+=2; - segment_length=(dvbsub->buf[dvbsub->i]<<8)|dvbsub->buf[dvbsub->i+1]; dvbsub->i+=2; - j=dvbsub->i+segment_length; - - CLUT_id=dvbsub->buf[dvbsub->i++]; - CLUT_version_number=(dvbsub->buf[dvbsub->i]&0xf0)>>4; + /* + const uint16_t page_id= _X_BE_16(&dvbsub->buf[dvbsub->i]); + */ + dvbsub->i+=2; + const uint16_t segment_length= _X_BE_16(&dvbsub->buf[dvbsub->i]); + dvbsub->i+=2; + const int j=dvbsub->i+segment_length; + + const uint8_t CLUT_id=dvbsub->buf[dvbsub->i++]; + /* + const uint8_t CLUT_version_number=(dvbsub->buf[dvbsub->i]&0xf0)>>4; + */ dvbsub->i++; while (dvbsub->i < j) { - CLUT_entry_id=dvbsub->buf[dvbsub->i++]; - - CLUT_flag_2_bit=(dvbsub->buf[dvbsub->i]&0x80)>>7; - CLUT_flag_4_bit=(dvbsub->buf[dvbsub->i]&0x40)>>6; - CLUT_flag_8_bit=(dvbsub->buf[dvbsub->i]&0x20)>>5; - full_range_flag=dvbsub->buf[dvbsub->i]&1; + const uint8_t CLUT_entry_id=dvbsub->buf[dvbsub->i++]; + /* + const uint8_t CLUT_flag_2_bit=(dvbsub->buf[dvbsub->i]&0x80)>>7; + const uint8_t CLUT_flag_4_bit=(dvbsub->buf[dvbsub->i]&0x40)>>6; + const uint8_t CLUT_flag_8_bit=(dvbsub->buf[dvbsub->i]&0x20)>>5; + */ + const uint8_t full_range_flag=dvbsub->buf[dvbsub->i]&1; dvbsub->i++; + int Y_value, + Cr_value, + Cb_value, + T_value; if (full_range_flag==1) { Y_value=dvbsub->buf[dvbsub->i++]; Cr_value=dvbsub->buf[dvbsub->i++]; @@ -390,17 +372,14 @@ static void process_CLUT_definition_segment(dvb_spu_decoder_t *this) { static void process_pixel_data_sub_block (dvb_spu_decoder_t * this, int r, int o, int ofs, int n) { - int data_type; - int j; - dvbsub_func_t *dvbsub = this->dvbsub; - j = dvbsub->i + n; + const int j = dvbsub->i + n; dvbsub->x = (dvbsub->regions[r].object_pos[o]) >> 16; dvbsub->y = ((dvbsub->regions[r].object_pos[o]) & 0xffff) + ofs; while (dvbsub->i < j) { - data_type = dvbsub->buf[dvbsub->i++]; + const uint8_t data_type = dvbsub->buf[dvbsub->i++]; switch (data_type) { case 0: @@ -423,83 +402,87 @@ static void process_pixel_data_sub_block (dvb_spu_decoder_t * this, int r, int o static void process_page_composition_segment (dvb_spu_decoder_t * this) { - int segment_length; - int region_id, region_x, region_y; - int j; - int r; dvbsub_func_t *dvbsub = this->dvbsub; - dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + dvbsub->page.page_id = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t segment_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - j = dvbsub->i + segment_length; + const int j = dvbsub->i + segment_length; dvbsub->page.page_time_out = dvbsub->buf[dvbsub->i++]; + if ( dvbsub->page.page_time_out>6 ) /* some timeout are insane, e.g. 65s ! */ + dvbsub->page.page_time_out = 6; - dvbsub->page.page_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + int version = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + if ( version == dvbsub->page.page_version_number ) + return; + dvbsub->page.page_version_number = version; dvbsub->page.page_state = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; dvbsub->i++; - if (dvbsub->page.page_state==2) { - for (r=0; r<MAX_REGIONS; r++) - dvbsub->page.regions[r].is_visible = 0; - } - else if ( dvbsub->page.page_state!=0 && dvbsub->page.page_state!=1 ) { - return; + int r; + for (r=0; r<MAX_REGIONS; r++) { /* reset */ + dvbsub->page.regions[r].is_visible = 0; } while (dvbsub->i < j) { - region_id = dvbsub->buf[dvbsub->i++]; + const uint8_t region_id = dvbsub->buf[dvbsub->i++]; dvbsub->i++; /* reserved */ - region_x = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t region_x = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - region_y = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t region_y = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; dvbsub->page.regions[region_id].x = region_x; dvbsub->page.regions[region_id].y = region_y; + dvbsub->page.regions[region_id].is_visible = 1; } } static void process_region_composition_segment (dvb_spu_decoder_t * this) { - int segment_length, - region_id, - region_version_number, - region_fill_flag, region_width, region_height, region_level_of_compatibility, region_depth, CLUT_id, region_8_bit_pixel_code, region_4_bit_pixel_code, region_2_bit_pixel_code; - int object_id, object_type, object_provider_flag, object_x, object_y, foreground_pixel_code, background_pixel_code; - int j; - int o; dvbsub_func_t *dvbsub = this->dvbsub; - dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + dvbsub->page.page_id = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t segment_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - j = dvbsub->i + segment_length; + const int j = dvbsub->i + segment_length; - region_id = dvbsub->buf[dvbsub->i++]; - region_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; - region_fill_flag = (dvbsub->buf[dvbsub->i] & 0x08) >> 3; + const uint8_t region_id = dvbsub->buf[dvbsub->i++]; + const uint8_t region_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + const uint8_t region_fill_flag = (dvbsub->buf[dvbsub->i] & 0x08) >> 3; dvbsub->i++; - region_width = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t region_width = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - region_height = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t region_height = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - region_level_of_compatibility = (dvbsub->buf[dvbsub->i] & 0xe0) >> 5; - region_depth = (dvbsub->buf[dvbsub->i] & 0x1c) >> 2; + /* + const uint8_t region_level_of_compatibility = (dvbsub->buf[dvbsub->i] & 0xe0) >> 5; + const uint8_t region_depth = (dvbsub->buf[dvbsub->i] & 0x1c) >> 2; + */ + dvbsub->i++; + const uint8_t CLUT_id = dvbsub->buf[dvbsub->i++]; + /* + const uint8_t region_8_bit_pixel_code = dvbsub->buf[dvbsub->i]; + */ dvbsub->i++; - CLUT_id = dvbsub->buf[dvbsub->i++]; - region_8_bit_pixel_code = dvbsub->buf[dvbsub->i++]; - region_4_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; - region_2_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; + const uint8_t region_4_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + /* + const uint8_t region_2_bit_pixel_code = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; + */ dvbsub->i++; if(region_id>=MAX_REGIONS) return; - + + if ( dvbsub->regions[region_id].version_number == region_version_number ) + return; + + dvbsub->regions[region_id].version_number = region_version_number; + /* Check if region size has changed and fill background. */ update_region (this, region_id, region_width, region_height, region_fill_flag, region_4_bit_pixel_code); if ( CLUT_id<MAX_REGIONS ) @@ -508,25 +491,33 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) dvbsub->regions[region_id].objects_start = dvbsub->i; dvbsub->regions[region_id].objects_end = j; - for (o = 0; o < 65536; o++) { - dvbsub->regions[region_id].object_pos[o] = 0xffffffff; + { + int o; + for (o = 0; o < 65536; o++) { + dvbsub->regions[region_id].object_pos[o] = 0xffffffff; + } } while (dvbsub->i < j) { - object_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t object_id = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; - object_type = (dvbsub->buf[dvbsub->i] & 0xc0) >> 6; - object_provider_flag = (dvbsub->buf[dvbsub->i] & 0x30) >> 4; - object_x = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint8_t object_type = (dvbsub->buf[dvbsub->i] & 0xc0) >> 6; + /* + const uint8_t object_provider_flag = (dvbsub->buf[dvbsub->i] & 0x30) >> 4; + */ + const uint16_t object_x = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; - object_y = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t object_y = ((dvbsub->buf[dvbsub->i] & 0x0f) << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; dvbsub->regions[region_id].object_pos[object_id] = (object_x << 16) | object_y; if ((object_type == 0x01) || (object_type == 0x02)) { - foreground_pixel_code = dvbsub->buf[dvbsub->i++]; - background_pixel_code = dvbsub->buf[dvbsub->i++]; + /* + const uint8_t foreground_pixel_code = dvbsub->buf[dvbsub->i]; + const uint8_t background_pixel_code = dvbsub->buf[dvbsub->i+1]; + */ + dvbsub->i += 2; } } @@ -534,49 +525,48 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) static void process_object_data_segment (dvb_spu_decoder_t * this) { - int segment_length, object_id, object_version_number, object_coding_method, non_modifying_colour_flag; - - int top_field_data_block_length, bottom_field_data_block_length; - dvbsub_func_t *dvbsub = this->dvbsub; - int j; - int old_i; - int r; - dvbsub->page.page_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; dvbsub->i += 2; - segment_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + /* + const uint16_t segment_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); + */ dvbsub->i += 2; - j = dvbsub->i + segment_length; - object_id = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; + const uint16_t object_id = _X_BE_16(&dvbsub->buf[dvbsub->i]); dvbsub->i += 2; dvbsub->curr_obj = object_id; - object_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; - object_coding_method = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; - non_modifying_colour_flag = (dvbsub->buf[dvbsub->i] & 0x02) >> 1; + const uint8_t object_coding_method = (dvbsub->buf[dvbsub->i] & 0x0c) >> 2; + /* + const uint8_t object_version_number = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; + const uint8_t non_modifying_colour_flag = (dvbsub->buf[dvbsub->i] & 0x02) >> 1; + */ dvbsub->i++; - old_i = dvbsub->i; + if ( object_coding_method != 0 ) + return; + + const int old_i = dvbsub->i; + int r; for (r = 0; r < MAX_REGIONS; r++) { /* If this object is in this region... */ - if (dvbsub->regions[r].img) { - if (dvbsub->regions[r].object_pos[object_id] != 0xffffffff) { - dvbsub->i = old_i; - if (object_coding_method == 0) { - top_field_data_block_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; - dvbsub->i += 2; - bottom_field_data_block_length = (dvbsub->buf[dvbsub->i] << 8) | dvbsub->buf[dvbsub->i + 1]; - dvbsub->i += 2; - - process_pixel_data_sub_block (this, r, object_id, 0, top_field_data_block_length); - - process_pixel_data_sub_block (this, r, object_id, 1, bottom_field_data_block_length); - } - } - } + if (!dvbsub->regions[r].img) + continue; + + if (dvbsub->regions[r].object_pos[object_id] == 0xffffffff) + continue; + + dvbsub->i = old_i; + + const uint16_t top_field_data_block_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); + dvbsub->i += 2; + const uint16_t bottom_field_data_block_length = _X_BE_16(&dvbsub->buf[dvbsub->i]); + dvbsub->i += 2; + + process_pixel_data_sub_block (this, r, object_id, 0, top_field_data_block_length); + process_pixel_data_sub_block (this, r, object_id, 1, bottom_field_data_block_length); } } @@ -603,38 +593,37 @@ static void* dvbsub_timer_func(void *this_gen) { dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen; pthread_mutex_lock(&this->dvbsub_osd_mutex); - int i; /* If we're cancelled via pthread_cancel, unlock the mutex */ pthread_cleanup_push(unlock_mutex_cancellation_func, &this->dvbsub_osd_mutex); - while(1) - { + while(1) { /* Record the current timeout, and wait - note that pthread_cond_timedwait will unlock the mutex on entry, and lock it on exit */ struct timespec timeout = this->dvbsub_hide_timeout; - int result = pthread_cond_timedwait(&this->dvbsub_restart_timeout, - &this->dvbsub_osd_mutex, - &this->dvbsub_hide_timeout); - if(result == ETIMEDOUT && - timeout.tv_sec == this->dvbsub_hide_timeout.tv_sec && - timeout.tv_nsec == this->dvbsub_hide_timeout.tv_nsec) - { - /* We timed out, and no-one changed the timeout underneath us. - Hide the OSD, then wait until we're signalled. */ - if(this && this->stream && this->stream->osd_renderer) - { - for ( i=0; i<MAX_REGIONS; i++ ) { - if ( this->dvbsub->regions[i].osd ) { - this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); + const int result = pthread_cond_timedwait(&this->dvbsub_restart_timeout, + &this->dvbsub_osd_mutex, + &this->dvbsub_hide_timeout); + if(result != ETIMEDOUT || + timeout.tv_sec != this->dvbsub_hide_timeout.tv_sec || + timeout.tv_nsec != this->dvbsub_hide_timeout.tv_nsec) + continue; + + /* We timed out, and no-one changed the timeout underneath us. + Hide the OSD, then wait until we're signalled. */ + if(this && this->stream && this->stream->osd_renderer) { + int i; + for ( i=0; i<MAX_REGIONS; i++ ) { + if ( !this->dvbsub->regions[i].osd ) + continue; + + this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); #ifdef LOG - printf("SPUDVB: thread hiding = %d\n",i); + printf("SPUDVB: thread hiding = %d\n",i); #endif - } - } } - pthread_cond_wait(&this->dvbsub_restart_timeout, &this->dvbsub_osd_mutex); } + pthread_cond_wait(&this->dvbsub_restart_timeout, &this->dvbsub_osd_mutex); } pthread_cleanup_pop(1); @@ -654,34 +643,41 @@ static void downscale_region_image( region_t *reg, unsigned char *dest, int dest static void draw_subtitles (dvb_spu_decoder_t * this) { - int r; - int display=0; int64_t dum; - int dest_width=0, dest_height, reg_width; + int dest_width=0, dest_height; this->stream->video_out->status(this->stream->video_out, NULL, &dest_width, &dest_height, &dum); - unsigned char tmp[dest_width*576]; - unsigned char *reg; if ( !dest_width ) return; /* render all regions onto the page */ - for ( r=0; r<MAX_REGIONS; r++ ) { - if ( this->dvbsub->page.regions[r].is_visible ) - display++; + { + int r; + int display = 0; + for ( r=0; r<MAX_REGIONS; r++ ) { + if ( this->dvbsub->page.regions[r].is_visible ) { + display = 1; + break; + } + } + if ( !display ) + return; } - if ( !display ) - return; + int r; for (r = 0; r < MAX_REGIONS; r++) { - if (this->dvbsub->regions[r].img) { + if (this->dvbsub->regions[r].img) { if (this->dvbsub->page.regions[r].is_visible && !this->dvbsub->regions[r].empty) { update_osd( this, r ); if ( !this->dvbsub->regions[r].osd ) continue; /* clear osd */ this->stream->osd_renderer->clear( this->dvbsub->regions[r].osd ); + + uint8_t *reg; + int reg_width; + uint8_t tmp[dest_width*576]; if (this->dvbsub->regions[r].width>dest_width) { downscale_region_image(&this->dvbsub->regions[r], tmp, dest_width); reg = tmp; @@ -702,6 +698,9 @@ static void draw_subtitles (dvb_spu_decoder_t * this) printf("SPUDVB: this->vpts=%llu\n",this->vpts); #endif for ( r=0; r<MAX_REGIONS; r++ ) { +#ifdef LOG + printf("SPUDVB : region=%d, visible=%d, osd=%d, empty=%d\n", r, this->dvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); +#endif if ( this->dvbsub->page.regions[r].is_visible && this->dvbsub->regions[r].osd && !this->dvbsub->regions[r].empty ) { this->stream->osd_renderer->set_position( this->dvbsub->regions[r].osd, this->dvbsub->page.regions[r].x, this->dvbsub->page.regions[r].y ); this->stream->osd_renderer->show( this->dvbsub->regions[r].osd, this->vpts ); @@ -731,21 +730,16 @@ static void draw_subtitles (dvb_spu_decoder_t * this) static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) { dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen; - int new_i; - int data_identifier, subtitle_stream_id; - int segment_length, segment_type; - int PES_header_data_length; - int PES_packet_length; - int i; - + if((buf->type & 0xffff0000)!=BUF_SPU_DVB) - return; + return; if (buf->decoder_flags & BUF_FLAG_SPECIAL) { if (buf->decoder_info[1] == BUF_SPECIAL_SPU_DVB_DESCRIPTOR) { if (buf->decoder_info[2] == 0) { /* Hide the osd - note that if the timeout thread times out, it'll rehide, which is harmless */ pthread_mutex_lock(&this->dvbsub_osd_mutex); + int i; for ( i=0; i<MAX_REGIONS; i++ ) { if ( this->dvbsub->regions[i].osd ) this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); @@ -779,12 +773,12 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) * because buf->pts could be too far in future and metronom won't accept * further backwards pts (see metronom_got_spu_packet) */ if (buf->pts) { - metronom_t *metronom = this->stream->metronom; - int64_t vpts_offset = metronom->get_option( metronom, METRONOM_VPTS_OFFSET ); - int64_t spu_offset = metronom->get_option( metronom, METRONOM_SPU_OFFSET ); - int64_t vpts = (int64_t)(buf->pts)+vpts_offset+spu_offset; - metronom_clock_t *clock = this->stream->xine->clock; - int64_t curvpts = clock->get_current_time( clock ); + metronom_t *const metronom = this->stream->metronom; + const int64_t vpts_offset = metronom->get_option( metronom, METRONOM_VPTS_OFFSET ); + const int64_t spu_offset = metronom->get_option( metronom, METRONOM_SPU_OFFSET ); + const int64_t vpts = (int64_t)(buf->pts)+vpts_offset+spu_offset; + metronom_clock_t *const clock = this->stream->xine->clock; + const int64_t curvpts = clock->get_current_time( clock ); /* if buf->pts is unreliable, show page asap (better than nothing) */ #ifdef LOG printf("SPUDVB: spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts); @@ -795,58 +789,62 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) this->vpts = vpts; } + /* completely ignore pts since it makes a lot of problems with various providers */ + this->vpts = 0; + /* process the pes section */ - - PES_packet_length = this->pes_pkt_size; - this->dvbsub->buf = this->pes_pkt; + const int PES_packet_length = this->pes_pkt_size; - PES_header_data_length = 0; - this->dvbsub->i = 0; + this->dvbsub->buf = this->pes_pkt; - data_identifier = this->dvbsub->buf[this->dvbsub->i++]; - subtitle_stream_id = this->dvbsub->buf[this->dvbsub->i++]; + this->dvbsub->i = 0; - while (this->dvbsub->i <= (PES_packet_length)) { - /* SUBTITLING SEGMENT */ - this->dvbsub->i++; - segment_type = this->dvbsub->buf[this->dvbsub->i++]; - - this->dvbsub->page.page_id = (this->dvbsub->buf[this->dvbsub->i] << 8) | this->dvbsub->buf[this->dvbsub->i + 1]; - segment_length = (this->dvbsub->buf[this->dvbsub->i + 2] << 8) | this->dvbsub->buf[this->dvbsub->i + 3]; - new_i = this->dvbsub->i + segment_length + 4; + /* + const uint8_t data_identifier = this->dvbsub->buf[this->dvbsub->i]; + const uint8_t subtitle_stream_id = this->dvbsub->buf[this->dvbsub->i+1]; + */ + this->dvbsub->i += 2; - /* only process complete segments */ - if(new_i > (this->pes_pkt_wrptr - this->pes_pkt)) - break; - /* verify we've the right segment */ - if(this->dvbsub->page.page_id==this->spu_descriptor->comp_page_id){ - /* SEGMENT_DATA_FIELD */ - switch (segment_type & 0xff) { - case 0x10: - process_page_composition_segment (this); - break; - case 0x11: - process_region_composition_segment (this); - break; - case 0x12: - process_CLUT_definition_segment(this); - break; - case 0x13: - process_object_data_segment (this); - break; - case 0x80: /* Page is now completely rendered */ - draw_subtitles( this ); - break; - default: - return; - break; - } - } - this->dvbsub->i = new_i; - } + while (this->dvbsub->i <= (PES_packet_length)) { + /* SUBTITLING SEGMENT */ + this->dvbsub->i++; + const uint8_t segment_type = this->dvbsub->buf[this->dvbsub->i++]; + + this->dvbsub->page.page_id = (this->dvbsub->buf[this->dvbsub->i] << 8) | this->dvbsub->buf[this->dvbsub->i + 1]; + const uint16_t segment_length = _X_BE_16(&this->dvbsub->buf[this->dvbsub->i + 2]); + const int new_i = this->dvbsub->i + segment_length + 4; + + /* only process complete segments */ + if(new_i > (this->pes_pkt_wrptr - this->pes_pkt)) + break; - return; + /* verify we've the right segment */ + if(this->dvbsub->page.page_id==this->spu_descriptor->comp_page_id){ + /* SEGMENT_DATA_FIELD */ + switch (segment_type) { + case 0x10: + process_page_composition_segment(this); + break; + case 0x11: + process_region_composition_segment(this); + break; + case 0x12: + process_CLUT_definition_segment(this); + break; + case 0x13: + process_object_data_segment (this); + break; + case 0x80: + draw_subtitles( this ); /* Page is now completely rendered */ + break; + default: + return; + break; + } + } + this->dvbsub->i = new_i; + } } static void spudec_reset (spu_decoder_t * this_gen) @@ -859,7 +857,9 @@ static void spudec_reset (spu_decoder_t * this_gen) for ( i=0; i<MAX_REGIONS; i++ ) { if ( this->dvbsub->regions[i].osd ) this->stream->osd_renderer->hide(this->dvbsub->regions[i].osd, 0); + this->dvbsub->regions[i].version_number = -1; } + this->dvbsub->page.page_version_number = -1; pthread_mutex_unlock(&this->dvbsub_osd_mutex); } @@ -872,42 +872,31 @@ static void spudec_discontinuity (spu_decoder_t * this_gen) static void spudec_dispose (spu_decoder_t * this_gen) { dvb_spu_decoder_t *this = (dvb_spu_decoder_t *) this_gen; - int i; pthread_cancel(this->dvbsub_timer_thread); pthread_join(this->dvbsub_timer_thread, NULL); pthread_mutex_destroy(&this->dvbsub_osd_mutex); pthread_cond_destroy(&this->dvbsub_restart_timeout); - if(this->spu_descriptor){ - free(this->spu_descriptor); - this->spu_descriptor=NULL; - } + free(this->spu_descriptor); + this->spu_descriptor=NULL; + int i; for ( i=0; i<MAX_REGIONS; i++ ) { - if ( this->dvbsub->regions[i].img ) - free( this->dvbsub->regions[i].img ); + free( this->dvbsub->regions[i].img ); if ( this->dvbsub->regions[i].osd ) this->stream->osd_renderer->free_object( this->dvbsub->regions[i].osd ); } - if (this->pes_pkt) - free (this->pes_pkt); - - if (this->dvbsub) - free (this->dvbsub); - + free (this->pes_pkt); + free (this->dvbsub); free (this); } static spu_decoder_t *dvb_spu_class_open_plugin (spu_decoder_class_t * class_gen, xine_stream_t * stream) { - - int i; - dvb_spu_decoder_t *this; - dvb_spu_class_t *class = (dvb_spu_class_t *) class_gen; - - this = (dvb_spu_decoder_t *) xine_xmalloc (sizeof (dvb_spu_decoder_t)); + dvb_spu_decoder_t *this = calloc(1, sizeof (dvb_spu_decoder_t)); + dvb_spu_class_t *class = (dvb_spu_class_t *)class_gen; this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -919,17 +908,10 @@ static spu_decoder_t *dvb_spu_class_open_plugin (spu_decoder_class_t * class_gen this->class = class; this->stream = stream; - this->pes_pkt = xine_xmalloc (1024*65); - this->spu_descriptor = xine_xmalloc(sizeof(spu_dvb_descriptor_t)); - - this->dvbsub = xine_xmalloc (sizeof (dvbsub_func_t)); + this->pes_pkt = calloc(65, 1024); + this->spu_descriptor = calloc(1, sizeof(spu_dvb_descriptor_t)); - for (i = 0; i < MAX_REGIONS; i++) { - this->dvbsub->page.regions[i].is_visible = 0; - this->dvbsub->regions[i].img = NULL; - this->dvbsub->regions[i].osd = NULL; - this->dvbsub->regions[i].CLUT_id = 0; - } + this->dvbsub = calloc(1, sizeof (dvbsub_func_t)); pthread_mutex_init(&this->dvbsub_osd_mutex, NULL); pthread_cond_init(&this->dvbsub_restart_timeout, NULL); @@ -957,9 +939,7 @@ static char *dvb_spu_class_get_description (spu_decoder_class_t * this) static void *init_spu_decoder_plugin (xine_t * xine, void *data) { - - dvb_spu_class_t *this; - this = (dvb_spu_class_t *) xine_xmalloc (sizeof (dvb_spu_class_t)); + dvb_spu_class_t *this = calloc(1, sizeof (dvb_spu_class_t)); this->class.open_plugin = dvb_spu_class_open_plugin; this->class.get_identifier = dvb_spu_class_get_identifier; diff --git a/src/libspuhdmv/Makefile.am b/src/libspuhdmv/Makefile.am new file mode 100644 index 000000000..15a029f8a --- /dev/null +++ b/src/libspuhdmv/Makefile.am @@ -0,0 +1,9 @@ +include $(top_builddir)/misc/Makefile.plugins +include $(top_srcdir)/misc/Makefile.common + +xineplug_LTLIBRARIES = xineplug_decode_spuhdmv.la + +xineplug_decode_spuhdmv_la_SOURCES = xine_hdmv_decoder.c +xineplug_decode_spuhdmv_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_decode_spuhdmv_la_CFLAGS = $(VISIBILITY_FLAG) +xineplug_decode_spuhdmv_la_LDFLAGS = $(xineplug_ldflags) diff --git a/src/libspuhdmv/xine_hdmv_decoder.c b/src/libspuhdmv/xine_hdmv_decoder.c new file mode 100644 index 000000000..be5e6b638 --- /dev/null +++ b/src/libspuhdmv/xine_hdmv_decoder.c @@ -0,0 +1,1019 @@ +/* + * Copyright (C) 2000-2009 the xine project + * + * Copyright (C) 2009 Petri Hintukainen <phintuka@users.sourceforge.net> + * + * This file is part of xine, a unix video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * Decoder for HDMV/BluRay bitmap subtitles + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#ifdef HAVE_CONFIG_H +# include "xine_internal.h" +# include "buffer.h" +# include "xineutils.h" +# include "video_out.h" +# include "video_overlay.h" +#else +# include <xine/xine_internal.h> +# include <xine/buffer.h> +# include <xine/xineutils.h> +# include <xine/video_out.h> +# include <xine/video_overlay.h> +#endif + +#define XINE_HDMV_TRACE(x...) printf(x) +/*#define TRACE(x...) */ +#define XINE_HDMV_ERROR(x...) fprintf(stderr, "spuhdmv: " x) +/*#define ERROR(x...) lprintf(x) */ + +/* + * cached palette (xine-lib format) + */ +typedef struct subtitle_clut_s subtitle_clut_t; +struct subtitle_clut_s { + uint8_t id; + uint32_t color[256]; + uint8_t trans[256]; + subtitle_clut_t *next; + + int shown; +}; + +/* + * cached RLE image (xine-lib format) + */ +typedef struct subtitle_object_s subtitle_object_t; +struct subtitle_object_s { + uint16_t id; + uint16_t xpos, ypos; + uint16_t width, height; + + rle_elem_t *rle; + unsigned int num_rle; + size_t data_size; + +#if 0 + uint8_t *raw_data; /* partial RLE data in HDMV format */ + size_t raw_data_len; + size_t raw_data_size; +#endif + + subtitle_object_t *next; + + int shown; +}; + +/* + * Window definition + */ +typedef struct window_def_s window_def_t; +struct window_def_s { + uint8_t id; + uint16_t xpos, ypos; + uint16_t width, height; + + window_def_t *next; + + int shown; +}; + + +/* + * decoded SPU + */ +typedef struct composition_object_s composition_object_t; +struct composition_object_s { + uint8_t window_id_ref; + uint8_t object_id_ref; + + uint16_t xpos, ypos; + + uint8_t forced_flag; + uint8_t cropped_flag; + uint16_t crop_horiz_pos, crop_vert_pos; + uint16_t crop_width, crop_height; + + composition_object_t *next; + + int shown; +}; + +typedef struct composition_descriptor_s composition_descriptor_t; +struct composition_descriptor_s { + uint16_t number; + uint8_t state; +}; + +typedef struct presentation_segment_s presentation_segment_t; +struct presentation_segment_s { + composition_descriptor_t comp_descr; + + uint8_t palette_update_flag; + uint8_t palette_id_ref; + uint8_t object_number; + + composition_object_t *comp_objs; + + presentation_segment_t *next; + + int64_t pts; + int shown; +}; + +/* + * list handling + */ + +#define LIST_REPLACE(list, obj, FREE_FUNC) \ + do { \ + unsigned int id = obj->id; \ + \ + /* insert to list */ \ + obj->next = list; \ + list = obj; \ + \ + /* remove old */ \ + while (obj->next && obj->next->id != id) \ + obj = obj->next; \ + if (obj->next) { \ + void *tmp = (void*)obj->next; \ + obj->next = obj->next->next; \ + FREE_FUNC(tmp); \ + } \ + } while (0); + +#define LIST_DESTROY(list, FREE_FUNC) \ + while (list) { \ + void *tmp = (void*)list; \ + list = list->next; \ + FREE_FUNC(tmp); \ + } + +static void free_subtitle_object(void *ptr) +{ + if (ptr) { + free(((subtitle_object_t*)ptr)->rle); + free(ptr); + } +} +static void free_presentation_segment(void *ptr) +{ + if (ptr) { + presentation_segment_t *seg = (presentation_segment_t*)ptr; + LIST_DESTROY(seg->comp_objs, free); + free(ptr); + } +} + + +/* + * segment_buffer_t + * + * assemble and decode segments + */ + +typedef struct { + /* current segment */ + int segment_len; /* length of current segment (without 3-byte header) */ + uint8_t segment_type; /* current segment type */ + uint8_t *segment_data; /* pointer to current segment payload */ + uint8_t *segment_end; /* pointer to last byte + 1 of current segment */ + uint8_t error; /* boolean: buffer overflow etc. */ + + /* accumulated data */ + uint8_t *buf; /* */ + size_t len; /* count of unprocessed bytes */ + size_t data_size; /* allocated buffer size */ +} segment_buffer_t; + +/* + * mgmt + */ + +static segment_buffer_t *segbuf_init(void) +{ + segment_buffer_t *buf = calloc(1, sizeof(segment_buffer_t)); + return buf; +} + +static void segbuf_dispose(segment_buffer_t *buf) +{ + if (buf->buf) + free (buf->buf); + free (buf); +} + +static void segbuf_reset(segment_buffer_t *buf) +{ + buf->segment_end = buf->segment_data = buf->buf; + buf->len = 0; + buf->segment_len = -1; + buf->segment_type = 0; + buf->error = 0; +} + +/* + * assemble, parse + */ + +static void segbuf_parse_segment_header(segment_buffer_t *buf) +{ + if (buf->len > 2) { + buf->segment_type = buf->buf[0]; + buf->segment_len = (buf->buf[1] << 8) | buf->buf[2]; + buf->segment_data = buf->buf + 3; + buf->segment_end = buf->segment_data + buf->segment_len; + buf->error = 0; + + if ( buf->segment_type < 0x14 || + ( buf->segment_type > 0x18 && + buf->segment_type != 0x80)) { + XINE_HDMV_ERROR("unknown segment type, resetting\n"); + segbuf_reset(buf); + } + } else { + buf->segment_len = -1; + buf->error = 1; + } +} + +static void segbuf_fill(segment_buffer_t *buf, uint8_t *data, size_t len) +{ + if (buf->len + len > buf->data_size) { + buf->data_size = buf->len + len; + if (buf->buf) + buf->buf = realloc(buf->buf, buf->data_size); + else + buf->buf = malloc(buf->data_size); + } + + memcpy(buf->buf + buf->len, data, len); + buf->len += len; + + segbuf_parse_segment_header(buf); +} + +static int segbuf_segment_complete(segment_buffer_t *buf) +{ + return (buf->segment_len >= 0) && (buf->len >= buf->segment_len + 3); +} + +static void segbuf_skip_segment(segment_buffer_t *buf) +{ + if (segbuf_segment_complete (buf)) { + buf->len -= buf->segment_len + 3; + if (buf->len > 0) + memmove(buf->buf, buf->buf + buf->segment_len + 3, buf->len); + + segbuf_parse_segment_header(buf); + + XINE_HDMV_TRACE(" skip_segment: %zd bytes left\n", buf->len); + } else { + XINE_HDMV_ERROR(" skip_segment: ERROR - %zd bytes queued, %d required\n", + buf->len, buf->segment_len); + segbuf_reset (buf); + } +} + +/* + * access segment data + */ + +static uint8_t segbuf_segment_type(segment_buffer_t *buf) +{ + return buf->segment_type; +} + +static size_t segbuf_data_length(segment_buffer_t *buf) +{ + ssize_t val = buf->segment_end - buf->segment_data; + if (val < 0) val = 0; + return (size_t)val; +} + +static uint8_t segbuf_get_u8(segment_buffer_t *buf) +{ + if (!(buf->error = ++buf->segment_data > buf->segment_end)) + return buf->segment_data[-1]; + XINE_HDMV_ERROR("segbuf_get_u8: read failed (end of segment reached) !"); + return 0; +} + +static uint16_t segbuf_get_u16(segment_buffer_t *buf) +{ + return (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf); +} + +static uint32_t segbuf_get_u24(segment_buffer_t *buf) +{ + return (segbuf_get_u8(buf) << 16) | (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf); +} + +static uint8_t *segbuf_get_string(segment_buffer_t *buf, size_t len) +{ + if (len > 0) { + uint8_t *val = buf->segment_data; + buf->segment_data += len; + if (buf->segment_data <= buf->segment_end) + return val; + } + XINE_HDMV_ERROR("segbuf_get_string(%zd): read failed (end of segment reached) !", len); + buf->error = 1; + return NULL; +} + +/* + * decode segments + */ + +static subtitle_clut_t *segbuf_decode_palette(segment_buffer_t *buf) +{ + uint8_t palette_id = segbuf_get_u8 (buf); + uint8_t palette_version_number = segbuf_get_u8 (buf); + + size_t len = segbuf_data_length(buf); + size_t entries = len / 5; + int i; + + if (buf->error) + return NULL; + + if (len % 5) { + XINE_HDMV_ERROR(" decode_palette: segment size error (%zd ; expected %zd for %zd entries)\n", + len, (5 * entries), entries); + return NULL; + } + XINE_HDMV_TRACE("decode_palette: %zd items (id %d, version %d)\n", + entries, palette_id, palette_version_number); + + /* convert to xine-lib clut */ + subtitle_clut_t *clut = calloc(1, sizeof(subtitle_clut_t)); + clut->id = palette_id; + + for (i = 0; i < entries; i++) { + uint8_t index = segbuf_get_u8 (buf); + uint8_t Y = segbuf_get_u8 (buf); + uint8_t Cr = segbuf_get_u8 (buf); + uint8_t Cb = segbuf_get_u8 (buf); + uint8_t alpha = segbuf_get_u8 (buf); + clut->color[index] = (Y << 16) | (Cr << 8) | Cb; + clut->trans[index] = alpha >> 4; + } + + return clut; +} + +static int segbuf_decode_rle(segment_buffer_t *buf, subtitle_object_t *obj) +{ + int x = 0, y = 0; + int rle_size = sizeof(rle_elem_t) * obj->width / 16 * obj->height + 1; + rle_elem_t *rlep = malloc(rle_size); + + free (obj->rle); + obj->rle = rlep; + obj->data_size = rle_size; + obj->num_rle = 0; + + /* convert to xine-lib rle format */ + while (y < obj->height && !buf->error) { + + /* decode RLE element */ + uint8_t byte = segbuf_get_u8 (buf); + if (byte != 0) { + rlep->color = byte; + rlep->len = 1; + } else { + byte = segbuf_get_u8 (buf); + if (!(byte & 0x80)) { + rlep->color = 0; + if (!(byte & 0x40)) + rlep->len = byte & 0x3f; + else + rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf); + } else { + if (!(byte & 0x40)) + rlep->len = byte & 0x3f; + else + rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf); + rlep->color = segbuf_get_u8 (buf); + } + } + + /* move to next element */ + if (rlep->len > 0) { + x += rlep->len; + rlep++; + obj->num_rle ++; + } else { + /* end of line marker (00 00) */ + if (x < obj->width) { + rlep->len = obj->width - x; + rlep->color = 0xff; + rlep++; + obj->num_rle ++; + } + x = 0; + y++; + } + + /* grow allocated RLE data size ? */ + if (obj->data_size <= (obj->num_rle + 1) * sizeof(rle_elem_t)) { + obj->data_size *= 2; + obj->rle = realloc(obj->rle, obj->data_size); + rlep = obj->rle + obj->num_rle; + } + } + + return buf->error; +} + +static subtitle_object_t *segbuf_decode_object(segment_buffer_t *buf) +{ + uint8_t object_id = segbuf_get_u16(buf); + uint8_t version = segbuf_get_u8 (buf); + uint8_t seq_desc = segbuf_get_u8 (buf); + + XINE_HDMV_TRACE(" decode_object: object_id %d, version %d, seq 0x%x\n", + object_id, version, seq_desc); + + //LIST_FIND(); + subtitle_object_t *obj = calloc(1, sizeof(subtitle_object_t)); + obj->id = object_id; + + if (seq_desc & 0x80) { + + uint32_t data_len = segbuf_get_u24(buf); + obj->width = segbuf_get_u16(buf); + obj->height = segbuf_get_u16(buf); + + XINE_HDMV_TRACE(" object length %d bytes, size %dx%d\n", data_len, obj->width, obj->height); + + segbuf_decode_rle (buf, obj); + + if (buf->error) { + free_subtitle_object(obj); + return NULL; + } + + } else { + XINE_HDMV_ERROR(" TODO: APPEND RLE, length %d bytes\n", buf->segment_len - 4); + /* TODO */ + free_subtitle_object(obj); + return NULL; + } + + return obj; +} + +static window_def_t *segbuf_decode_window_definition(segment_buffer_t *buf) +{ + window_def_t *wnd = calloc(1, sizeof(window_def_t)); + + uint8_t a = segbuf_get_u8 (buf); + wnd->id = segbuf_get_u8 (buf); + wnd->xpos = segbuf_get_u16 (buf); + wnd->ypos = segbuf_get_u16 (buf); + wnd->width = segbuf_get_u16 (buf); + wnd->height = segbuf_get_u16 (buf); + + XINE_HDMV_TRACE(" window: [%02x %d] %d,%d %dx%d\n", a, + wnd->id, wnd->xpos, wnd->ypos, wnd->width, wnd->height); + + if (buf->error) { + free(wnd); + return NULL; + } + + return wnd; +} + +static int segbuf_decode_video_descriptor(segment_buffer_t *buf) +{ + uint16_t width = segbuf_get_u16(buf); + uint16_t height = segbuf_get_u16(buf); + uint8_t frame_rate = segbuf_get_u8 (buf); + + XINE_HDMV_TRACE(" video_descriptor: %dx%d fps %d\n", width, height, frame_rate); + return buf->error; +} + +static int segbuf_decode_composition_descriptor(segment_buffer_t *buf, composition_descriptor_t *descr) +{ + descr->number = segbuf_get_u16(buf); + descr->state = segbuf_get_u8 (buf); + + XINE_HDMV_TRACE(" composition_descriptor: number %d, state %d\n", descr->number, descr->state); + return buf->error; +} + +static composition_object_t *segbuf_decode_composition_object(segment_buffer_t *buf) +{ + composition_object_t *cobj = calloc(1, sizeof(composition_object_t)); + + cobj->object_id_ref = segbuf_get_u16 (buf); + cobj->window_id_ref = segbuf_get_u8 (buf); + uint8_t tmp = segbuf_get_u8 (buf); + cobj->cropped_flag = !!(tmp & 0x80); + cobj->forced_flag = !!(tmp & 0x40); + cobj->xpos = segbuf_get_u16 (buf); + cobj->ypos = segbuf_get_u16 (buf); + if (cobj->cropped_flag) { + /* x,y where to take the image from */ + cobj->crop_horiz_pos = segbuf_get_u8 (buf); + cobj->crop_vert_pos = segbuf_get_u8 (buf); + /* size of the cropped image */ + cobj->crop_width = segbuf_get_u8 (buf); + cobj->crop_height = segbuf_get_u8 (buf); + } + + if (buf->error) { + free(cobj); + return NULL; + } + + XINE_HDMV_TRACE(" composition_object: id: %d, win: %d, position %d,%d crop %d forced %d\n", + cobj->object_id_ref, cobj->window_id_ref, cobj->xpos, cobj->ypos, + cobj->cropped_flag, cobj->forced_flag); + + return cobj; +} + +static presentation_segment_t *segbuf_decode_presentation_segment(segment_buffer_t *buf) +{ + presentation_segment_t *seg = calloc(1, sizeof(presentation_segment_t)); + int index; + + segbuf_decode_video_descriptor (buf); + segbuf_decode_composition_descriptor (buf, &seg->comp_descr); + + seg->palette_update_flag = !!((segbuf_get_u8(buf)) & 0x80); + seg->palette_id_ref = segbuf_get_u8 (buf); + seg->object_number = segbuf_get_u8 (buf); + + XINE_HDMV_TRACE(" presentation_segment: object_number %d, palette %d\n", + seg->object_number, seg->palette_id_ref); + + for (index = 0; index < seg->object_number; index++) { + composition_object_t *cobj = segbuf_decode_composition_object (buf); + cobj->next = seg->comp_objs; + seg->comp_objs = cobj; + } + + if (buf->error) { + free_presentation_segment(seg); + return NULL; + } + + return seg; +} + +static rle_elem_t *copy_crop_rle(subtitle_object_t *obj, composition_object_t *cobj) +{ + /* TODO: cropping (w,h sized image from pos x,y) */ + + rle_elem_t *rle = calloc (obj->num_rle, sizeof(rle_elem_t)); + memcpy (rle, obj->rle, obj->num_rle * sizeof(rle_elem_t)); + return rle; +} + + +/* + * xine plugin + */ + +typedef struct { + spu_decoder_class_t decoder_class; +} spuhdmv_class_t; + +typedef struct spuhdmv_decoder_s { + spu_decoder_t spu_decoder; + + spuhdmv_class_t *class; + xine_stream_t *stream; + + segment_buffer_t *buf; + + subtitle_clut_t *cluts; + subtitle_object_t *objects; + window_def_t *windows; + presentation_segment_t *segments; + + int overlay_handles[MAX_OBJECTS]; + + int64_t pts; + +} spuhdmv_decoder_t; + +static int decode_palette(spuhdmv_decoder_t *this) +{ + /* decode */ + subtitle_clut_t *clut = segbuf_decode_palette(this->buf); + if (!clut) + return 1; + + LIST_REPLACE (this->cluts, clut, free); + + return 0; +} + +static int decode_object(spuhdmv_decoder_t *this) +{ + /* decode */ + subtitle_object_t *obj = segbuf_decode_object(this->buf); + if (!obj) + return 1; + + LIST_REPLACE (this->objects, obj, free_subtitle_object); + + return 0; +} + +static int decode_window_definition(spuhdmv_decoder_t *this) +{ + /* decode */ + window_def_t *wnd = segbuf_decode_window_definition (this->buf); + if (!wnd) + return 1; + + LIST_REPLACE (this->windows, wnd, free); + + return 0; +} + +static int decode_presentation_segment(spuhdmv_decoder_t *this) +{ + /* decode */ + presentation_segment_t *seg = segbuf_decode_presentation_segment(this->buf); + if (!seg) + return 1; + + seg->pts = this->pts; + + /* replace */ + if (this->segments) + LIST_DESTROY(this->segments, free_presentation_segment); + this->segments = seg; + + return 0; +} + +static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, unsigned int palette_id_ref, + int overlay_index, int64_t pts, int force_update) +{ + video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); + metronom_t *metronom = this->stream->metronom; + video_overlay_event_t event = {0}; + vo_overlay_t overlay = {0}; + + /* find palette */ + subtitle_clut_t *clut = this->cluts; + while (clut && clut->id != palette_id_ref) + clut = clut->next; + if (!clut) { + XINE_HDMV_TRACE(" show_overlay: clut %d not found !\n", palette_id_ref); + return -1; + } + + /* find RLE image */ + subtitle_object_t *obj = this->objects; + while (obj && obj->id != cobj->object_id_ref) + obj = obj->next; + if (!obj) { + XINE_HDMV_TRACE(" show_overlay: object %d not found !\n", cobj->object_id_ref); + return -1; + } + + /* find window */ + window_def_t *wnd = this->windows; + while (wnd && wnd->id != cobj->window_id_ref) + wnd = wnd->next; + if (!wnd) { + XINE_HDMV_TRACE(" show_overlay: window %d not found !\n", cobj->window_id_ref); + return -1; + } + + /* do not show again if all elements are unchanged */ + if (!force_update && clut->shown && obj->shown && wnd->shown && cobj->shown) + return 0; + clut->shown = obj->shown = wnd->shown = cobj->shown = 1; + + /* copy palette to xine overlay */ + overlay.rgb_clut = 0; + memcpy(overlay.color, clut->color, sizeof(uint32_t) * 256); + memcpy(overlay.trans, clut->trans, sizeof(uint8_t) * 256); + + /* copy and crop RLE image to xine overlay */ + overlay.width = obj->width; + overlay.height = obj->height; + + overlay.rle = copy_crop_rle (obj, cobj); + overlay.num_rle = obj->num_rle; + overlay.data_size = obj->num_rle * sizeof(rle_elem_t); + + /* */ + + overlay.x = /*wnd->xpos +*/ cobj->xpos; + overlay.y = /*wnd->ypos +*/ cobj->ypos; + + overlay.unscaled = 0; + overlay.hili_top = -1; + overlay.hili_bottom = -1; + overlay.hili_left = -1; + overlay.hili_right = -1; + + XINE_HDMV_TRACE(" -> overlay: %d,%d %dx%d\n", + overlay.x, overlay.y, overlay.width, overlay.height); + + + /* set timings */ + + if (pts > 0) + event.vpts = metronom->got_spu_packet (metronom, pts); + else + event.vpts = 0; + + + /* generate SHOW event */ + + this->stream->video_out->enable_ovl(this->stream->video_out, 1); + + if (this->overlay_handles[overlay_index] < 0) + this->overlay_handles[overlay_index] = ovl_manager->get_handle(ovl_manager, 0); + + event.event_type = OVERLAY_EVENT_SHOW; + event.object.handle = this->overlay_handles[overlay_index]; + event.object.overlay = &overlay; + event.object.object_type = 0; /* subtitle */ + + ovl_manager->add_event (ovl_manager, (void *)&event); + + return 0; +} + +static void hide_overlays(spuhdmv_decoder_t *this, int64_t pts) +{ + video_overlay_event_t event = {0}; + int i = 0; + + while (this->overlay_handles[i] >= 0) { + XINE_HDMV_TRACE(" -> HIDE %d\n", i); + + video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); + metronom_t *metronom = this->stream->metronom; + + event.object.handle = this->overlay_handles[i]; + if (this) + event.vpts = metronom->got_spu_packet (metronom, pts); + else + event.vpts = 0; + event.event_type = OVERLAY_EVENT_HIDE; + event.object.overlay = NULL; + ovl_manager->add_event (ovl_manager, (void *)&event); + + //this->overlay_handles[i] = -1; + i++; + } +} + +static void update_overlays(spuhdmv_decoder_t *this) +{ + presentation_segment_t *pseg = this->segments; + + while (pseg) { + + if (!pseg->comp_descr.state) { + + /* HIDE */ + if (!pseg->shown) + hide_overlays (this, pseg->pts); + + } else { + + /* SHOW */ + composition_object_t *cobj = pseg->comp_objs; + int i; + + for (i = 0; i < pseg->object_number; i++) { + if (!cobj) { + XINE_HDMV_ERROR("show_overlays: composition object %d missing !\n", i); + } else { + show_overlay(this, cobj, pseg->palette_id_ref, i, pseg->pts, !pseg->shown); + cobj = cobj->next; + } + } + } + + pseg->shown = 1; + + pseg = pseg->next; + } +} + +static void free_objs(spuhdmv_decoder_t *this) +{ + LIST_DESTROY (this->cluts, free); + LIST_DESTROY (this->objects, free_subtitle_object); + LIST_DESTROY (this->windows, free); + LIST_DESTROY (this->segments, free_presentation_segment); +} + +static void decode_segment(spuhdmv_decoder_t *this) +{ + XINE_HDMV_TRACE("*** new segment, pts %010ld: 0x%02x (%8d bytes)", + this->pts, this->buf->segment_type, this->buf->segment_len); + + switch (this->buf->segment_type) { + case 0x14: + XINE_HDMV_TRACE(" segment: PALETTE\n"); + decode_palette(this); + break; + case 0x15: + XINE_HDMV_TRACE(" segment: OBJECT\n"); + decode_object(this); + break; + case 0x16: + XINE_HDMV_TRACE(" segment: PRESENTATION SEGMENT\n"); + decode_presentation_segment(this); + break; + case 0x17: + XINE_HDMV_TRACE(" segment: WINDOW DEFINITION\n"); + decode_window_definition(this); + break; + case 0x18: + XINE_HDMV_TRACE(" segment: INTERACTIVE\n"); + break; + case 0x80: + XINE_HDMV_TRACE(" segment: END OF DISPLAY\n"); + /* drop all cached objects */ + free_objs(this); + break; + default: + XINE_HDMV_ERROR(" segment type 0x%x unknown, skipping\n", this->buf->segment_type); + break; + } + if (this->buf->error) { + XINE_HDMV_ERROR("*** DECODE ERROR ***\n"); + } + + update_overlays (this); +} + +static void close_osd(spuhdmv_decoder_t *this) +{ + video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out); + + int i = 0; + while (this->overlay_handles[i] >= 0) { + ovl_manager->free_handle(ovl_manager, this->overlay_handles[i]); + this->overlay_handles[i] = -1; + i++; + } +} + +static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + if ((buf->type & 0xffff0000) != BUF_SPU_HDMV) + return; + + if (buf->size < 1) + return; + + if (buf->pts) + this->pts = buf->pts; + +#ifdef DUMP_SPU_DATA + int i; + for(i = 0; i < buf->size; i++) + printf(" %02x", buf->content[i]); + printf("\n"); +#endif + + segbuf_fill(this->buf, buf->content, buf->size); + + while (segbuf_segment_complete(this->buf)) { + decode_segment(this); + segbuf_skip_segment(this->buf); + } +} + +static void spudec_reset (spu_decoder_t * this_gen) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + if (this->buf) + segbuf_reset(this->buf); + + free_objs(this); + + close_osd(this); +} + +static void spudec_discontinuity (spu_decoder_t *this_gen) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + close_osd(this); +} + +static void spudec_dispose (spu_decoder_t *this_gen) +{ + spuhdmv_decoder_t *this = (spuhdmv_decoder_t *) this_gen; + + close_osd (this); + segbuf_dispose (this->buf); + + free_objs(this); + + free (this); +} + +static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t *stream) +{ + spuhdmv_decoder_t *this; + + this = (spuhdmv_decoder_t *) calloc(1, sizeof (spuhdmv_decoder_t)); + + this->spu_decoder.decode_data = spudec_decode_data; + this->spu_decoder.reset = spudec_reset; + this->spu_decoder.discontinuity = spudec_discontinuity; + this->spu_decoder.dispose = spudec_dispose; + this->spu_decoder.get_interact_info = NULL; + this->spu_decoder.set_button = NULL; + this->stream = stream; + this->class = (spuhdmv_class_t *) class_gen; + + this->buf = segbuf_init(); + + memset(this->overlay_handles, 0xff, sizeof(this->overlay_handles)); /* --> -1 */ + + return &this->spu_decoder; +} + +static char *get_identifier (spu_decoder_class_t *this) +{ + return "spuhdmv"; +} + +static char *get_description (spu_decoder_class_t *this) +{ + return "HDMV/BluRay bitmap SPU decoder plugin"; +} + +static void dispose_class (spu_decoder_class_t *this) +{ + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) +{ + spuhdmv_class_t *this; + + this = calloc(1, sizeof (spuhdmv_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +/* plugin catalog information */ +static uint32_t supported_types[] = { BUF_SPU_HDMV, 0 }; + +static const decoder_info_t dec_info_data = { + supported_types, /* supported types */ + 5 /* priority */ +}; + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_SPU_DECODER, 16, "spuhdmv", XINE_VERSION_CODE, &dec_info_data, &init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/libsputext/Makefile.am b/src/libsputext/Makefile.am index 4f03d7fa9..ad6c1b776 100644 --- a/src/libsputext/Makefile.am +++ b/src/libsputext/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_LDFLAGS = $(xineplug_ldflags) @@ -8,6 +9,6 @@ xineplug_dmx_sputext_la_SOURCES = demux_sputext.c xineplug_dmx_sputext_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_dmx_sputext_la_CFLAGS = $(VISIBILITY_FLAG) -xineplug_decode_sputext_la_SOURCES = xine_sputext_decoder.c +xineplug_decode_sputext_la_SOURCES = xine_sputext_decoder.c xineplug_decode_sputext_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) xineplug_decode_sputext_la_CFLAGS = $(VISIBILITY_FLAG) diff --git a/src/libsputext/demux_sputext.c b/src/libsputext/demux_sputext.c index acf8e10f6..b0e1299d9 100644 --- a/src/libsputext/demux_sputext.c +++ b/src/libsputext/demux_sputext.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -67,7 +67,7 @@ typedef struct { long start; /* csecs */ long end; /* csecs */ - + char *text[SUB_MAX_TEXT]; } subtitle_t; @@ -84,10 +84,10 @@ typedef struct { char buf[SUB_BUFSIZE]; off_t buflen; - float mpsub_position; + float mpsub_position; - int uses_time; - int errs; + int uses_time; + int errs; subtitle_t *subtitles; int num; /* number of subtitle structs */ int cur; /* current subtitle */ @@ -117,8 +117,8 @@ typedef struct demux_sputext_class_s { #define FORMAT_RT 5 #define FORMAT_SSA 6 /* Sub Station Alpha */ #define FORMAT_PJS 7 -#define FORMAT_MPSUB 8 -#define FORMAT_AQTITLE 9 +#define FORMAT_MPSUB 8 +#define FORMAT_AQTITLE 9 #define FORMAT_JACOBSUB 10 #define FORMAT_SUBVIEWER2 11 #define FORMAT_SUBRIP09 12 @@ -129,7 +129,6 @@ static int eol(char p) { } static inline void trail_space(char *s) { - int i; while (isspace(*s)) { char *copy = s; do { @@ -137,8 +136,8 @@ static inline void trail_space(char *s) { copy++; } while(*copy); } - i = strlen(s) - 1; - while (i > 0 && isspace(s[i])) + size_t i = strlen(s) - 1; + while (i > 0 && isspace(s[i])) s[i--] = '\0'; } @@ -147,26 +146,24 @@ static inline void trail_space(char *s) { */ static char *read_line_from_input(demux_sputext_t *this, char *line, off_t len) { off_t nread = 0; - char *s; - int linelen; - - if ((len - this->buflen) > 512) { - if((nread = this->input->read(this->input, + + if ((len - this->buflen) > 512 && len < SUB_BUFSIZE) { + if((nread = this->input->read(this->input, &this->buf[this->buflen], len - this->buflen)) < 0) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "read failed.\n"); return NULL; } } - + this->buflen += nread; this->buf[this->buflen] = '\0'; - s = strchr(this->buf, '\n'); + char *s = strchr(this->buf, '\n'); if (line && (s || this->buflen)) { - - linelen = s ? (s - this->buf) + 1 : this->buflen; - + + size_t linelen = s ? (s - this->buf) + 1 : this->buflen; + memcpy(line, this->buf, linelen); line[linelen] = '\0'; @@ -184,21 +181,20 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *this, subtitle_t *current static char line[LINE_LEN + 1]; static char *s = NULL; - char text[LINE_LEN + 1], *p, *q; - int state; + char text[LINE_LEN + 1]; - p = NULL; + char *p = NULL; current->lines = current->start = 0; current->end = -1; - state = 0; - + int state = 0; + /* read the first line */ if (!s) if (!(s = read_line_from_input(this, line, LINE_LEN))) return 0; - + do { switch (state) { - + case 0: /* find "START=" */ s = strstr (s, "Start="); if (s) { @@ -206,15 +202,15 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *this, subtitle_t *current state = 1; continue; } break; - + case 1: /* find "<P" */ if ((s = strstr (s, "<P"))) { s += 2; state = 2; continue; } break; - + case 2: /* find ">" */ if ((s = strchr (s, '>'))) { s++; state = 3; p = text; continue; } break; - + case 3: /* get all text until '<' appears */ if (*s == '\0') { break; } else if (*s == '<') { state = 4; } @@ -228,50 +224,47 @@ static subtitle_t *sub_read_line_sami(demux_sputext_t *this, subtitle_t *current } else *p++ = *s++; continue; - + case 4: /* get current->end or skip <TAG> */ - q = strstr (s, "Start="); - if (q) { - current->end = strtol (q + 6, &q, 0) / 10 - 1; - *p = '\0'; trail_space (text); - if (text[0] != '\0') - current->text[current->lines++] = strdup (text); - if (current->lines > 0) { state = 99; break; } - state = 0; continue; + { + char *q = strstr (s, "Start="); + if (q) { + current->end = strtol (q + 6, &q, 0) / 10 - 1; + *p = '\0'; trail_space (text); + if (text[0] != '\0') + current->text[current->lines++] = strdup (text); + if (current->lines > 0) { state = 99; break; } + state = 0; continue; + } } s = strchr (s, '>'); if (s) { s++; state = 3; continue; } break; } - + /* read next line */ - if (state != 99 && !(s = read_line_from_input (this, line, LINE_LEN))) + if (state != 99 && !(s = read_line_from_input (this, line, LINE_LEN))) return 0; - + } while (state != 99); - + return current; } static char *sub_readtext(char *source, char **dest) { - int len=0; + size_t len=0; char *p=source; - + while ( !eol(*p) && *p!= '|' ) { p++,len++; } - - *dest= (char *)xine_xmalloc (len+1); - if (!dest) - return ERR; - - strncpy(*dest, source, len); - (*dest)[len]=0; - + + *dest = strndup(source, len); + while (*p=='\r' || *p=='\n' || *p=='|') p++; - + if (*p) return p; /* not-last text field */ else return NULL; /* last text field */ } @@ -280,63 +273,62 @@ static subtitle_t *sub_read_line_microdvd(demux_sputext_t *this, subtitle_t *cur char line[LINE_LEN + 1]; char line2[LINE_LEN + 1]; - char *p, *next; - int i; - + memset (current, 0, sizeof(subtitle_t)); - + current->end=-1; do { if (!read_line_from_input (this, line, LINE_LEN)) return NULL; } while ((sscanf (line, "{%ld}{}%" LINE_LEN_QUOT "[^\r\n]", &(current->start), line2) !=2) && (sscanf (line, "{%ld}{%ld}%" LINE_LEN_QUOT "[^\r\n]", &(current->start), &(current->end),line2) !=3) ); - - p=line2; - - next=p, i=0; + + char *p=line2; + + char *next=p; + size_t i=0; while ((next =sub_readtext (next, &(current->text[i])))) { if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; } } current->lines= ++i; - + return current; } static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN + 1]; - int a1,a2,a3,a4,b1,b2,b3,b4; - char *p=NULL, *q=NULL; - int len; - + memset (current, 0, sizeof(subtitle_t)); - + while (1) { if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) { - if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) - continue; + + { + int a1,a2,a3,a4,b1,b2,b3,b4; + if (sscanf (line, "%d:%d:%d.%d,%d:%d:%d.%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) { + if (sscanf (line, "%d:%d:%d,%d,%d:%d:%d,%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4) < 8) + continue; + } + + current->start = a1*360000+a2*6000+a3*100+a4; + current->end = b1*360000+b2*6000+b3*100+b4; } - current->start = a1*360000+a2*6000+a3*100+a4; - current->end = b1*360000+b2*6000+b3*100+b4; - + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - - p=q=line; + + char *p = line, *q = line; for (current->lines=1; current->lines <= SUB_MAX_TEXT; current->lines++) { + size_t len; for (q=p,len=0; *p && *p!='\r' && *p!='\n' && *p!='|' && strncasecmp(p,"[br]",4); p++,len++); - current->text[current->lines-1]=(char *)xine_xmalloc (len+1); + current->text[current->lines-1] = strndup(q, len); if (!current->text[current->lines-1]) return ERR; - strncpy (current->text[current->lines-1], q, len); - current->text[current->lines-1][len]='\0'; if (!*p || *p=='\r' || *p=='\n') break; if (*p=='[') while (*p++!=']'); if (*p=='|') p++; @@ -348,25 +340,27 @@ static subtitle_t *sub_read_line_subviewer(demux_sputext_t *this, subtitle_t *cu } static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *current) { - char line[LINE_LEN + 1]; - int a1,a2,a3,a4,b1,b2,b3,b4; - int i,end_sub; - memset(current,0,sizeof(subtitle_t)); - do { - if(!read_line_from_input(this,line,LINE_LEN)) - return NULL; - i = sscanf(line,"%d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4); - } while(i < 8); - current->start = a1*360000+a2*6000+a3*100+a4/10; - current->end = b1*360000+b2*6000+b3*100+b4/10; - i=0; - end_sub=0; + + { + int a1,a2,a3,a4,b1,b2,b3,b4,i; + do { + char line[LINE_LEN + 1]; + if(!read_line_from_input(this,line,LINE_LEN)) + return NULL; + i = sscanf(line,"%d:%d:%d%*[,.]%d --> %d:%d:%d%*[,.]%d",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4); + } while(i < 8); + current->start = a1*360000+a2*6000+a3*100+a4/10; + current->end = b1*360000+b2*6000+b3*100+b4/10; + } + + int i=0; + int end_sub=0; do { char *p; /* pointer to the curently read char */ - char temp_line[SUB_BUFSIZE]; /* subtitle line that will be transfered to current->text[i] */ - int temp_index; /* ... and its index wich 'points' to the first EMPTY place -> last read char is at temp_index-1 if temp_index>0 */ - temp_line[SUB_BUFSIZE-1]='\0'; /* just in case... */ + char line[LINE_LEN + 1]; + char temp_line[SUB_BUFSIZE] = { 0, }; /* subtitle line that will be transfered to current->text[i] */ + size_t temp_index; /* ... and its index wich 'points' to the first EMPTY place -> last read char is at temp_index-1 if temp_index>0 */ if(!read_line_from_input(this,line,LINE_LEN)) { if(i) break; /* if something was read, transmit it */ @@ -396,10 +390,10 @@ static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *curren xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many characters in a subtitle line\n"); if(temp_line[temp_index-1]=='\0' || temp_index==SUB_BUFSIZE) { if(temp_index>1) { /* more than 1 char (including '\0') -> that is a valid one */ - current->text[i]=(char *)xine_xmalloc(temp_index); + /* temp_index<=SUB_BUFSIZE is always true here */ + current->text[i] = strndup(temp_line, temp_index); if(!current->text[i]) return ERR; - strncpy(current->text[i],temp_line,temp_index); /* temp_index<=SUB_BUFSIZE is always true here */ i++; temp_index=0; } else @@ -416,12 +410,9 @@ static subtitle_t *sub_read_line_subrip(demux_sputext_t *this,subtitle_t *curren static subtitle_t *sub_read_line_vplayer(demux_sputext_t *this,subtitle_t *current) { char line[LINE_LEN + 1]; - int a1,a2,a3,b1,b2,b3; - char *p=NULL, *next, *p2; - int i; - + memset (current, 0, sizeof(subtitle_t)); - + while (!current->text[0]) { if( this->next_line[0] == '\0' ) { /* if the buffer is empty.... */ if( !read_line_from_input(this, line, LINE_LEN) ) return NULL; @@ -436,29 +427,37 @@ static subtitle_t *sub_read_line_vplayer(demux_sputext_t *this,subtitle_t *curre this->next_line[0] = '\0'; return NULL; } - if( (sscanf( line, "%d:%d:%d:", &a1, &a2, &a3) < 3) || - (sscanf( this->next_line, "%d:%d:%d:", &b1, &b2, &b3) < 3) ) - continue; - current->start = a1*360000+a2*6000+a3*100; - current->end = b1*360000+b2*6000+b3*100; - if ((current->end - current->start) > LINE_LEN) + + { + int a1,a2,a3,b1,b2,b3; + if( (sscanf( line, "%d:%d:%d:", &a1, &a2, &a3) < 3) || + (sscanf( this->next_line, "%d:%d:%d:", &b1, &b2, &b3) < 3) ) + continue; + current->start = a1*360000+a2*6000+a3*100; + current->end = b1*360000+b2*6000+b3*100; + } + + if ((current->end - current->start) > LINE_LEN) current->end = current->start + LINE_LEN; /* not too long though. */ /* teraz czas na wkopiowanie stringu */ - p=line; + char *p=line; /* finds the body of the subtitle_t */ - for (i=0; i<3; i++){ - p2=strchr( p, ':'); - if( p2 == NULL ) break; - p=p2+1; - } - - next=p; - i=0; + { + int i; + for (i=0; i<3; i++){ + char *p2=strchr( p, ':'); + if( p2 == NULL ) break; + p=p2+1; + } + } + + char *next=p; + int i=0; while( (next = sub_readtext( next, &(current->text[i]))) ) { - if (current->text[i]==ERR) + if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; @@ -471,44 +470,49 @@ static subtitle_t *sub_read_line_vplayer(demux_sputext_t *this,subtitle_t *curre static subtitle_t *sub_read_line_rt(demux_sputext_t *this,subtitle_t *current) { /* - * TODO: This format uses quite rich (sub/super)set of xhtml + * TODO: This format uses quite rich (sub/super)set of xhtml * I couldn't check it since DTD is not included. - * WARNING: full XML parses can be required for proper parsing + * WARNING: full XML parses can be required for proper parsing */ - char line[LINE_LEN + 1]; - int a1,a2,a3,a4,b1,b2,b3,b4; - char *p=NULL,*next=NULL; - int i,len,plen; - memset (current, 0, sizeof(subtitle_t)); - + while (!current->text[0]) { + char line[LINE_LEN + 1]; if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + + char *p = line; /* * TODO: it seems that format of time is not easily determined, it may be 1:12, 1:12.0 or 0:1:12.0 * to describe the same moment in time. Maybe there are even more formats in use. */ - if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8) - - plen=a1=a2=a3=a4=b1=b2=b3=b4=0; - if ( - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&plen)) < 4) && - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&b4,&plen)) < 5) && - /* ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&plen)) < 5) && */ - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&b4,&plen)) < 6) && - ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d:%d.%d\" %*[Ee]nd=\"%d:%d:%d.%d\"%*[^<]<clear/>%n",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen)) < 8) - ) - continue; - current->start = a1*360000+a2*6000+a3*100+a4/10; - current->end = b1*360000+b2*6000+b3*100+b4/10; - p=line; p+=plen;i=0; + { + int a1,a2,a3,a4,b1,b2,b3,b4,len,plen; + if ((len=sscanf (line, "<Time Begin=\"%d:%d:%d.%d\" End=\"%d:%d:%d.%d\"",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4)) < 8) + + a1=a2=a3=a4=b1=b2=b3=b4=0; + if ( + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&plen)) < 4) && + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&b2,&b3,&b4,&plen)) < 5) && + /* ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&plen)) < 5) && */ + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d.%d\" %*[Ee]nd=\"%d:%d.%d\"%*[^<]<clear/>%n",&a2,&a3,&a4,&b2,&b3,&b4,&plen)) < 6) && + ((len=sscanf (line, "<%*[tT]ime %*[bB]egin=\"%d:%d:%d.%d\" %*[Ee]nd=\"%d:%d:%d.%d\"%*[^<]<clear/>%n",&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&plen)) < 8) + ) + continue; + + current->start = a1*360000+a2*6000+a3*100+a4/10; + current->end = b1*360000+b2*6000+b3*100+b4/10; + + p += plen; + } + + int i=0; /* TODO: I don't know what kind of convention is here for marking multiline subs, maybe <br/> like in xml? */ - next = strstr(line,"<clear/>")+8;i=0; + char *next = strstr(line,"<clear/>")+8;i=0; while ((next =sub_readtext (next, &(current->text[i])))) { - if (current->text[i]==ERR) + if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; @@ -520,61 +524,63 @@ static subtitle_t *sub_read_line_rt(demux_sputext_t *this,subtitle_t *current) { } static subtitle_t *sub_read_line_ssa(demux_sputext_t *this,subtitle_t *current) { - int comma; static int max_comma = 32; /* let's use 32 for the case that the */ /* amount of commas increase with newer SSA versions */ - + int hour1, min1, sec1, hunsec1, hour2, min2, sec2, hunsec2, nothing; - int num; - char line[LINE_LEN + 1], line3[LINE_LEN + 1], *line2; - char *tmp; - - do { - if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - } while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d," - "%[^\n\r]", ¬hing, - &hour1, &min1, &sec1, &hunsec1, - &hour2, &min2, &sec2, &hunsec2, - line3) < 9 - && - sscanf (line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d," - "%[^\n\r]", ¬hing, - &hour1, &min1, &sec1, &hunsec1, - &hour2, &min2, &sec2, &hunsec2, - line3) < 9 ); - - line2=strchr(line3, ','); - - for (comma = 4; comma < max_comma; comma ++) - { - tmp = line2; - if(!(tmp=strchr(++tmp, ','))) break; - if(*(++tmp) == ' ') break; - /* a space after a comma means we're already in a sentence */ - line2 = tmp; - } - + char line3[LINE_LEN + 1]; + + { + char line[LINE_LEN + 1]; + do { + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + } while (sscanf (line, "Dialogue: Marked=%d,%d:%d:%d.%d,%d:%d:%d.%d," + "%[^\n\r]", ¬hing, + &hour1, &min1, &sec1, &hunsec1, + &hour2, &min2, &sec2, &hunsec2, + line3) < 9 + && + sscanf (line, "Dialogue: %d,%d:%d:%d.%d,%d:%d:%d.%d," + "%[^\n\r]", ¬hing, + &hour1, &min1, &sec1, &hunsec1, + &hour2, &min2, &sec2, &hunsec2, + line3) < 9 ); + } + + char *line2=strchr(line3, ','); + if (!line2) + return NULL; + + int comma; + for (comma = 4; comma < max_comma; comma ++) { + char *tmp = line2; + if(!(tmp=strchr(++tmp, ','))) break; + if(*(++tmp) == ' ') break; + /* a space after a comma means we're already in a sentence */ + line2 = tmp; + } + if(comma < max_comma)max_comma = comma; /* eliminate the trailing comma */ if(*line2 == ',') line2++; - - current->lines=0;num=0; + + current->lines=0; current->start = 360000*hour1 + 6000*min1 + 100*sec1 + hunsec1; current->end = 360000*hour2 + 6000*min2 + 100*sec2 + hunsec2; - + + int num=0; + char *tmp; while (((tmp=strstr(line2, "\\n")) != NULL) || ((tmp=strstr(line2, "\\N")) != NULL) ){ - current->text[num]=(char *)malloc(tmp-line2+1); - strncpy (current->text[num], line2, tmp-line2); - current->text[num][tmp-line2]='\0'; + current->text[num] = strndup(line2, tmp-line2); line2=tmp+2; num++; current->lines++; if (current->lines >= SUB_MAX_TEXT) return current; } - + current->text[num]=strdup(line2); current->lines++; - + return current; } @@ -591,11 +597,10 @@ static subtitle_t *sub_read_line_ssa(demux_sputext_t *this,subtitle_t *current) static subtitle_t *sub_read_line_pjs (demux_sputext_t *this, subtitle_t *current) { char line[LINE_LEN + 1]; - char text[LINE_LEN + 1]; - char *s, *d; - + char *s; + memset (current, 0, sizeof(subtitle_t)); - + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; for (s = line; *s && isspace(*s); s++); @@ -607,7 +612,7 @@ static subtitle_t *sub_read_line_pjs (demux_sputext_t *this, subtitle_t *current /* the files I have are in tenths of second */ current->start *= 10; current->end *= 10; - + /* walk to the beggining of the string */ for (; *s; s++) if (*s==',') break; if (*s) { @@ -618,56 +623,57 @@ static subtitle_t *sub_read_line_pjs (demux_sputext_t *this, subtitle_t *current return ERR; } /* copy the string to the text buffer */ + char text[LINE_LEN + 1]; + char *d = NULL; for (s++, d=text; *s && *s!='"'; s++, d++) *d=*s; *d=0; current->text[0] = strdup(text); current->lines = 1; - + return current; } static subtitle_t *sub_read_line_mpsub (demux_sputext_t *this, subtitle_t *current) { char line[LINE_LEN + 1]; - float a,b; - int num=0; - char *p, *q; - - do { - if (!read_line_from_input(this, line, LINE_LEN)) - return NULL; - } while (sscanf (line, "%f %f", &a, &b) !=2); - this->mpsub_position += (a*100.0); - current->start = (int) this->mpsub_position; - this->mpsub_position += (b*100.0); - current->end = (int) this->mpsub_position; - + { + float a,b; + do { + if (!read_line_from_input(this, line, LINE_LEN)) + return NULL; + } while (sscanf (line, "%f %f", &a, &b) !=2); + + this->mpsub_position += (a*100.0); + current->start = (int) this->mpsub_position; + this->mpsub_position += (b*100.0); + current->end = (int) this->mpsub_position; + } + + int num = 0; while (num < SUB_MAX_TEXT) { - if (!read_line_from_input(this, line, LINE_LEN)) + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - p=line; - while (isspace(*p)) + char *p=line; + while (isspace(*p)) p++; - if (eol(*p) && num > 0) + if (eol(*p) && num > 0) return current; - if (eol(*p)) + if (eol(*p)) return NULL; - + + char *q; for (q=p; !eol(*q); q++); *q='\0'; - if (strlen(p)) { + if (*p) { current->text[num]=strdup(p); xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, ">%s<\n",p); current->lines = ++num; } else { - if (num) - return current; - else - return NULL; + return num ? current : NULL; } } @@ -675,299 +681,296 @@ static subtitle_t *sub_read_line_mpsub (demux_sputext_t *this, subtitle_t *curre } static subtitle_t *sub_read_line_aqt (demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN + 1]; - memset (current, 0, sizeof(subtitle_t)); while (1) { + char line[LINE_LEN + 1]; /* try to locate next subtitle_t */ if (!read_line_from_input(this, line, LINE_LEN)) return NULL; if (!(sscanf (line, "-->> %ld", &(current->start)) <1)) break; } - + + char line[LINE_LEN + 1]; if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - + sub_readtext((char *) &line,¤t->text[0]); current->lines = 1; current->end = -1; - + if (!read_line_from_input(this, line, LINE_LEN)) return current;; - + sub_readtext((char *) &line,¤t->text[1]); current->lines = 2; - + if ((current->text[0][0]==0) && (current->text[1][0]==0)) { return NULL; } - + return current; } static subtitle_t *sub_read_line_jacobsub(demux_sputext_t *this, subtitle_t *current) { - char line1[LINE_LEN], line2[LINE_LEN], directive[LINE_LEN], *p, *q; - unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0; - static unsigned jacoTimeres = 30; - static int jacoShift = 0; - - memset(current, 0, sizeof(subtitle_t)); - memset(line1, 0, LINE_LEN); - memset(line2, 0, LINE_LEN); - memset(directive, 0, LINE_LEN); - while (!current->text[0]) { - if (!read_line_from_input(this, line1, LINE_LEN)) { - return NULL; - } - if (sscanf - (line1, "%u:%u:%u.%u %u:%u:%u.%u %" LINE_LEN_QUOT "[^\n\r]", &a1, &a2, &a3, &a4, - &b1, &b2, &b3, &b4, line2) < 9) { - if (sscanf(line1, "@%u @%u %" LINE_LEN_QUOT "[^\n\r]", &a4, &b4, line2) < 3) { - if (line1[0] == '#') { - int hours = 0, minutes = 0, seconds, delta, inverter = - 1; - unsigned units = jacoShift; - switch (toupper(line1[1])) { - case 'S': - if (isalpha(line1[2])) { - delta = 6; - } else { - delta = 2; - } - if (sscanf(&line1[delta], "%d", &hours)) { - if (hours < 0) { - hours *= -1; - inverter = -1; - } - if (sscanf(&line1[delta], "%*d:%d", &minutes)) { - if (sscanf - (&line1[delta], "%*d:%*d:%d", - &seconds)) { - sscanf(&line1[delta], "%*d:%*d:%*d.%d", - &units); - } else { - hours = 0; - sscanf(&line1[delta], "%d:%d.%d", - &minutes, &seconds, &units); - minutes *= inverter; - } - } else { - hours = minutes = 0; - sscanf(&line1[delta], "%d.%d", &seconds, - &units); - seconds *= inverter; - } - jacoShift = - ((hours * 3600 + minutes * 60 + - seconds) * jacoTimeres + - units) * inverter; - } - break; - case 'T': - if (isalpha(line1[2])) { - delta = 8; - } else { - delta = 2; - } - sscanf(&line1[delta], "%u", &jacoTimeres); - break; - } - } - continue; + char line1[LINE_LEN] = { 0, }, line2[LINE_LEN] = { 0, }, directive[LINE_LEN] = { 0, }, *p, *q; + unsigned a1, a2, a3, a4, b1, b2, b3, b4, comment = 0; + static unsigned jacoTimeres = 30; + static int jacoShift = 0; + + memset(current, 0, sizeof(subtitle_t)); + while (!current->text[0]) { + if (!read_line_from_input(this, line1, LINE_LEN)) { + return NULL; + } + if (sscanf + (line1, "%u:%u:%u.%u %u:%u:%u.%u %" LINE_LEN_QUOT "[^\n\r]", &a1, &a2, &a3, &a4, + &b1, &b2, &b3, &b4, line2) < 9) { + if (sscanf(line1, "@%u @%u %" LINE_LEN_QUOT "[^\n\r]", &a4, &b4, line2) < 3) { + if (line1[0] == '#') { + int hours = 0, minutes = 0, seconds, delta, inverter = + 1; + unsigned units = jacoShift; + switch (toupper(line1[1])) { + case 'S': + if (isalpha(line1[2])) { + delta = 6; } else { - current->start = - (unsigned long) ((a4 + jacoShift) * 100.0 / - jacoTimeres); - current->end = - (unsigned long) ((b4 + jacoShift) * 100.0 / - jacoTimeres); - } - } else { - current->start = - (unsigned - long) (((a1 * 3600 + a2 * 60 + a3) * jacoTimeres + a4 + - jacoShift) * 100.0 / jacoTimeres); - current->end = - (unsigned - long) (((b1 * 3600 + b2 * 60 + b3) * jacoTimeres + b4 + - jacoShift) * 100.0 / jacoTimeres); - } - current->lines = 0; - p = line2; - while ((*p == ' ') || (*p == '\t')) { - ++p; - } - if (isalpha(*p)||*p == '[') { - int cont, jLength; - - if (sscanf(p, "%s %" LINE_LEN_QUOT "[^\n\r]", directive, line1) < 2) - return ERR; - jLength = strlen(directive); - for (cont = 0; cont < jLength; ++cont) { - if (isalpha(*(directive + cont))) - *(directive + cont) = toupper(*(directive + cont)); + delta = 2; } - if ((strstr(directive, "RDB") != NULL) - || (strstr(directive, "RDC") != NULL) - || (strstr(directive, "RLB") != NULL) - || (strstr(directive, "RLG") != NULL)) { - continue; + if (sscanf(&line1[delta], "%d", &hours)) { + if (hours < 0) { + hours *= -1; + inverter = -1; + } + if (sscanf(&line1[delta], "%*d:%d", &minutes)) { + if (sscanf + (&line1[delta], "%*d:%*d:%d", + &seconds)) { + sscanf(&line1[delta], "%*d:%*d:%*d.%d", + &units); + } else { + hours = 0; + sscanf(&line1[delta], "%d:%d.%d", + &minutes, &seconds, &units); + minutes *= inverter; + } + } else { + hours = minutes = 0; + sscanf(&line1[delta], "%d.%d", &seconds, + &units); + seconds *= inverter; + } + jacoShift = + ((hours * 3600 + minutes * 60 + + seconds) * jacoTimeres + + units) * inverter; } - /* no alignment */ -#if 0 - if (strstr(directive, "JL") != NULL) { - current->alignment = SUB_ALIGNMENT_HLEFT; - } else if (strstr(directive, "JR") != NULL) { - current->alignment = SUB_ALIGNMENT_HRIGHT; + break; + case 'T': + if (isalpha(line1[2])) { + delta = 8; } else { - current->alignment = SUB_ALIGNMENT_HCENTER; + delta = 2; } + sscanf(&line1[delta], "%u", &jacoTimeres); + break; + } + } + continue; + } else { + current->start = + (unsigned long) ((a4 + jacoShift) * 100.0 / + jacoTimeres); + current->end = + (unsigned long) ((b4 + jacoShift) * 100.0 / + jacoTimeres); + } + } else { + current->start = + (unsigned + long) (((a1 * 3600 + a2 * 60 + a3) * jacoTimeres + a4 + + jacoShift) * 100.0 / jacoTimeres); + current->end = + (unsigned + long) (((b1 * 3600 + b2 * 60 + b3) * jacoTimeres + b4 + + jacoShift) * 100.0 / jacoTimeres); + } + current->lines = 0; + p = line2; + while ((*p == ' ') || (*p == '\t')) { + ++p; + } + if (isalpha(*p)||*p == '[') { + if (sscanf(p, "%s %" LINE_LEN_QUOT "[^\n\r]", directive, line1) < 2) + return ERR; + if ((strcasestr(directive, "RDB") != NULL) + || (strcasestr(directive, "RDC") != NULL) + || (strcasestr(directive, "RLB") != NULL) + || (strcasestr(directive, "RLG") != NULL)) { + continue; + } + /* no alignment */ +#if 0 + if (strcasestr(directive, "JL") != NULL) { + current->alignment = SUB_ALIGNMENT_HLEFT; + } else if (strcasestr(directive, "JR") != NULL) { + current->alignment = SUB_ALIGNMENT_HRIGHT; + } else { + current->alignment = SUB_ALIGNMENT_HCENTER; + } #endif - strcpy(line2, line1); - p = line2; + strcpy(line2, line1); + p = line2; + } + for (q = line1; (!eol(*p)) && (current->lines < SUB_MAX_TEXT); ++p) { + switch (*p) { + case '{': + comment++; + break; + case '}': + if (comment) { + --comment; + /* the next line to get rid of a blank after the comment */ + if ((*(p + 1)) == ' ') + p++; } - for (q = line1; (!eol(*p)) && (current->lines < SUB_MAX_TEXT); ++p) { - switch (*p) { - case '{': - comment++; - break; - case '}': - if (comment) { - --comment; - /* the next line to get rid of a blank after the comment */ - if ((*(p + 1)) == ' ') - p++; - } - break; - case '~': - if (!comment) { - *q = ' '; - ++q; - } - break; - case ' ': - case '\t': - if ((*(p + 1) == ' ') || (*(p + 1) == '\t')) - break; - if (!comment) { - *q = ' '; - ++q; - } - break; - case '\\': - if (*(p + 1) == 'n') { - *q = '\0'; - q = line1; - current->text[current->lines++] = strdup(line1); - ++p; - break; - } - if ((toupper(*(p + 1)) == 'C') - || (toupper(*(p + 1)) == 'F')) { - ++p,++p; - break; - } - if ((*(p + 1) == 'B') || (*(p + 1) == 'b') || - /* actually this means "insert current date here" */ - (*(p + 1) == 'D') || - (*(p + 1) == 'I') || (*(p + 1) == 'i') || - (*(p + 1) == 'N') || - /* actually this means "insert current time here" */ - (*(p + 1) == 'T') || - (*(p + 1) == 'U') || (*(p + 1) == 'u')) { - ++p; - break; - } - if ((*(p + 1) == '\\') || - (*(p + 1) == '~') || (*(p + 1) == '{')) { - ++p; - } else if (eol(*(p + 1))) { - if (!read_line_from_input(this, directive, LINE_LEN)) - return NULL; - trail_space(directive); - strncat(line2, directive, - ((LINE_LEN > 511) ? LINE_LEN-1 : 511) - - strlen(line2)); - break; - } - default: - if (!comment) { - *q = *p; - ++q; - } - } + break; + case '~': + if (!comment) { + *q = ' '; + ++q; + } + break; + case ' ': + case '\t': + if ((*(p + 1) == ' ') || (*(p + 1) == '\t')) + break; + if (!comment) { + *q = ' '; + ++q; + } + break; + case '\\': + if (*(p + 1) == 'n') { + *q = '\0'; + q = line1; + current->text[current->lines++] = strdup(line1); + ++p; + break; + } + if ((toupper(*(p + 1)) == 'C') + || (toupper(*(p + 1)) == 'F')) { + ++p,++p; + break; + } + if ((*(p + 1) == 'B') || (*(p + 1) == 'b') || + /* actually this means "insert current date here" */ + (*(p + 1) == 'D') || + (*(p + 1) == 'I') || (*(p + 1) == 'i') || + (*(p + 1) == 'N') || + /* actually this means "insert current time here" */ + (*(p + 1) == 'T') || + (*(p + 1) == 'U') || (*(p + 1) == 'u')) { + ++p; + break; } - *q = '\0'; - current->text[current->lines] = strdup(line1); + if ((*(p + 1) == '\\') || + (*(p + 1) == '~') || (*(p + 1) == '{')) { + ++p; + } else if (eol(*(p + 1))) { + if (!read_line_from_input(this, directive, LINE_LEN)) + return NULL; + trail_space(directive); + strncat(line2, directive, + ((LINE_LEN > 511) ? LINE_LEN-1 : 511) + - strlen(line2)); + break; + } + default: + if (!comment) { + *q = *p; + ++q; + } + } } - current->lines++; - return current; + *q = '\0'; + if (current->lines < SUB_MAX_TEXT) + current->text[current->lines] = strdup(line1); + else + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); + } + current->lines++; + return current; } static subtitle_t *sub_read_line_subviewer2(demux_sputext_t *this, subtitle_t *current) { + char *p=NULL; + + while (!current->text[0]) { char line[LINE_LEN+1]; - int a1,a2,a3,a4; - char *p=NULL; - int i,len; - - while (!current->text[0]) { - if (!read_line_from_input(this, line, LINE_LEN)) return NULL; - if (line[0]!='{') - continue; - if ((len=sscanf (line, "{T %d:%d:%d:%d",&a1,&a2,&a3,&a4)) < 4) - continue; - current->start = a1*360000+a2*6000+a3*100+a4/10; - for (i=0; i<SUB_MAX_TEXT;) { - if (!read_line_from_input(this, line, LINE_LEN)) break; - if (line[0]=='}') break; - len=0; - for (p=line; *p!='\n' && *p!='\r' && *p; ++p,++len); - if (len) { - current->text[i]=(char *)malloc (len+1); - if (!current->text[i]) return ERR; - strncpy (current->text[i], line, len); current->text[i][len]='\0'; - ++i; - } else { - break; - } - } - current->lines=i; + if (!read_line_from_input(this, line, LINE_LEN)) return NULL; + if (line[0]!='{') + continue; + + { + int a1,a2,a3,a4; + const int len = sscanf (line, "{T %d:%d:%d:%d",&a1,&a2,&a3,&a4); + if (len < 4) + continue; + current->start = a1*360000+a2*6000+a3*100+a4/10; } - return current; + + int i; + for (i=0; i<SUB_MAX_TEXT;) { + if (!read_line_from_input(this, line, LINE_LEN)) break; + if (line[0]=='}') break; + size_t len=0; + for (p=line; *p!='\n' && *p!='\r' && *p; ++p,++len); + if (len) { + current->text[i] = strndup(line, len); + if (!current->text[i]) return ERR; + ++i; + } else { + break; + } + } + current->lines=i; + } + return current; } static subtitle_t *sub_read_line_subrip09 (demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN + 1]; - char *next; - int h, m, s; - int i; - memset (current, 0, sizeof(subtitle_t)); - - do { - if (!read_line_from_input (this, line, LINE_LEN)) return NULL; - } while (sscanf (line, "[%d:%d:%d]", &h, &m, &s) != 3); + int h, m, s; + { + char line[LINE_LEN + 1]; + do { + if (!read_line_from_input (this, line, LINE_LEN)) return NULL; + } while (sscanf (line, "[%d:%d:%d]", &h, &m, &s) != 3); + } + + char line[LINE_LEN + 1]; if (!read_line_from_input (this, line, LINE_LEN)) return NULL; current->start = 360000 * h + 6000 * m + 100 * s; current->end = -1; - next=line; - i=0; + char *next = line; + int i=0; while ((next = sub_readtext (next, &(current->text[i])))) { if (current->text[i]==ERR) return ERR; i++; - if (i>=SUB_MAX_TEXT) { + if (i>=SUB_MAX_TEXT) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Too many lines in a subtitle\n"); current->lines=i; return current; } } current->lines= ++i; - + return current; } @@ -976,22 +979,27 @@ static subtitle_t *sub_read_line_subrip09 (demux_sputext_t *this, subtitle_t *cu */ static subtitle_t *sub_read_line_mpl2(demux_sputext_t *this, subtitle_t *current) { - char line[LINE_LEN+1]; char line2[LINE_LEN+1]; - char *p, *next; - int i; memset (current, 0, sizeof(subtitle_t)); - do { - if (!read_line_from_input (this, line, LINE_LEN)) return NULL; - } while ((sscanf (line, + + { + char line[LINE_LEN+1]; + long start, end; + + do { + if (!read_line_from_input (this, line, LINE_LEN)) return NULL; + } while ((sscanf (line, "[%ld][%ld]%[^\r\n]", - &(current->start), &(current->end), line2) < 3)); - current->start *= 10; - current->end *= 10; - p=line2; + &start, &end, line2) < 3)); + + current->start = start * 10; + current->end = end * 10; + } + + char *p = line2, *next = p; + int i = 0; - next=p, i=0; while ((next = sub_readtext (next, &(current->text[i])))) { if (current->text[i] == ERR) {return ERR;} i++; @@ -1009,16 +1017,13 @@ static subtitle_t *sub_read_line_mpl2(demux_sputext_t *this, subtitle_t *current static int sub_autodetect (demux_sputext_t *this) { - - char line[LINE_LEN + 1]; - int i, j=0; - char p; - - while (j < 100) { - j++; + int j; + for(j = 1; j < 100; j++) { + char line[LINE_LEN + 1]; if (!read_line_from_input(this, line, LINE_LEN)) return FORMAT_UNKNOWN; + int i; if ((sscanf (line, "{%d}{}", &i)==1) || (sscanf (line, "{%d}{%d}", &i, &i)==2)) { this->uses_time=0; @@ -1045,7 +1050,7 @@ static int sub_autodetect (demux_sputext_t *this) { } if (strstr (line, "<SAMI>")) { - this->uses_time=1; + this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "sami subtitle format detected\n"); return FORMAT_SAMI; } @@ -1064,7 +1069,7 @@ static int sub_autodetect (demux_sputext_t *this) { return FORMAT_RT; } if ((!memcmp(line, "Dialogue: Marked", 16)) || (!memcmp(line, "Dialogue: ", 10))) { - this->uses_time=1; + this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "ssa subtitle format detected\n"); return FORMAT_SSA; } @@ -1074,17 +1079,20 @@ static int sub_autodetect (demux_sputext_t *this) { return FORMAT_PJS; } if (sscanf (line, "FORMAT=%d", &i) == 1) { - this->uses_time=0; + this->uses_time=0; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "mpsub subtitle format detected\n"); return FORMAT_MPSUB; } + + char p; if (sscanf (line, "FORMAT=TIM%c", &p)==1 && p=='E') { - this->uses_time=1; + this->uses_time=1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "mpsub subtitle format detected\n"); return FORMAT_MPSUB; } + if (strstr (line, "-->>")) { - this->uses_time=0; + this->uses_time=0; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "aqtitle subtitle format detected\n"); return FORMAT_AQTITLE; } @@ -1104,7 +1112,7 @@ static int sub_autodetect (demux_sputext_t *this) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subrip 0.9 subtitle format detected\n"); return FORMAT_SUBRIP09; } - + if (sscanf (line, "[%d][%d]", &i, &i) == 2) { this->uses_time = 1; xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "mpl2 subtitle format detected\n"); @@ -1116,9 +1124,6 @@ static int sub_autodetect (demux_sputext_t *this) { static subtitle_t *sub_read_file (demux_sputext_t *this) { - int n_max; - int timeout; - subtitle_t *first; subtitle_t * (*func[])(demux_sputext_t *this,subtitle_t *dest)= { sub_read_line_microdvd, @@ -1151,7 +1156,7 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { } xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "Detected subtitle file format: %d\n",this->format); - + /* Rewind */ if(this->input->seek(this->input, 0, SEEK_SET) == -1) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "seek failed.\n"); @@ -1159,33 +1164,33 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { } this->buflen = 0; - this->num=0;n_max=32; - first = (subtitle_t *) xine_xmalloc(n_max*sizeof(subtitle_t)); + this->num=0; + int n_max=32; + subtitle_t *first = calloc(n_max, sizeof(subtitle_t)); if(!first) return NULL; - timeout = ((demux_sputext_class_t *) - (this->demux_plugin.demux_class))->max_timeout; - if (this->uses_time) timeout *= 100; - else timeout *= 10; - while(1) { - subtitle_t *sub; + const int timeout = + (((demux_sputext_class_t *) + (this->demux_plugin.demux_class))->max_timeout) * + (this->uses_time ? 100 : 10); + while(1) { if(this->num>=n_max){ n_max+=16; first=realloc(first,n_max*sizeof(subtitle_t)); } - sub = func[this->format] (this, &first[this->num]); + subtitle_t *sub = func[this->format] (this, &first[this->num]); - if (!sub) + if (!sub) break; /* EOF */ - if (sub==ERR) - ++this->errs; + if (sub==ERR) + ++this->errs; else { if (this->num > 0 && first[this->num-1].end == -1) { /* end time not defined in the subtitle */ - if (timeout > 0) { + if (timeout > 0) { /* timeout */ if (timeout > sub->start - first[this->num-1].start) { first[this->num-1].end = sub->start; @@ -1210,57 +1215,56 @@ static subtitle_t *sub_read_file (demux_sputext_t *this) { sprintf(buffer, "Read %i subtitles", this->num); - if(this->errs) + if(this->errs) sprintf(buffer + strlen(buffer), ", %i bad line(s).\n", this->errs); else strcat(buffer, "\n"); - + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "%s", buffer); } - + return first; } static int demux_sputext_next (demux_sputext_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - buf_element_t *buf; - uint32_t *val; - char *str; - subtitle_t *sub; - int line; - + if (this->cur >= this->num) return 0; - sub = &this->subtitles[this->cur]; - - buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); + subtitle_t *sub = &this->subtitles[this->cur]; + + buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); buf->type = BUF_SPU_TEXT; buf->pts = 0; - val = (uint32_t * )buf->content; + uint32_t *val = (uint32_t * )buf->content; *val++ = sub->lines; *val++ = this->uses_time; *val++ = (this->uses_time) ? sub->start * 10 : sub->start; *val++ = (this->uses_time) ? sub->end * 10 : sub->end; - str = (char *)val; + char *str = (char *)val; + + /** @FIXME The way this works seems wrong, SUB_BUFSIZE-1 is not the + right maximum, I think. */ + int line; for (line = 0; line < sub->lines; line++, str+=strlen(str)+1) { - if( strlen(sub->text[line]) > SUB_BUFSIZE ) - sub->text[line][SUB_BUFSIZE] = '\0'; - strcpy(str, sub->text[line]); + strncpy(str, sub->text[line], SUB_BUFSIZE-1); + str[SUB_BUFSIZE-1] = '\0'; } - + this->stream->video_fifo->put(this->stream->video_fifo, buf); this->cur++; - + return 1; } static void demux_sputext_dispose (demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - int i, l; - + + int i; for (i = 0; i < this->num; i++) { + int l; for (l = 0; l < this->subtitles[i].lines; l++) free(this->subtitles[i].text[l]); } @@ -1276,16 +1280,14 @@ static int demux_sputext_get_status (demux_plugin_t *this_gen) { static int demux_sputext_get_stream_length (demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - if( this->uses_time && this->num ) { - return this->subtitles[this->num-1].end * 10; - } else { - return 0; - } + return ( this->uses_time && this->num ) ? + this->subtitles[this->num-1].end * 10 : + 0; } static int demux_sputext_send_chunk (demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t *) this_gen; - + if (!demux_sputext_next (this)) { this->status = DEMUX_FINISHED; } @@ -1299,35 +1301,33 @@ static int demux_sputext_seek (demux_plugin_t *this_gen, lprintf("seek() called\n"); - /* simple seeking approach: just go back to start. + /* simple seeking approach: just go back to start. * decoder will discard subtitles until the desired position. */ this->cur = 0; this->status = DEMUX_OK; - + _x_demux_flush_engine (this->stream); _x_demux_control_newpts(this->stream, 0, 0); - + return this->status; } static void demux_sputext_send_headers(demux_plugin_t *this_gen) { demux_sputext_t *this = (demux_sputext_t*)this_gen; - buf_element_t *buf; - lprintf("send_headers() called\n"); - + _x_demux_control_start(this->stream); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 0); /* enable the SPU channel */ - buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); + buf_element_t *buf = this->stream->video_fifo->buffer_pool_alloc(this->stream->video_fifo); buf->type = BUF_CONTROL_SPU_CHANNEL; buf->decoder_info[0] = buf->decoder_info[1] = buf->decoder_info[2] = 0; this->stream->video_fifo->put(this->stream->video_fifo, buf); - + this->status = DEMUX_OK; } @@ -1357,8 +1357,8 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ demux_sputext_t *this; lprintf("open_plugin() called\n"); - - this = xine_xmalloc (sizeof (demux_sputext_t)); + + this = calloc(1, sizeof (demux_sputext_t)); this->stream = stream; this->input = input; @@ -1392,26 +1392,26 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ } } /* falling through is intended */ - + case METHOD_EXPLICIT: /* case METHOD_BY_CONTENT: */ - + /* FIXME: for now this demuxer only works when requested explicitly * to make sure it does not interfere with others; * If this is found too inconvenient, this may be changed after making * sure the content detection does not produce any false positives. */ - + if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) { - + this->subtitles = sub_read_file (this); this->cur = 0; if (this->subtitles) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subtitle format %s time.\n", + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "subtitle format %s time.\n", this->uses_time ? "uses" : "doesn't use"); - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "read %i subtitles, %i errors.\n", this->num, this->errs); return &this->demux_plugin; } @@ -1422,7 +1422,7 @@ static demux_plugin_t *open_demux_plugin (demux_class_t *class_gen, xine_stream_ free (this); return NULL; } - + static const char *get_demux_description (demux_class_t *this_gen) { return "sputext demuxer plugin"; } @@ -1460,7 +1460,7 @@ static void *init_sputext_demux_class (xine_t *xine, void *data) { lprintf("initializing\n"); - this = xine_xmalloc (sizeof (demux_sputext_class_t)); + this = calloc(1, sizeof (demux_sputext_class_t)); this->demux_class.open_plugin = open_demux_plugin; this->demux_class.get_description = get_demux_description; @@ -1469,13 +1469,13 @@ static void *init_sputext_demux_class (xine_t *xine, void *data) { this->demux_class.get_extensions = get_demux_extensions; this->demux_class.dispose = demux_class_dispose; - /* + /* * Some subtitling formats, namely AQT and Subrip09, define the end of a - * subtitle as the beginning of the following. From end-user view it's + * subtitle as the beginning of the following. From end-user view it's * better define timeout of hidding. Setting to zero means "no timeout". */ - this->max_timeout = xine->config->register_num(xine->config, - "subtitles.separate.timeout", 4, + this->max_timeout = xine->config->register_num(xine->config, + "subtitles.separate.timeout", 4, _("default duration of subtitle display in seconds"), _("Some subtitle formats do not explicitly give a duration for each subtitle. " "For these, you can set a default duration here. Setting to zero will result " @@ -1486,7 +1486,7 @@ static void *init_sputext_demux_class (xine_t *xine, void *data) { } const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_DEMUX, 26, "sputext", XINE_VERSION_CODE, NULL, &init_sputext_demux_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libsputext/xine_sputext_decoder.c b/src/libsputext/xine_sputext_decoder.c index 1de1eb099..cda8a5983 100644 --- a/src/libsputext/xine_sputext_decoder.c +++ b/src/libsputext/xine_sputext_decoder.c @@ -1,23 +1,27 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <unistd.h> @@ -63,7 +67,7 @@ #define rgb2yuv(R,G,B) ((((((66*R+129*G+25*B+128)>>8)+16)<<8)|(((112*R-94*G-18*B+128)>>8)+128))<<8|(((-38*R-74*G+112*B+128)>>8)+128)) -static uint32_t sub_palette[22]={ +static const uint32_t sub_palette[22]={ /* RED */ rgb2yuv(0,0,0), rgb2yuv(0,0,0), @@ -90,7 +94,7 @@ static uint32_t sub_palette[22]={ rgb2yuv(0,170,255) }; -static uint8_t sub_trans[22]={ +static const uint8_t sub_trans[22]={ 0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15, 0, 0, 3, 6, 8, 10, 12, 14, 15, 15, 15 }; @@ -169,7 +173,7 @@ typedef struct sputext_decoder_s { int64_t img_duration; int64_t last_subtitle_end; /* no new subtitle before this vpts */ int unscaled; /* use unscaled OSD */ - + int last_y; /* location of the previous subtitle */ int last_lines; /* number of lines of the previous subtitle */ video2wnd_t video2wnd; @@ -185,12 +189,12 @@ static inline char *get_font (sputext_class_t *class) } static void update_font_size (sputext_decoder_t *this, int force_update) { - static int sizes[SUBTITLE_SIZE_NUM] = { 16, 20, 24, 32, 48, 64 }; + static const int sizes[SUBTITLE_SIZE_NUM] = { 16, 20, 24, 32, 48, 64 }; if ((this->subtitle_size != this->class->subtitle_size) || (this->vertical_offset != this->class->vertical_offset) || force_update) { - + this->subtitle_size = this->class->subtitle_size; this->vertical_offset = this->class->vertical_offset; this->last_lines = 0; @@ -203,7 +207,7 @@ static void update_font_size (sputext_decoder_t *this, int force_update) { if( this->osd ) this->renderer->free_object (this->osd); - this->osd = this->renderer->new_object (this->renderer, + this->osd = this->renderer->new_object (this->renderer, this->width, this->height); @@ -214,11 +218,9 @@ static void update_font_size (sputext_decoder_t *this, int force_update) { } static void update_output_size (sputext_decoder_t *this) { - int unscaled; - - unscaled = this->class->use_unscaled && - (this->stream->video_out->get_capabilities(this->stream->video_out) & - VO_CAP_UNSCALED_OVERLAY); + const int unscaled = this->class->use_unscaled && + (this->stream->video_out->get_capabilities(this->stream->video_out) & + VO_CAP_UNSCALED_OVERLAY); if( unscaled != this->unscaled ) { this->unscaled = unscaled; @@ -227,14 +229,14 @@ static void update_output_size (sputext_decoder_t *this) { /* initialize decoder if needed */ if( this->unscaled ) { - if( this->width != this->stream->video_out->get_property(this->stream->video_out, + if( this->width != this->stream->video_out->get_property(this->stream->video_out, VO_PROP_WINDOW_WIDTH) || - this->height != this->stream->video_out->get_property(this->stream->video_out, + this->height != this->stream->video_out->get_property(this->stream->video_out, VO_PROP_WINDOW_HEIGHT) || !this->img_duration || !this->osd ) { int width = 0, height = 0; - + this->stream->video_out->status(this->stream->video_out, NULL, &width, &height, &this->img_duration ); if( width && height ) { @@ -251,13 +253,13 @@ static void update_output_size (sputext_decoder_t *this) { /* and a displacement factor because video may have blacks lines. */ int output_width, output_height, output_xoffset, output_yoffset; - output_width = this->stream->video_out->get_property(this->stream->video_out, + output_width = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_WIDTH); - output_height = this->stream->video_out->get_property(this->stream->video_out, + output_height = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_HEIGHT); - output_xoffset = this->stream->video_out->get_property(this->stream->video_out, + output_xoffset = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_XOFFSET); - output_yoffset = this->stream->video_out->get_property(this->stream->video_out, + output_yoffset = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_OUTPUT_YOFFSET); /* driver don't seen to be capable to give us those values */ @@ -281,16 +283,16 @@ static void update_output_size (sputext_decoder_t *this) { } } else { if( !this->width || !this->height || !this->img_duration || !this->osd ) { - + this->width = 0; this->height = 0; - + this->stream->video_out->status(this->stream->video_out, NULL, &this->width, &this->height, &this->img_duration ); - + if(!this->osd || ( this->width && this->height)) { this->renderer = this->stream->osd_renderer; - + /* in scaled mode, we have to convert subtitle position in film coordinates. */ this->video2wnd.x = 0; this->video2wnd.y = 0; @@ -303,18 +305,18 @@ static void update_output_size (sputext_decoder_t *this) { } } -static int parse_utf8_size(unsigned char *c) +static int parse_utf8_size(const uint8_t *c) { if ( c[0]<0x80 ) return 1; - + if( c[1]==0 ) return 1; if ( (c[0]>=0xC2 && c[0]<=0xDF) && (c[1]>=0x80 && c[1]<=0xBF) ) return 2; - + if( c[2]==0 ) - return 2; + return 2; else if ( c[0]==0xE0 && (c[1]>=0xA0 && c[1]<=0xBF) && (c[2]>=0x80 && c[1]<=0xBF) ) return 3; else if ( (c[0]>=0xE1 && c[0]<=0xEC) && (c[1]>=0x80 && c[1]<=0xBF) && (c[2]>=0x80 && c[1]<=0xBF) ) @@ -329,13 +331,8 @@ static int parse_utf8_size(unsigned char *c) static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const char *text, int render) { - int i = 0, w, value; - char* end; - char letter[5]={0, 0, 0, 0, 0}; - const char *encoding = this->buf_encoding ? this->buf_encoding - : this->class->src_encoding; - int shift, isutf8 = !strcmp(encoding, "utf-8"); - size_t length = strlen (text); + const size_t length = strlen (text); + size_t i = 0; while (i <= length) { @@ -352,7 +349,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const this->current_osd_text = OSD_TEXT1; i=i+4; continue; - } else if (!strncmp("<i>", text+i, 3)) { + } else if (!strncmp("<i>", text+i, 3)) { /* enable italics color */ if (render) this->current_osd_text = OSD_TEXT3; @@ -364,7 +361,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const this->current_osd_text = OSD_TEXT1; i=i+4; continue; - } else if (!strncmp("<font>", text+i, 6)) { + } else if (!strncmp("<font>", text+i, 6)) { /*Do somethink to disable typing fixme - no teststreams*/ i=i+6; @@ -379,6 +376,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const if (text[i] == '{') { if (!strncmp("{\\", text+i, 2)) { + int value; if (sscanf(text+i, "{\\b%d}", &value) == 1) { if (render) { @@ -395,7 +393,7 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const this->current_osd_text = OSD_TEXT1; } } - end = strstr(text+i+2, "}"); + char *const end = strstr(text+i+2, "}"); if (end) { i=end-text+1; continue; @@ -403,15 +401,20 @@ static int ogm_render_line_internal(sputext_decoder_t *this, int x, int y, const } } - shift = isutf8 ? parse_utf8_size (&text[i]) : 1; + char letter[5]; + const char *const encoding = this->buf_encoding ? : this->class->src_encoding; + const int isutf8 = !strcmp(encoding, "utf-8"); + const size_t shift = isutf8 ? parse_utf8_size (&text[i]) : 1; memcpy(letter,&text[i],shift); letter[shift]=0; - + if (render) this->renderer->render_text(this->osd, x, y, letter, this->current_osd_text); - this->renderer->get_text_size(this->osd, letter, &w, &value); - x=x+w; - i+=shift; + + int w, dummy; + this->renderer->get_text_size(this->osd, letter, &w, &dummy); + x += w; + i += shift; } return x; @@ -429,7 +432,7 @@ static inline void ogm_render_line(sputext_decoder_t *this, int x, int y, char* /* \a : alignment in SSA code (see #defines) */ /* \an : alignment in 'numpad code' */ /* \pos : absolute position of subtitles. Alignment define origin. */ -static void read_ssa_tag(sputext_decoder_t *this, const char* text, +static void read_ssa_tag(sputext_decoder_t *this, const char* text, int* alignment, int* sub_x, int* sub_y, int* max_width) { int in_tag = 0; @@ -465,7 +468,7 @@ static void read_ssa_tag(sputext_decoder_t *this, const char* text, if (*text == '}') in_tag = 0; } - + text++; } @@ -479,7 +482,7 @@ static void read_ssa_tag(sputext_decoder_t *this, const char* text, if ((*sub_x) >= 0 && (*sub_y) >= 0) { (*sub_x) = this->video2wnd.x + this->video2wnd.dx * (*sub_x); (*sub_y) = this->video2wnd.y + this->video2wnd.dy * (*sub_y); - } + } /* check validity, compute max width */ if ( (*sub_x) < 0 || (*sub_x) >= this->width || @@ -506,15 +509,50 @@ static void read_ssa_tag(sputext_decoder_t *this, const char* text, (*sub_x), (*sub_y), (*max_width), (*alignment)); } +static int is_cjk_encoding(const char *enc) { + /* CJK charset strings defined in iconvdata/gconv-modules of glibc */ + static const char cjk_encoding_strings[][16] = { + "SJIS", + "CP932", + "EUC-KR", + "UHC", + "JOHAB", + "BIG5", + "BIG5HKSCS", + "EUC-JP-MS", + "EUC-JP", + "EUC-CN", + "GBBIG5", + "GBK", + "GBGBK", + "EUC-TW", + "ISO-2022-JP", + "ISO-2022-JP-2", + "ISO-2022-JP-3", + "ISO-2022-KR", + "ISO-2022-CN", + "ISO-2022-CN-EXT", + "GB18030", + "EUC-JISX0213", + "SHIFT_JISX0213", + }; + + int pstr; + + /* return 1 if encoding string is one of the CJK(Chinese,Jananese,Korean) + * character set strings. */ + for (pstr = 0; pstr < sizeof (cjk_encoding_strings) / sizeof (cjk_encoding_strings[0]); pstr++) + if (strcasecmp (enc, cjk_encoding_strings[pstr]) == 0) + return 1; + + return 0; +} + static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t sub_end ) { - - int line, y; - int font_size; - char *font; + + int y; int sub_x, sub_y, max_width; int alignment; - int rebuild_all; - _x_assert(this->renderer != NULL); if ( ! this->renderer ) @@ -523,22 +561,21 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su read_ssa_tag(this, this->text[0], &alignment, &sub_x, &sub_y, &max_width); update_font_size(this, 0); - - font = get_font (this->class); + + const char *const font = get_font (this->class); if( strcmp(this->font, font) ) { strncpy(this->font, font, FILENAME_MAX); this->font[FILENAME_MAX - 1] = '\0'; this->renderer->set_font (this->osd, font, this->font_size); } - font_size = this->font_size; - if (this->buf_encoding) - this->renderer->set_encoding(this->osd, this->buf_encoding); - else - this->renderer->set_encoding(this->osd, this->class->src_encoding); + int font_size = this->font_size; + const char *const encoding = this->buf_encoding ? : this->class->src_encoding; + this->renderer->set_encoding(this->osd, encoding); - rebuild_all = 0; + int rebuild_all = 0; + int line; for (line = 0; line < this->lines; line++) { int line_width = ogm_get_width(this, this->text[line]); @@ -547,13 +584,13 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su char *current_cut, *best_cut; int a; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "libsputext: Line too long: %d > %d, split at max size.\n", + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "libsputext: Line too long: %d > %d, split at max size.\n", line_width, max_width); /* can't fit with keeping existing lines */ if (this->lines + 1 > SUB_MAX_TEXT) { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "libsputext: Can't fit with keeping existing line, we have to rebuild all the subtitle\n"); rebuild_all = 1; break; @@ -577,7 +614,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su } if (best_cut == NULL) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libsputext: Can't wrap line: a word is too long, abort.\n"); break; } @@ -596,30 +633,27 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su /* regenerate all the lines to find something that better fits */ if (rebuild_all) { - int line, line_width; - char *stream, *current_cut, *best_cut; - char buf[SUB_BUFSIZE * SUB_MAX_TEXT]; + char buf[SUB_BUFSIZE * SUB_MAX_TEXT] = { 0, }; - buf[0] = 0; + int line; for(line = 0; line < this->lines; line++) { - int len = strlen(buf); - if (len) { + const size_t len = strlen(buf); + if (len) buf[len] = ' '; - len++; - } - strncpy(buf + len, this->text[line], SUB_BUFSIZE); - *(buf + len + SUB_BUFSIZE) = 0; + + strncat(buf, this->text[line], SUB_BUFSIZE-len-1); } - stream = buf; + char *stream = buf; this->lines = 0; + char *current_cut, *best_cut; do { if (this->lines + 1 < SUB_MAX_TEXT) { - + /* find the longest sequence witch fit */ - line_width = 0; + int line_width = 0; current_cut = stream; best_cut = NULL; while (line_width < max_width) { @@ -637,7 +671,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su } } } - + /* line maybe too long, but we have reached last subtitle line */ else { best_cut = current_cut = stream + strlen(stream); @@ -650,7 +684,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su stream = best_cut + 1; - } while (best_cut != current_cut); + } while (best_cut != current_cut); } @@ -658,7 +692,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su /* Erase subtitle : use last_y and last_lines saved last turn. */ if (this->last_lines) { this->renderer->filled_rect (this->osd, 0, this->last_y, - this->width - 1, this->last_y + this->last_lines * this->line_height, + this->width - 1, this->last_y + this->last_lines * this->line_height, 0); } @@ -672,23 +706,23 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su if (sub_y >= 0) y = sub_y - (this->lines * this->line_height) / 2; else y = (this->height - this->lines * this->line_height) / 2; break; - + case ALIGN_BOTTOM: default: if (sub_y >= 0) y = sub_y - this->lines * this->line_height; else y = this->height - this->lines * this->line_height - this->class->vertical_offset; break; } - if (y < 0 || y >= this->height) + if (y < 0 || y >= this->height) y = this->height - this->line_height * this->lines; - this->last_lines = this->lines; - this->last_y = y; + this->last_lines = this->lines; + this->last_y = y; for (line = 0; line < this->lines; line++) { int w, x; - + while(1) { w = ogm_get_width( this, this->text[line]); @@ -702,7 +736,7 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su if (sub_x >= 0) x = sub_x - w; else x = max_width - w - 5; break; - + case ALIGN_CENTER: default: if (sub_x >= 0) x = sub_x - w / 2; @@ -718,34 +752,39 @@ static void draw_subtitle(sputext_decoder_t *this, int64_t sub_start, int64_t su break; } } - - ogm_render_line(this, x, y + line*this->line_height, this->text[line]); + + if( is_cjk_encoding(encoding) ) { + this->renderer->render_text (this->osd, x, y + line * this->line_height, + this->text[line], OSD_TEXT1); + } else { + ogm_render_line(this, x, y + line*this->line_height, this->text[line]); + } } - + if( font_size != this->font_size ) this->renderer->set_font (this->osd, get_font (this->class), this->font_size); - + if( this->last_subtitle_end && sub_start < this->last_subtitle_end ) { sub_start = this->last_subtitle_end; } this->last_subtitle_end = sub_end; - + this->renderer->set_text_palette (this->osd, -1, OSD_TEXT1); this->renderer->get_palette(this->osd, this->spu_palette, this->spu_trans); /* append some colors for colored typeface tag */ memcpy(this->spu_palette+OSD_TEXT2, sub_palette, sizeof(sub_palette)); memcpy(this->spu_trans+OSD_TEXT2, sub_trans, sizeof(sub_trans)); this->renderer->set_palette(this->osd, this->spu_palette, this->spu_trans); - + if (this->unscaled) this->renderer->show_unscaled (this->osd, sub_start); else this->renderer->show (this->osd, sub_start); - + this->renderer->hide (this->osd, sub_end); - + lprintf ("scheduling subtitle >%s< at %"PRId64" until %"PRId64", current time is %"PRId64"\n", - this->text[0], sub_start, sub_end, + this->text[0], sub_start, sub_end, this->stream->xine->clock->get_current_time (this->stream->xine->clock)); } @@ -770,7 +809,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; - + if ((this->stream->spu_channel & 0x1f) != (buf->type & 0x1f)) return; @@ -793,9 +832,9 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if (!*str) return; /* Empty ogm packets (as created by ogmmux) clears out old messages. We already respect the end time. */ - + this->lines = 0; - + i = 0; while (*str && (this->lines < SUB_MAX_TEXT) && (i < SUB_BUFSIZE)) { if (*str == '\r' || *str == '\n') { @@ -813,7 +852,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } if (i == SUB_BUFSIZE) i--; - + if (i) { this->text[ this->lines ][i] = 0; this->lines++; @@ -823,7 +862,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { this->ogm = 0; val = (uint32_t * )buf->content; - + this->lines = *val++; uses_time = *val++; start = *val++; @@ -835,7 +874,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { } } - + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "libsputext: decoder data [%s]\n", this->text[0]); xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, @@ -846,7 +885,7 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { "libsputext: discarding subtitle with invalid timing\n"); return; } - + spu_offset = this->stream->master->metronom->get_option (this->stream->master->metronom, METRONOM_SPU_OFFSET); if( uses_time ) { @@ -858,17 +897,17 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { end += spu_offset / this->img_duration; } } - + while( !this->finished ) { - + master_status = xine_get_status (this->stream->master); slave_status = xine_get_status (this->stream); - vo_discard = this->stream->video_out->get_property(this->stream->video_out, + vo_discard = this->stream->video_out->get_property(this->stream->video_out, VO_PROP_DISCARD_FRAMES); _x_get_current_info (this->stream->master, &extra_info, sizeof(extra_info) ); - - lprintf("master: %d slave: %d input_normpos: %d vo_discard: %d\n", + + lprintf("master: %d slave: %d input_normpos: %d vo_discard: %d\n", master_status, slave_status, extra_info.input_normpos, vo_discard); if( !this->started && (master_status == XINE_STATUS_PLAY && @@ -886,63 +925,63 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { if( this->started ) { - if( master_status != XINE_STATUS_PLAY || + if( master_status != XINE_STATUS_PLAY || slave_status != XINE_STATUS_PLAY || vo_discard ) { lprintf("finished\n"); - + this->width = this->height = 0; this->finished = 1; return; } if( this->osd ) { - + /* try to use frame number mode */ if( !uses_time && extra_info.frame_number ) { - + diff = end - extra_info.frame_number; - + /* discard old subtitles */ if( diff < 0 ) { - xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "libsputext: discarding old subtitle\n"); return; } - + diff = start - extra_info.frame_number; - + start_vpts = extra_info.vpts + diff * this->img_duration; end_vpts = start_vpts + (end-start) * this->img_duration; - + } else { - + if( !uses_time ) { start = start * this->img_duration / 90; end = end * this->img_duration / 90; uses_time = 1; } - + diff = end - extra_info.input_time; - + /* discard old subtitles */ if( diff < 0 ) { xprintf(this->class->xine, XINE_VERBOSITY_DEBUG, "libsputext: discarding old subtitle\n"); return; } - + diff = start - extra_info.input_time; - + start_vpts = extra_info.vpts + diff * 90; end_vpts = start_vpts + (end-start) * 90; } - + _x_spu_decoder_sleep(this->stream, start_vpts); update_output_size( this ); draw_subtitle(this, start_vpts, end_vpts); - - return; + + return; } } @@ -951,12 +990,12 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { else return; } -} +} static void spudec_reset (spu_decoder_t *this_gen) { sputext_decoder_t *this = (sputext_decoder_t *) this_gen; - + lprintf("i guess we just seeked\n"); this->width = this->height = 0; this->started = this->finished = 0; @@ -970,7 +1009,7 @@ static void spudec_discontinuity (spu_decoder_t *this_gen) { static void spudec_dispose (spu_decoder_t *this_gen) { sputext_decoder_t *this = (sputext_decoder_t *) this_gen; - + if (this->osd) { this->renderer->free_object (this->osd); this->osd = NULL; @@ -991,7 +1030,7 @@ static void update_osd_font(void *class_gen, xine_cfg_entry_t *entry) strncpy(class->font, entry->str_value, FONTNAME_SIZE); class->font[FONTNAME_SIZE - 1] = '\0'; - + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "libsputext: spu_font = %s\n", class->font ); } @@ -1002,7 +1041,7 @@ static void update_osd_font_ft(void *class_gen, xine_cfg_entry_t *entry) strncpy(class->font_ft, entry->str_value, FILENAME_MAX); class->font_ft[FILENAME_MAX - 1] = '\0'; - + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "libsputext: spu_font_ft = %s\n", class->font_ft); } @@ -1011,7 +1050,7 @@ static void update_osd_use_font_ft(void *class_gen, xine_cfg_entry_t *entry) sputext_class_t *class = (sputext_class_t *)class_gen; class->use_font_ft = entry->num_value; - + xprintf(class->xine, XINE_VERBOSITY_DEBUG, "libsputext: spu_use_font_ft = %d\n", class->use_font_ft); } #endif @@ -1035,7 +1074,7 @@ static spu_decoder_t *sputext_class_open_plugin (spu_decoder_class_t *class_gen, sputext_class_t *class = (sputext_class_t *)class_gen; sputext_decoder_t *this ; - this = (sputext_decoder_t *) xine_xmalloc (sizeof (sputext_decoder_t)); + this = (sputext_decoder_t *) calloc(1, sizeof(sputext_decoder_t)); this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; @@ -1082,14 +1121,14 @@ static void update_src_encoding(void *class_gen, xine_cfg_entry_t *entry) static void *init_spu_decoder_plugin (xine_t *xine, void *data) { - static const char *subtitle_size_strings[] = { - "tiny", "small", "normal", "large", "very large", "huge", NULL + static const char *subtitle_size_strings[] = { + "tiny", "small", "normal", "large", "very large", "huge", NULL }; sputext_class_t *this ; lprintf("init class\n"); - - this = (sputext_class_t *) xine_xmalloc (sizeof (sputext_class_t)); + + this = (sputext_class_t *) calloc(1, sizeof(sputext_class_t)); this->class.open_plugin = sputext_class_open_plugin; this->class.get_identifier = sputext_class_get_identifier; @@ -1098,8 +1137,8 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { this->xine = xine; - this->subtitle_size = xine->config->register_enum(xine->config, - "subtitles.separate.subtitle_size", + this->subtitle_size = xine->config->register_enum(xine->config, + "subtitles.separate.subtitle_size", 1, subtitle_size_strings, _("subtitle size"), @@ -1107,7 +1146,7 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { "be evaluated relative to the window size."), 0, update_subtitle_size, this); this->vertical_offset = xine->config->register_num(xine->config, - "subtitles.separate.vertical_offset", + "subtitles.separate.vertical_offset", 0, _("subtitle vertical offset"), _("You can adjust the vertical position of the subtitle. " @@ -1136,8 +1175,8 @@ static void *init_spu_decoder_plugin (xine_t *xine, void *data) { NULL, 10, update_osd_use_font_ft, this); #endif - this->src_encoding = xine->config->register_string(xine->config, - "subtitles.separate.src_encoding", + this->src_encoding = xine->config->register_string(xine->config, + "subtitles.separate.src_encoding", xine_guess_spu_encoding(), _("encoding of the subtitles"), _("The encoding of the subtitle text in the stream. This setting " @@ -1170,7 +1209,7 @@ static const decoder_info_t spudec_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_SPU_DECODER | PLUGIN_MUST_PRELOAD, 16, "sputext", XINE_VERSION_CODE, &spudec_info, &init_spu_decoder_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libw32dll/DirectShow/DS_AudioDecoder.c b/src/libw32dll/DirectShow/DS_AudioDecoder.c index 2dcf21f9e..84e84747e 100644 --- a/src/libw32dll/DirectShow/DS_AudioDecoder.c +++ b/src/libw32dll/DirectShow/DS_AudioDecoder.c @@ -15,7 +15,7 @@ #include "DS_Filter.h" struct _DS_AudioDecoder -{ +{ WAVEFORMATEX in_fmt; AM_MEDIA_TYPE m_sOurType, m_sDestType; DS_Filter* m_pDS_Filter; @@ -46,20 +46,20 @@ DS_AudioDecoder * DS_AudioDecoder_Open(char* dllname, GUID* guid, WAVEFORMATEX* #endif this = malloc(sizeof(DS_AudioDecoder)); - + sz = 18 + wf->cbSize; this->m_sVhdr = malloc(sz); memcpy(this->m_sVhdr, wf, sz); this->m_sVhdr2 = malloc(18); memcpy(this->m_sVhdr2, this->m_sVhdr, 18); - + pWF = (WAVEFORMATEX*)this->m_sVhdr2; pWF->wFormatTag = 1; pWF->wBitsPerSample = 16; pWF->nBlockAlign = pWF->nChannels * (pWF->wBitsPerSample + 7) / 8; pWF->cbSize = 0; pWF->nAvgBytesPerSec = pWF->nBlockAlign * pWF->nSamplesPerSec; - + memcpy(&this->in_fmt,wf,sizeof(WAVEFORMATEX)); memset(&this->m_sOurType, 0, sizeof(this->m_sOurType)); @@ -105,7 +105,7 @@ print_wave_header(this->m_sVhdr2); free(this); return NULL; } - + this->m_pDS_Filter->Start(this->m_pDS_Filter); props.cBuffers=1; @@ -141,7 +141,7 @@ int DS_AudioDecoder_Convert(DS_AudioDecoder *this, const void* in_data, unsigned { unsigned int written = 0; unsigned int read = 0; - + if (!in_data || !out_data) return -1; @@ -157,7 +157,7 @@ int DS_AudioDecoder_Convert(DS_AudioDecoder *this, const void* in_data, unsigned IMediaSample* sample=0; char* ptr; int result; - + // this->m_pOurOutput->SetFramePointer(out_data+written); this->m_pDS_Filter->m_pOurOutput->SetFramePointer(this->m_pDS_Filter->m_pOurOutput,&frame_pointer); this->m_pDS_Filter->m_pOurOutput->SetFrameSizePointer(this->m_pDS_Filter->m_pOurOutput,(long*)&frame_size); @@ -198,7 +198,7 @@ int DS_AudioDecoder_GetSrcSize(DS_AudioDecoder *this, int dest_size) double efficiency =(double) this->in_fmt.nAvgBytesPerSec / (this->in_fmt.nSamplesPerSec*this->in_fmt.nBlockAlign); int frames = (int)(dest_size*efficiency);; - + if (frames < 1) frames = 1; return frames * this->in_fmt.nBlockAlign; diff --git a/src/libw32dll/DirectShow/DS_VideoDecoder.c b/src/libw32dll/DirectShow/DS_VideoDecoder.c index c0a08d5e3..f88e480e3 100644 --- a/src/libw32dll/DirectShow/DS_VideoDecoder.c +++ b/src/libw32dll/DirectShow/DS_VideoDecoder.c @@ -18,7 +18,7 @@ struct _DS_VideoDecoder { IVideoDecoder iv; - + DS_Filter* m_pDS_Filter; AM_MEDIA_TYPE m_sOurType, m_sDestType; VIDEOINFOHEADER* m_sVhdr; @@ -59,7 +59,7 @@ struct _DS_VideoDecoder int DS_VideoDecoder_GetCapabilities(DS_VideoDecoder *this) {return this->m_Caps;} - + typedef struct _ct ct; struct _ct { @@ -68,7 +68,7 @@ struct _ct { const GUID *subtype; int cap; }; - + static ct check[] = { {16, fccYUY2, &MEDIASUBTYPE_YUY2, CAP_YUY2}, {12, fccIYUV, &MEDIASUBTYPE_IYUV, CAP_IYUV}, @@ -87,10 +87,10 @@ DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEAD DS_VideoDecoder *this; HRESULT result; ct* c; - + this = malloc(sizeof(DS_VideoDecoder)); memset( this, 0, sizeof(DS_VideoDecoder)); - + this->m_sVhdr2 = 0; this->m_iLastQuality = -1; this->m_iMaxAuto = maxauto; @@ -104,10 +104,10 @@ DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEAD /*try*/ { unsigned int bihs; - + bihs = (format->biSize < (int) sizeof(BITMAPINFOHEADER)) ? sizeof(BITMAPINFOHEADER) : format->biSize; - + this->iv.m_bh = (BITMAPINFOHEADER*)malloc(bihs); memcpy(this->iv.m_bh, format, bihs); this->iv.m_bh->biSize = bihs; @@ -119,7 +119,7 @@ DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEAD this->iv.m_iPlaypos = -1; this->iv.m_fQuality = 0.0f; this->iv.m_bCapable16b = true; - + bihs += sizeof(VIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER); this->m_sVhdr = (VIDEOINFOHEADER*)malloc(bihs); memset(this->m_sVhdr, 0, bihs); @@ -159,7 +159,7 @@ DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEAD this->m_sDestType.pUnk = 0; this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); this->m_sDestType.pbFormat = (char*)this->m_sVhdr2; - + memset(&this->iv.m_obh, 0, sizeof(this->iv.m_obh)); memcpy(&this->iv.m_obh, this->iv.m_bh, sizeof(this->iv.m_obh) < (unsigned) this->iv.m_bh->biSize ? sizeof(this->iv.m_obh) : (unsigned) this->iv.m_bh->biSize); @@ -172,7 +172,7 @@ DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEAD this->m_pDS_Filter = DS_FilterCreate(dllname, guid, &this->m_sOurType, &this->m_sDestType); - + if (!this->m_pDS_Filter) { printf("Failed to create DirectShow filter\n"); @@ -216,7 +216,7 @@ DS_VideoDecoder * DS_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHEAD break; #endif default: - + this->m_Caps = CAP_NONE; printf("Decoder supports the following YUV formats: "); @@ -278,7 +278,7 @@ void DS_VideoDecoder_StartInternal(DS_VideoDecoder *this) Debug printf("DS_VideoDecoder_StartInternal\n"); //cout << "DSSTART" << endl; this->m_pDS_Filter->Start(this->m_pDS_Filter); - + props.cBuffers = 1; props.cbBuffer = this->m_sDestType.lSampleSize; @@ -286,7 +286,7 @@ void DS_VideoDecoder_StartInternal(DS_VideoDecoder *this) props.cbAlign = props.cbPrefix = 0; this->m_pDS_Filter->m_pAll->vt->SetProperties(this->m_pDS_Filter->m_pAll, &props, &props1); this->m_pDS_Filter->m_pAll->vt->Commit(this->m_pDS_Filter->m_pAll); - + this->iv.m_State = START; } @@ -301,17 +301,17 @@ int DS_VideoDecoder_DecodeInternal(DS_VideoDecoder *this, const void* src, int s IMediaSample* sample = 0; char* ptr; int result; - + Debug printf("DS_VideoDecoder_DecodeInternal(%p,%p,%d,%d,%p)\n",this,src,size,is_keyframe,pImage); - + this->m_pDS_Filter->m_pAll->vt->GetBuffer(this->m_pDS_Filter->m_pAll, &sample, 0, 0, 0); - + if (!sample) { Debug printf("ERROR: null sample\n"); return -1; } - + //cout << "DECODE " << (void*) pImage << " d: " << (void*) pImage->Data() << endl; if (pImage) { @@ -425,15 +425,15 @@ int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp { HRESULT result; int should_test=1; - int stoped = 0; - + int stoped = 0; + Debug printf("DS_VideoDecoder_SetDestFmt (%p, %d, %d)\n",this,bits,(int)csp); - + /* if (!CImage::Supported(csp, bits)) return -1; */ // BitmapInfo temp = m_obh; - + if (!csp) // RGB { int ok = true; @@ -442,7 +442,7 @@ int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp { case 15: this->m_sDestType.subtype = MEDIASUBTYPE_RGB555; - break; + break; case 16: this->m_sDestType.subtype = MEDIASUBTYPE_RGB565; break; @@ -464,7 +464,7 @@ int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp this->iv.m_obh.biCompression=3;//BI_BITFIELDS this->iv.m_obh.biSizeImage=abs((int)(2*this->iv.m_obh.biWidth*this->iv.m_obh.biHeight)); } - + if( bits == 16 ) { this->iv.m_obh.colors[0]=0xF800; this->iv.m_obh.colors[1]=0x07E0; @@ -514,7 +514,7 @@ int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp if (ok) { if (csp != 0 && csp != 3 && this->iv.m_obh.biHeight > 0) - this->iv.m_obh.biHeight *= -1; // YUV formats uses should have height < 0 + this->iv.m_obh.biHeight *= -1; // YUV formats uses should have height < 0 this->iv.m_obh.biSize = sizeof(BITMAPINFOHEADER); this->iv.m_obh.biCompression=csp; this->iv.m_obh.biBitCount=bits; @@ -578,9 +578,9 @@ int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp memcpy(&(this->m_sVhdr2->bmiHeader), &this->iv.m_decoder, sizeof(this->iv.m_decoder)); this->m_sVhdr2->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); if (this->m_sVhdr2->bmiHeader.biCompression == 3) - this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER) + 12; + this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER) + 12; else - this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); + this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); return -1; } @@ -624,7 +624,7 @@ int DS_VideoDecoder_SetDestFmt(DS_VideoDecoder *this, int bits, unsigned int csp if (stoped) { DS_VideoDecoder_StartInternal(this); - this->iv.m_State = START; + this->iv.m_State = START; } return 0; @@ -789,7 +789,7 @@ int DS_VideoDecoder_SetValue(DS_VideoDecoder *this, const char* name, int value) // get4=set3 73 // get5=set4 19 // get6=set5 23 - hidden = (IHidden*)((int)this->m_pDS_Filter->m_pFilter + 0xb8); + hidden = (IHidden*)((int)this->m_pDS_Filter->m_pFilter + 0xb8); // printf("DS_SetValue for DIVX, name=%s value=%d\n",name,value); if (strcmp(name, "Quality") == 0) { @@ -810,7 +810,7 @@ int DS_VideoDecoder_SetValue(DS_VideoDecoder *this, const char* name, int value) } return 0; } -#if 0 +#if 0 if (strcmp((const char*)record.dll, "ir50_32.dll") == 0) { IHidden2* hidden = 0; @@ -844,7 +844,7 @@ int DS_VideoDecoder_SetValue(DS_VideoDecoder *this, const char* name, int value) if(!recordpar[5]) { hidden->vt->Release((IUnknown*)hidden); - return -1; + return -1; } HRESULT result = hidden->vt->DecodeSet(hidden, recordpar); hidden->vt->Release((IUnknown*)hidden); @@ -865,28 +865,28 @@ int DS_SetAttr_DivX(char* attribute, int value){ int result, status, newkey, count; if(strcmp(attribute, "Quality")==0){ char* keyname="SOFTWARE\\Microsoft\\Scrunch"; - result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); + result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); if(result!=0) { printf("VideoDecoder::SetExtAttr: registry failure\n"); return -1; - } + } result=RegSetValueExA(newkey, "Current Post Process Mode", 0, REG_DWORD, &value, 4); if(result!=0) { printf("VideoDecoder::SetExtAttr: error writing value\n"); return -1; - } + } value=-1; result=RegSetValueExA(newkey, "Force Post Process Mode", 0, REG_DWORD, &value, 4); if(result!=0) { printf("VideoDecoder::SetExtAttr: error writing value\n"); - return -1; - } - RegCloseKey(newkey); - return 0; - } + return -1; + } + RegCloseKey(newkey); + return 0; + } if( (strcmp(attribute, "Saturation")==0) || @@ -896,21 +896,21 @@ int DS_SetAttr_DivX(char* attribute, int value){ ) { char* keyname="SOFTWARE\\Microsoft\\Scrunch\\Video"; - result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); + result=RegCreateKeyExA(HKEY_CURRENT_USER, keyname, 0, 0, 0, 0, 0, &newkey, &status); if(result!=0) { printf("VideoDecoder::SetExtAttr: registry failure\n"); return -1; - } + } result=RegSetValueExA(newkey, attribute, 0, REG_DWORD, &value, 4); if(result!=0) { printf("VideoDecoder::SetExtAttr: error writing value\n"); return -1; - } - RegCloseKey(newkey); - return 0; - } + } + RegCloseKey(newkey); + return 0; + } printf("Unknown attribute!\n"); return -200; diff --git a/src/libw32dll/DirectShow/iunk.h b/src/libw32dll/DirectShow/iunk.h index 7998011cd..e571176df 100644 --- a/src/libw32dll/DirectShow/iunk.h +++ b/src/libw32dll/DirectShow/iunk.h @@ -11,39 +11,39 @@ #define DECLARE_IUNKNOWN() \ int refcount; -#define IMPLEMENT_IUNKNOWN(CLASSNAME) \ +#define IMPLEMENT_IUNKNOWN(CLASSNAME) \ static long STDCALL CLASSNAME ## _QueryInterface(IUnknown * This, \ const GUID* riid, void **ppvObject) \ { \ CLASSNAME * me = (CLASSNAME *)This; \ const GUID* r; unsigned int i = 0; \ Debug printf(#CLASSNAME "_QueryInterface(%p) called\n", This);\ - if (!ppvObject) return E_POINTER; \ + if (!ppvObject) return E_POINTER; \ for(r=me->interfaces; i<sizeof(me->interfaces)/sizeof(me->interfaces[0]); r++, i++) \ if(!memcmp(r, riid, sizeof(*r))) \ - { \ - me->vt->AddRef((IUnknown*)This); \ - *ppvObject=This; \ - return 0; \ - } \ + { \ + me->vt->AddRef((IUnknown*)This); \ + *ppvObject=This; \ + return 0; \ + } \ Debug printf("Query failed! (GUID: 0x%x)\n", *(const unsigned int*)riid); \ return E_NOINTERFACE; \ -} \ +} \ \ static long STDCALL CLASSNAME ## _AddRef(IUnknown * This) \ { \ CLASSNAME * me=( CLASSNAME *)This; \ Debug printf(#CLASSNAME "_AddRef(%p) called (ref:%d)\n", This, me->refcount); \ - return ++(me->refcount); \ -} \ + return ++(me->refcount); \ +} \ \ static long STDCALL CLASSNAME ## _Release(IUnknown * This) \ -{ \ - CLASSNAME* me=( CLASSNAME *)This; \ +{ \ + CLASSNAME* me=( CLASSNAME *)This; \ Debug printf(#CLASSNAME "_Release(%p) called (new ref:%d)\n", This, me->refcount - 1); \ if(--(me->refcount) == 0) \ - CLASSNAME ## _Destroy(me); \ - return 0; \ + CLASSNAME ## _Destroy(me); \ + return 0; \ } #endif /* DS_IUNK_H */ diff --git a/src/libw32dll/Makefile.am b/src/libw32dll/Makefile.am index e7f655888..5036851a3 100644 --- a/src/libw32dll/Makefile.am +++ b/src/libw32dll/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = -I$(srcdir)/wine -DWIN32_PATH=\"@w32_path@\" $(VISIBILITY_FLAG) diff --git a/src/libw32dll/common.c b/src/libw32dll/common.c index 35fe41941..76c114bca 100644 --- a/src/libw32dll/common.c +++ b/src/libw32dll/common.c @@ -6,7 +6,7 @@ static char *get_win32_codecs_path(config_values_t *cfg) { DIR *dir; char *path, *cfgpath; char *listpath[] = { "", - "/usr/lib/codecs", + "/usr/lib/codecs", "/usr/local/lib/codecs", "/usr/lib/win32", "/usr/local/lib/win32", @@ -35,5 +35,5 @@ static char *get_win32_codecs_path(config_values_t *cfg) { i++; } - return NULL; + return NULL; } diff --git a/src/libw32dll/dmo/DMO_AudioDecoder.c b/src/libw32dll/dmo/DMO_AudioDecoder.c index faf49e266..f2a1bfb5c 100644 --- a/src/libw32dll/dmo/DMO_AudioDecoder.c +++ b/src/libw32dll/dmo/DMO_AudioDecoder.c @@ -19,7 +19,7 @@ #include "DMO_AudioDecoder.h" struct _DMO_AudioDecoder -{ +{ DMO_MEDIA_TYPE m_sOurType, m_sDestType; DMO_Filter* m_pDMO_Filter; char* m_sVhdr; @@ -49,17 +49,17 @@ DMO_AudioDecoder * DMO_AudioDecoder_Open(char* dllname, GUID* guid, WAVEFORMATEX Setup_LDT_Keeper(); Setup_FS_Segment(); #endif - + this = malloc(sizeof(DMO_AudioDecoder)); - + this->m_iFlushed=1; - + sz = 18 + wf->cbSize; this->m_sVhdr = malloc(sz); memcpy(this->m_sVhdr, wf, sz); this->m_sVhdr2 = malloc(18); memcpy(this->m_sVhdr2, this->m_sVhdr, 18); - + pWF = (WAVEFORMATEX*)this->m_sVhdr2; pWF->wFormatTag = 1; pWF->wBitsPerSample = 16; @@ -67,7 +67,7 @@ DMO_AudioDecoder * DMO_AudioDecoder_Open(char* dllname, GUID* guid, WAVEFORMATEX pWF->nBlockAlign = 2*pWF->nChannels; //pWF->nChannels * (pWF->wBitsPerSample + 7) / 8; pWF->nAvgBytesPerSec = pWF->nBlockAlign * pWF->nSamplesPerSec; pWF->cbSize = 0; - + memset(&this->m_sOurType, 0, sizeof(this->m_sOurType)); this->m_sOurType.majortype=MEDIATYPE_Audio; this->m_sOurType.subtype=MEDIASUBTYPE_PCM; @@ -101,7 +101,7 @@ print_wave_header((WAVEFORMATEX *)this->m_sVhdr2); free(this); return NULL; } - + return this; } @@ -129,7 +129,7 @@ int DMO_AudioDecoder_Convert(DMO_AudioDecoder *this, const void* in_data, unsign #ifdef LDT_paranoia Setup_FS_Segment(); #endif - + //m_pDMO_Filter->m_pMedia->vt->Lock(m_pDMO_Filter->m_pMedia, 1); bufferin = CMediaBufferCreate(in_size, (void*)in_data, in_size, 1); r = this->m_pDMO_Filter->m_pMedia->vt->ProcessInput(this->m_pDMO_Filter->m_pMedia, 0, @@ -157,7 +157,7 @@ int DMO_AudioDecoder_Convert(DMO_AudioDecoder *this, const void* in_data, unsign ((IMediaBuffer*)db.pBuffer)->vt->GetBufferAndLength((IMediaBuffer*)db.pBuffer, 0, &written); ((IMediaBuffer*)db.pBuffer)->vt->Release((IUnknown*)db.pBuffer); - + //printf("RESULTB: %d 0x%x %ld\n", r, r, written); //printf("Converted %d -> %d\n", in_size, out_size); } diff --git a/src/libw32dll/dmo/DMO_VideoDecoder.c b/src/libw32dll/dmo/DMO_VideoDecoder.c index 7b25085f0..64b0ef78c 100644 --- a/src/libw32dll/dmo/DMO_VideoDecoder.c +++ b/src/libw32dll/dmo/DMO_VideoDecoder.c @@ -24,7 +24,7 @@ struct _DMO_VideoDecoder { IVideoDecoder iv; - + DMO_Filter* m_pDMO_Filter; AM_MEDIA_TYPE m_sOurType, m_sDestType; VIDEOINFOHEADER* m_sVhdr; @@ -72,7 +72,7 @@ struct _ct { const GUID* subtype; int cap; }; - + static ct check[] = { { fccI420, 12, &MEDIASUBTYPE_I420, CAP_I420 }, { fccYV12, 12, &MEDIASUBTYPE_YV12, CAP_YV12 }, @@ -95,10 +95,10 @@ DMO_VideoDecoder * DMO_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHE DMO_VideoDecoder *this; HRESULT result; ct* c; - + this = malloc(sizeof(DMO_VideoDecoder)); memset( this, 0, sizeof(DMO_VideoDecoder)); - + this->m_sVhdr2 = 0; this->m_iLastQuality = -1; this->m_iMaxAuto = maxauto; @@ -112,10 +112,10 @@ DMO_VideoDecoder * DMO_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHE /*try*/ { unsigned int bihs; - + bihs = (format->biSize < (int) sizeof(BITMAPINFOHEADER)) ? sizeof(BITMAPINFOHEADER) : format->biSize; - + this->iv.m_bh = (BITMAPINFOHEADER*)malloc(bihs); memcpy(this->iv.m_bh, format, bihs); this->iv.m_bh->biSize = bihs; @@ -127,7 +127,7 @@ DMO_VideoDecoder * DMO_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHE this->iv.m_iPlaypos = -1; this->iv.m_fQuality = 0.0f; this->iv.m_bCapable16b = true; - + bihs += sizeof(VIDEOINFOHEADER) - sizeof(BITMAPINFOHEADER); this->m_sVhdr = (VIDEOINFOHEADER*)malloc(bihs); memset(this->m_sVhdr, 0, bihs); @@ -171,7 +171,7 @@ DMO_VideoDecoder * DMO_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHE this->m_sDestType.pUnk = 0; this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); this->m_sDestType.pbFormat = (char*)this->m_sVhdr2; - + memset(&this->iv.m_obh, 0, sizeof(this->iv.m_obh)); memcpy(&this->iv.m_obh, this->iv.m_bh, sizeof(this->iv.m_obh) < (unsigned) this->iv.m_bh->biSize ? sizeof(this->iv.m_obh) : (unsigned) this->iv.m_bh->biSize); @@ -184,7 +184,7 @@ DMO_VideoDecoder * DMO_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHE this->m_pDMO_Filter = DMO_FilterCreate(dllname, guid, &this->m_sOurType, &this->m_sDestType); - + if (!this->m_pDMO_Filter) { printf("Failed to create DMO filter\n"); @@ -229,7 +229,7 @@ DMO_VideoDecoder * DMO_VideoDecoder_Open(char* dllname, GUID* guid, BITMAPINFOHE break; #endif default: - + this->m_Caps = CAP_NONE; printf("Decoder supports the following YUV formats: "); @@ -284,7 +284,7 @@ void DMO_VideoDecoder_StartInternal(DMO_VideoDecoder *this) Debug printf("DMO_VideoDecoder_StartInternal\n"); //cout << "DSSTART" << endl; this->m_pDMO_Filter->Start(this->m_pDMO_Filter); - + props.cBuffers = 1; props.cbBuffer = this->m_sDestType.lSampleSize; @@ -292,7 +292,7 @@ void DMO_VideoDecoder_StartInternal(DMO_VideoDecoder *this) props.cbAlign = props.cbPrefix = 0; this->m_pDMO_Filter->m_pAll->vt->SetProperties(this->m_pDMO_Filter->m_pAll, &props, &props1); this->m_pDMO_Filter->m_pAll->vt->Commit(this->m_pDMO_Filter->m_pAll); -#endif +#endif this->iv.m_State = START; } @@ -310,7 +310,7 @@ int DMO_VideoDecoder_DecodeInternal(DMO_VideoDecoder *this, const void* src, int DMO_OUTPUT_DATA_BUFFER db; CMediaBuffer* bufferin; //+ uint8_t* imdata = dest ? dest->Data() : 0; - + Debug printf("DMO_VideoDecoder_DecodeInternal(%p,%p,%d,%d,%p)\n",this,src,size,is_keyframe,imdata); // this->m_pDMO_Filter->m_pAll->vt->GetBuffer(this->m_pDMO_Filter->m_pAll, &sample, 0, 0, 0); @@ -371,14 +371,14 @@ int DMO_VideoDecoder_SetDestFmt(DMO_VideoDecoder *this, int bits, unsigned int c { HRESULT result; int should_test=1; - + Debug printf("DMO_VideoDecoder_SetDestFmt (%p, %d, %d)\n",this,bits,(int)csp); - + /* if (!CImage::Supported(csp, bits)) return -1; */ // BitmapInfo temp = m_obh; - + if (!csp) // RGB { int ok = true; @@ -387,7 +387,7 @@ int DMO_VideoDecoder_SetDestFmt(DMO_VideoDecoder *this, int bits, unsigned int c { case 15: this->m_sDestType.subtype = MEDIASUBTYPE_RGB555; - break; + break; case 16: this->m_sDestType.subtype = MEDIASUBTYPE_RGB565; break; @@ -409,7 +409,7 @@ int DMO_VideoDecoder_SetDestFmt(DMO_VideoDecoder *this, int bits, unsigned int c this->iv.m_obh.biCompression=3;//BI_BITFIELDS this->iv.m_obh.biSizeImage=abs((int)(2*this->iv.m_obh.biWidth*this->iv.m_obh.biHeight)); } - + if( bits == 16 ) { this->iv.m_obh.colors[0]=0xF800; this->iv.m_obh.colors[1]=0x07E0; @@ -459,7 +459,7 @@ int DMO_VideoDecoder_SetDestFmt(DMO_VideoDecoder *this, int bits, unsigned int c if (ok) { if (csp != 0 && csp != 3 && this->iv.m_obh.biHeight > 0) - this->iv.m_obh.biHeight *= -1; // YUV formats uses should have height < 0 + this->iv.m_obh.biHeight *= -1; // YUV formats uses should have height < 0 this->iv.m_obh.biSize = sizeof(BITMAPINFOHEADER); this->iv.m_obh.biCompression=csp; this->iv.m_obh.biBitCount=bits; @@ -532,9 +532,9 @@ int DMO_VideoDecoder_SetDestFmt(DMO_VideoDecoder *this, int bits, unsigned int c memcpy(&(this->m_sVhdr2->bmiHeader), &this->iv.m_decoder, sizeof(this->iv.m_decoder)); this->m_sVhdr2->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); if (this->m_sVhdr2->bmiHeader.biCompression == 3) - this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER) + 12; + this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER) + 12; else - this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); + this->m_sDestType.cbFormat = sizeof(VIDEOINFOHEADER); return -1; } diff --git a/src/libw32dll/dmo/Makefile.am b/src/libw32dll/dmo/Makefile.am index 2b7cd3e37..ad77447c2 100644 --- a/src/libw32dll/dmo/Makefile.am +++ b/src/libw32dll/dmo/Makefile.am @@ -17,7 +17,7 @@ libdmo_filter_la_SOURCES = \ dmo.c \ dmo_guids.c \ DMO_VideoDecoder.c - + noinst_HEADERS = \ DMO_AudioDecoder.h \ dmo_guids.h \ diff --git a/src/libw32dll/dmo/dmo.c b/src/libw32dll/dmo/dmo.c index 98cfbad40..103105040 100644 --- a/src/libw32dll/dmo/dmo.c +++ b/src/libw32dll/dmo/dmo.c @@ -61,7 +61,7 @@ DMO_Filter* DMO_FilterCreate(const char* dllname, const GUID* id, //trapbug(); hr = func(id, &IID_IClassFactory, (void**)&factory); if (hr || !factory) - { + { em = "no such class object"; break; } diff --git a/src/libw32dll/libwin32.h b/src/libw32dll/libwin32.h index e256ebf47..a8cc8504f 100644 --- a/src/libw32dll/libwin32.h +++ b/src/libw32dll/libwin32.h @@ -38,7 +38,7 @@ typedef struct _CodecInfo typedef struct _CImage // public your_libvo_mem { char* ptr; - + /*char* (*Data)(); { return 0; @@ -47,7 +47,7 @@ typedef struct _CImage // public your_libvo_mem /*int (*Supported)(fourcc_t csp, int bits); { return true; - // if you support such surface + // if you support such surface }*/ }CImage; @@ -105,18 +105,18 @@ struct IAudioEncoder typedef struct _BitmapInfo { - long biSize; - long biWidth; - long biHeight; - short biPlanes; - short biBitCount; - long biCompression; - long biSizeImage; - long biXPelsPerMeter; - long biYPelsPerMeter; - long biClrUsed; - long biClrImportant; - int colors[3]; + long biSize; + long biWidth; + long biHeight; + short biPlanes; + short biBitCount; + long biCompression; + long biSizeImage; + long biXPelsPerMeter; + long biYPelsPerMeter; + long biClrUsed; + long biClrImportant; + int colors[3]; } BitmapInfo; typedef struct _IVideoDecoder diff --git a/src/libw32dll/qt_decoder.c b/src/libw32dll/qt_decoder.c index 3053b2b68..f032b3827 100644 --- a/src/libw32dll/qt_decoder.c +++ b/src/libw32dll/qt_decoder.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -110,19 +110,19 @@ typedef struct SoundComponentData { typedef int (__cdecl* LPFUNC1)(long flag); -typedef int (__cdecl* LPFUNC2)(const SoundComponentData *, +typedef int (__cdecl* LPFUNC2)(const SoundComponentData *, const SoundComponentData *, SoundConverter *); typedef int (__cdecl* LPFUNC3)(SoundConverter sc); typedef int (__cdecl* LPFUNC4)(void); typedef int (__cdecl* LPFUNC5)(SoundConverter sc, OSType selector,void * infoPtr); -typedef int (__cdecl* LPFUNC6)(SoundConverter sc, +typedef int (__cdecl* LPFUNC6)(SoundConverter sc, unsigned long inputBytesTarget, unsigned long *inputFrames, unsigned long *inputBytes, unsigned long *outputBytes ); -typedef int (__cdecl* LPFUNC7)(SoundConverter sc, - const void *inputPtr, +typedef int (__cdecl* LPFUNC7)(SoundConverter sc, + const void *inputPtr, unsigned long inputFrames, void *outputPtr, unsigned long *outputFrames, @@ -131,7 +131,7 @@ typedef int (__cdecl* LPFUNC8)(SoundConverter sc, void *outputPtr, unsigned long *outputFrames, unsigned long *outputBytes); -typedef int (__cdecl* LPFUNC9)(SoundConverter sc) ; +typedef int (__cdecl* LPFUNC9)(SoundConverter sc) ; typedef struct { @@ -146,7 +146,7 @@ typedef struct qta_decoder_s { xine_stream_t *stream; - HINSTANCE qtml_dll; + HINSTANCE qtml_dll; xine_waveformatex wave; uint8_t out_buf[1000000]; @@ -173,7 +173,7 @@ typedef struct qta_decoder_s { uint8_t data[BUFSIZE]; int data_len; int num_frames; - + ldt_fs_t *ldt_fs; } qta_decoder_t; @@ -227,9 +227,9 @@ static void qta_init_driver (qta_decoder_t *this, buf_element_t *buf) { lprintf ("audio: init_driver... (mutex locked)\n"); this->ldt_fs = Setup_LDT_Keeper(); - + this->qtml_dll = LoadLibraryA("qtmlClient.dll"); - + if (this->qtml_dll == NULL ) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed to load dll\n" ); pthread_mutex_unlock(&win32_codec_mutex); @@ -240,63 +240,63 @@ static void qta_init_driver (qta_decoder_t *this, buf_element_t *buf) { this->InitializeQTML = (LPFUNC1)GetProcAddress (this->qtml_dll, "InitializeQTML"); if ( this->InitializeQTML == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed geting proc address InitializeQTML\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterOpen = (LPFUNC2)GetProcAddress (this->qtml_dll, "SoundConverterOpen"); if ( this->SoundConverterOpen == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterOpen\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterClose = (LPFUNC3)GetProcAddress (this->qtml_dll, "SoundConverterClose"); if ( this->SoundConverterClose == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterClose\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->TerminateQTML = (LPFUNC4)GetProcAddress (this->qtml_dll, "TerminateQTML"); if ( this->TerminateQTML == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address TerminateQTML\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterSetInfo = (LPFUNC5)GetProcAddress (this->qtml_dll, "SoundConverterSetInfo"); if ( this->SoundConverterSetInfo == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterSetInfo\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterGetBufferSizes = (LPFUNC6)GetProcAddress (this->qtml_dll, "SoundConverterGetBufferSizes"); if ( this->SoundConverterGetBufferSizes == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterGetBufferSizes\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterConvertBuffer = (LPFUNC7)GetProcAddress (this->qtml_dll, "SoundConverterConvertBuffer"); if ( this->SoundConverterConvertBuffer == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterConvertBuffer1\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterEndConversion = (LPFUNC8)GetProcAddress (this->qtml_dll, "SoundConverterEndConversion"); if ( this->SoundConverterEndConversion == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterEndConversion\n"); pthread_mutex_unlock(&win32_codec_mutex); return; } this->SoundConverterBeginConversion = (LPFUNC9)GetProcAddress (this->qtml_dll, "SoundConverterBeginConversion"); if ( this->SoundConverterBeginConversion == NULL ) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_audio: failed getting proc address SoundConverterBeginConversion\n"); pthread_mutex_unlock(&win32_codec_mutex); return; @@ -323,17 +323,17 @@ static void qta_init_driver (qta_decoder_t *this, buf_element_t *buf) { switch (buf->type) { case BUF_AUDIO_QDESIGN1: this->InputFormatInfo.format = FOUR_CHAR_CODE('Q','D','M','C'); - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "QDesign Music Codec v1 (QT DLL)"); break; case BUF_AUDIO_QDESIGN2: this->InputFormatInfo.format = FOUR_CHAR_CODE('Q','D','M','2'); - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "QDesign Music Codec v2 (QT DLL)"); break; case BUF_AUDIO_QCLP: this->InputFormatInfo.format = FOUR_CHAR_CODE('Q','c','l','p'); - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Qualcomm Purevoice Codec (QT DLL)"); break; default: @@ -352,8 +352,8 @@ static void qta_init_driver (qta_decoder_t *this, buf_element_t *buf) { qta_hexdump ((unsigned char *)buf->decoder_info_ptr[2], buf->decoder_info[2]); #endif - error = this->SoundConverterOpen (&this->InputFormatInfo, - &this->OutputFormatInfo, + error = this->SoundConverterOpen (&this->InputFormatInfo, + &this->OutputFormatInfo, &this->myConverter); lprintf ("audio: SoundConverterOpen:%i\n",error); @@ -392,7 +392,7 @@ static void qta_init_driver (qta_decoder_t *this, buf_element_t *buf) { error = this->SoundConverterBeginConversion (this->myConverter); lprintf ("audio: SoundConverterBeginConversion:%i\n",error); - if (error) { + if (error) { pthread_mutex_unlock(&win32_codec_mutex); return; } @@ -403,7 +403,7 @@ static void qta_init_driver (qta_decoder_t *this, buf_element_t *buf) { this->frame_size = this->wave.nChannels * this->wave.wBitsPerSample / 8; - this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, + this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, this->wave.wBitsPerSample, this->wave.nSamplesPerSec, @@ -433,17 +433,17 @@ static void qta_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->wave.nSamplesPerSec = buf->decoder_info[1]; lprintf ("audio: header copied\n"); - + } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) { lprintf ("audio: special buffer\n"); - + if (buf->decoder_info[1] == BUF_SPECIAL_STSD_ATOM) { lprintf ("audio: got stsd atom -> init codec\n"); if (!this->codec_initialized) { qta_init_driver (this, buf); } - + if (!this->codec_initialized) _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_HANDLED, 0); } @@ -457,13 +457,13 @@ static void qta_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { int num_frames = this->data_len / this->InFrameSize; long out_frames, out_bytes; int error, frames_left, bytes_sent; - + Check_FS_Segment(this->ldt_fs); pthread_mutex_lock(&win32_codec_mutex); error = this->SoundConverterConvertBuffer (this->myConverter, this->data, - num_frames, + num_frames, this->out_buf, &out_frames, &out_bytes); pthread_mutex_unlock(&win32_codec_mutex); @@ -474,7 +474,7 @@ static void qta_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->data_len -= this->InFrameSize * num_frames; if (this->data_len>0) memmove (this->data, this->data+num_frames*this->InFrameSize, this->data_len); - + frames_left = out_frames; bytes_sent = 0; @@ -498,21 +498,21 @@ static void qta_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { lprintf ("audio: sending %d frames, %d frames left\n", nframes, frames_left); - this->stream->audio_out->put_buffer (this->stream->audio_out, + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - + bytes_sent += nframes*this->frame_size; frames_left -= nframes; } } - + } } static void qta_reset (audio_decoder_t *this_gen) { qta_decoder_t *this = (qta_decoder_t *) this_gen; - + this->data_len = 0; } @@ -522,7 +522,7 @@ static void qta_discontinuity (audio_decoder_t *this_gen) { static void qta_dispose (audio_decoder_t *this_gen) { - qta_decoder_t *this = (qta_decoder_t *) this_gen; + qta_decoder_t *this = (qta_decoder_t *) this_gen; int error; unsigned long ConvertedFrames=0; unsigned long ConvertedBytes=0; @@ -548,12 +548,12 @@ static void qta_dispose (audio_decoder_t *this_gen) { free (this); } -static audio_decoder_t *qta_open_plugin (audio_decoder_class_t *class_gen, +static audio_decoder_t *qta_open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { qta_decoder_t *this ; - this = (qta_decoder_t *) xine_xmalloc (sizeof (qta_decoder_t)); + this = (qta_decoder_t *) calloc(1, sizeof(qta_decoder_t)); this->audio_decoder.decode_data = qta_decode_data; this->audio_decoder.reset = qta_reset; @@ -592,7 +592,7 @@ static void *qta_init_class (xine_t *xine, void *data) { pthread_once (&once_control, init_routine); - this = (qta_class_t *) xine_xmalloc (sizeof (qta_class_t)); + this = (qta_class_t *) calloc(1, sizeof(qta_class_t)); this->decoder_class.open_plugin = qta_open_plugin; this->decoder_class.get_identifier = qta_get_identifier; @@ -602,7 +602,7 @@ static void *qta_init_class (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_QDESIGN1, BUF_AUDIO_QDESIGN2, BUF_AUDIO_QCLP, @@ -636,7 +636,7 @@ typedef struct qtv_decoder_s { xine_stream_t *stream; - HINSTANCE qtml_dll; + HINSTANCE qtml_dll; xine_bmiheader bih; double ratio; @@ -658,8 +658,8 @@ typedef struct qtv_decoder_s { /* ImageSubCodecDecompressCapabilities icap; // for ImageCodecInitialize() */ Rect OutBufferRect; /* the dimensions of our GWorld */ - GWorldPtr OutBufferGWorld; /* a GWorld is some kind of - description for a drawing + GWorldPtr OutBufferGWorld; /* a GWorld is some kind of + description for a drawing environment */ ImageDescriptionHandle framedescHandle; @@ -691,7 +691,7 @@ typedef struct qtv_decoder_s { CodecDecompressParams * params); ComponentResult (*ImageCodecBandDecompress)(ComponentInstance ci, CodecDecompressParams * params); - PixMapHandle (*GetGWorldPixMap) (GWorldPtr offscreenGWorld); + PixMapHandle (*GetGWorldPixMap) (GWorldPtr offscreenGWorld); OSErr (*QTNewGWorldFromPtr)(GWorldPtr *gw, OSType pixelFormat, const Rect *boundsRect, @@ -699,7 +699,7 @@ typedef struct qtv_decoder_s { /*GDHandle*/void* aGDevice, /*unused*/ GWorldFlags flags, void *baseAddr, - long rowBytes); + long rowBytes); OSErr (*NewHandleClear)(Size byteCount); ldt_fs_t *ldt_fs; @@ -759,9 +759,9 @@ static void qtv_init_driver (qtv_decoder_t *this, buf_element_t *buf) { lprintf ("video: mutex locked\n"); this->ldt_fs = Setup_LDT_Keeper(); - + this->qtml_dll = LoadLibraryA("qtmlClient.dll"); - + if (this->qtml_dll == NULL ) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_video: failed to load dll\n" ); pthread_mutex_unlock(&win32_codec_mutex); @@ -784,8 +784,8 @@ static void qtv_init_driver (qtv_decoder_t *this, buf_element_t *buf) { this->GetGWorldPixMap = (PixMapHandle(*)(GWorldPtr))GetProcAddress(this->qtml_dll, "GetGWorldPixMap"); this->QTNewGWorldFromPtr = (OSErr(*)(GWorldPtr*,OSType,const Rect*,CTabHandle,void*,GWorldFlags,void*,long))GetProcAddress(this->qtml_dll, "QTNewGWorldFromPtr"); this->NewHandleClear = (OSErr(*)(Size))GetProcAddress(this->qtml_dll, "NewHandleClear"); - - if (!this->InitializeQTML || !this->EnterMovies || !this->FindNextComponent + + if (!this->InitializeQTML || !this->EnterMovies || !this->FindNextComponent || !this->ImageCodecBandDecompress){ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_video: invalid qt DLL!\n"); pthread_mutex_unlock(&win32_codec_mutex); @@ -872,7 +872,7 @@ static void qtv_init_driver (qtv_decoder_t *this, buf_element_t *buf) { memcpy(&id->name,stdata+0x2D,32); id->depth = _X_BE_16 (stdata+0x4E); id->clutID = _X_BE_16 (stdata+0x50); - if (stdata_len>0x56) + if (stdata_len>0x56) memcpy (((char*)&id->clutID)+2, stdata+0x52, stdata_len-0x52); lprintf ("video: id (%d bytes)\n", stdata_len); @@ -900,12 +900,12 @@ static void qtv_init_driver (qtv_decoder_t *this, buf_element_t *buf) { this->plane = malloc (this->bih.biWidth * this->bih.biHeight * 3); - result = this->QTNewGWorldFromPtr(&this->OutBufferGWorld, + result = this->QTNewGWorldFromPtr(&this->OutBufferGWorld, kYUVSPixelFormat, /*pixel format of new GWorld==YUY2 */ &this->OutBufferRect, /*we should benchmark if yvu9 is faster for svq3, too */ - 0, - 0, - 0, + 0, + 0, + 0, this->plane, this->bih.biWidth*2); @@ -922,14 +922,14 @@ static void qtv_init_driver (qtv_decoder_t *this, buf_element_t *buf) { this->decpar.accuracy = codecNormalQuality; this->decpar.port = (CGrafPtr)this->OutBufferGWorld; this->decpar.srcRect = this->OutBufferRect; - + this->decpar.transferMode = srcCopy; this->decpar.dstPixMap = **this->GetGWorldPixMap (this->OutBufferGWorld);/*destPixmap; */ - + cres = this->ImageCodecPreDecompress (this->ci, &this->decpar); lprintf ("video: ImageCodecPreDecompress cres=0x%X\n", cres); - + this->data_len = 0; this->codec_initialized = 1; @@ -943,7 +943,7 @@ static void qtv_init_driver (qtv_decoder_t *this, buf_element_t *buf) { static void qtv_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { qtv_decoder_t *this = (qtv_decoder_t *) this_gen; - lprintf ("video: decode_data, flags=0x%08x, len=%d, pts=%lld ...\n", + lprintf ("video: decode_data, flags=0x%08x, len=%d, pts=%lld ...\n", buf->decoder_flags, buf->size, buf->pts); if (buf->decoder_flags & BUF_FLAG_STDHEADER) { @@ -957,7 +957,7 @@ static void qtv_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) { lprintf ("video: special buffer\n"); - + if (buf->decoder_info[1] == BUF_SPECIAL_STSD_ATOM) { lprintf ("video: got stsd atom -> init codec\n"); @@ -975,12 +975,12 @@ static void qtv_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { this->data_len += buf->size; lprintf ("video: got %d bytes in buffer\n", this->data_len); - + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { ComponentResult cres; vo_frame_t *img; - + Check_FS_Segment(this->ldt_fs); pthread_mutex_lock(&win32_codec_mutex); @@ -990,30 +990,30 @@ static void qtv_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { (**this->framedescHandle).dataSize=this->data_len; cres = this->ImageCodecBandDecompress (this->ci, &this->decpar); - + ++this->decpar.frameNumber; pthread_mutex_unlock(&win32_codec_mutex); if (cres&0xFFFF){ - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "qt_video: ImageCodecBandDecompress cres=0x%lX (-0x%lX) %ld :(\n", cres,-cres,cres); } img = this->stream->video_out->get_frame (this->stream->video_out, this->bih.biWidth, this->bih.biHeight, - this->ratio, + this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); - + img->pts = buf->pts; img->duration = buf->decoder_info[0]; img->bad_frame = 0; - - xine_fast_memcpy (img->base[0], this->plane, + + xine_fast_memcpy (img->base[0], this->plane, this->bih.biWidth*this->bih.biHeight*2); - + img->draw(img, this->stream); img->free(img); @@ -1032,7 +1032,7 @@ static void qtv_flush (video_decoder_t *this_gen) { static void qtv_reset (video_decoder_t *this_gen) { qtv_decoder_t *this = (qtv_decoder_t *) this_gen; - + this->data_len = 0; } @@ -1057,13 +1057,13 @@ static void qtv_dispose (video_decoder_t *this_gen) { free (this); } -static video_decoder_t *qtv_open_plugin (video_decoder_class_t *class_gen, +static video_decoder_t *qtv_open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { qtv_class_t *cls = (qtv_class_t *) class_gen; qtv_decoder_t *this ; - this = (qtv_decoder_t *) xine_xmalloc (sizeof (qtv_decoder_t)); + this = (qtv_decoder_t *) calloc(1, sizeof(qtv_decoder_t)); this->video_decoder.decode_data = qtv_decode_data; this->video_decoder.flush = qtv_flush; @@ -1094,13 +1094,13 @@ static void qtv_dispose_class (video_decoder_class_t *this) { } /* - * some fake functions to make qt codecs happy + * some fake functions to make qt codecs happy */ #if 0 static void codec_path_cb (void *data, xine_cfg_entry_t *cfg) { qtv_class_t *this = (qt_class_t *) data; - + this->qt_codec_path = cfg->str_value; } #endif @@ -1116,7 +1116,7 @@ static void *qtv_init_class (xine_t *xine, void *data) { pthread_once (&once_control, init_routine); - this = (qtv_class_t *) xine_xmalloc (sizeof (qtv_class_t)); + this = (qtv_class_t *) calloc(1, sizeof(qtv_class_t)); this->decoder_class.open_plugin = qtv_open_plugin; this->decoder_class.get_identifier = qtv_get_identifier; @@ -1138,7 +1138,7 @@ static const decoder_info_t qtv_dec_info = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER | PLUGIN_MUST_PRELOAD, 18, "qtv", XINE_VERSION_CODE, &qtv_dec_info, qtv_init_class }, { PLUGIN_AUDIO_DECODER | PLUGIN_MUST_PRELOAD, 15, "qta", XINE_VERSION_CODE, &qta_dec_info, qta_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/libw32dll/qtx/qtxsdk/components.h b/src/libw32dll/qtx/qtxsdk/components.h index 1456342f9..11e0824c9 100644 --- a/src/libw32dll/qtx/qtxsdk/components.h +++ b/src/libw32dll/qtx/qtxsdk/components.h @@ -721,13 +721,13 @@ static inline void dump_CodecDecompressParams(void* xxx){ printf("sequenceID=%ld\n",cd->sequenceID); idh=cd->imageDescription; if(idh && idh[0]) dump_ImageDescription(idh[0]); - + for(i=0;i<sizeof(CodecDecompressParams);i++){ printf(" %02X",((unsigned char*)cd)[i]); if((i%16)==15) printf("\n"); } printf("\n"); - + printf("data=%p size=%ld\n",cd->data,cd->bufferSize); printf("frameno=%ld lines: %ld .. %ld condflags=0x%lX callerflags=0x%X\n", cd->frameNumber, cd->startLine, cd->stopLine, cd->conditionFlags,cd->callerFlags); diff --git a/src/libw32dll/w32codec.c b/src/libw32dll/w32codec.c index 88790ebc7..32cd7db29 100644 --- a/src/libw32dll/w32codec.c +++ b/src/libw32dll/w32codec.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,7 +21,11 @@ * DirectShow support by Miguel Freitas (Nov/2001) * DMO support (Dez/2002) */ - + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <inttypes.h> @@ -33,8 +37,8 @@ #include "wine/vfw.h" #include "wine/mmreg.h" #include "wine/ldt_keeper.h" -#include "wine/win32.h" -#include "wine/wineacm.h" +#include "wine/win32.h" +#include "wine/wineacm.h" #include "wine/loader.h" #define NOAVIFILE_HEADERS @@ -63,13 +67,13 @@ static GUID CLSID_Voxware = 0x73f7a062, 0x8829, 0x11d1, { 0xb5, 0x50, 0x00, 0x60, 0x97, 0x24, 0x2d, 0x8d } }; - + static GUID CLSID_Acelp = { 0x4009f700, 0xaeba, 0x11d1, { 0x83, 0x44, 0x00, 0xc0, 0x4f, 0xb9, 0x2e, 0xb7 } }; - + static GUID wmv1_clsid = { 0x4facbba1, 0xffd8, 0x4cd7, @@ -142,11 +146,11 @@ typedef struct w32v_decoder_s { video_decoder_t video_decoder; xine_stream_t *stream; - + int64_t video_step; int decoder_ok; - BITMAPINFOHEADER *bih, o_bih; + BITMAPINFOHEADER *bih, o_bih; double ratio; char scratch1[16]; /* some codecs overflow o_bih */ HIC hic; @@ -158,7 +162,7 @@ typedef struct w32v_decoder_s { void *img_buffer; int size; long outfmt; - + int ex_functions; int driver_type; GUID *guid; @@ -166,8 +170,8 @@ typedef struct w32v_decoder_s { DMO_VideoDecoder *dmo_dec; int stream_id; - int skipframes; - + int skipframes; + ldt_fs_t *ldt_fs; } w32v_decoder_t; @@ -177,7 +181,7 @@ typedef struct { typedef struct w32a_decoder_s { audio_decoder_t audio_decoder; - + xine_stream_t *stream; int output_open; @@ -186,25 +190,25 @@ typedef struct w32a_decoder_s { unsigned char *buf; int size; int64_t pts; - + /* these are used for pts estimation */ int64_t lastpts, sumpts, sumsize; double byterate; unsigned char *outbuf; int outsize; - + HACMSTREAM srcstream; int rec_audio_src_size; int max_audio_src_size; int num_channels; int rate; - + int driver_type; GUID *guid; DS_AudioDecoder *ds_dec; DMO_AudioDecoder *dmo_dec; - + ldt_fs_t *ldt_fs; } w32a_decoder_t; @@ -238,7 +242,7 @@ typedef struct { #define CENTERSAMPLE 128 #define SCALEBITS 16 -#define FIX(x) ( (int32_t) ( (x) * (1<<SCALEBITS) + 0.5 ) ) +#define FIX(x) ( (int32_t) ( (x) * (1<<SCALEBITS) + 0.5 ) ) #define ONE_HALF ( (int32_t) (1<< (SCALEBITS-1)) ) #define CBCR_OFFSET (CENTERSAMPLE << SCALEBITS) @@ -276,7 +280,7 @@ static void w32v_init_rgb_ycc(void) * the YCbCr constants times R,G,B for all possible values. */ int i; - + if (rgb_ycc_tab) return; rgb_ycc_tab = malloc(TABLE_SIZE * sizeof(int32_t)); @@ -345,14 +349,14 @@ static char* get_vids_codec_name(w32v_decoder_t *this, this->flipped=0; this->driver_type = DRIVER_STD; this->ex_functions = 0; - + buf_type &= 0xffff0000; switch (buf_type) { case BUF_VIDEO_MSMPEG4_V1: case BUF_VIDEO_MSMPEG4_V2: /* Microsoft MPEG-4 v1/v2 */ - /* old dll is disabled now due segfaults + /* old dll is disabled now due segfaults * (using directshow instead) this->yuv_supported=1; this->yuv_hack_needed=1; @@ -364,7 +368,7 @@ static char* get_vids_codec_name(w32v_decoder_t *this, this->guid=&msmpeg4_clsid; _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "MS MPEG-4 V1/V2 (win32)"); - return "mpg4ds32.ax"; + return "mpg4ds32.ax"; case BUF_VIDEO_MSMPEG4_V3: /* Microsoft MPEG-4 v3 */ @@ -379,28 +383,28 @@ static char* get_vids_codec_name(w32v_decoder_t *this, /* Video in Indeo Video 5 format */ this->yuv_supported=1; /* YUV pic is upside-down :( */ this->flipped=0; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Indeo Video 5 (win32)"); return "ir50_32.dll"; case BUF_VIDEO_IV41: /* Video in Indeo Video 4.1 format */ this->flipped=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Indeo Video 4.1 (win32)"); return "ir41_32.dll"; - + case BUF_VIDEO_IV32: /* Video in Indeo Video 3.2 format */ this->flipped=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Indeo Video 3.2 (win32)"); return "ir32_32.dll"; - + case BUF_VIDEO_IV31: /* Video in Indeo Video 3.1 format */ this->flipped=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Indeo Video 3.1 (win32)"); return "ir32_32.dll"; @@ -408,7 +412,7 @@ static char* get_vids_codec_name(w32v_decoder_t *this, /* Video in Cinepak format */ this->flipped=1; this->yuv_supported=0; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Cinepak (win32)"); return "iccvid.dll"; @@ -421,15 +425,15 @@ static char* get_vids_codec_name(w32v_decoder_t *this, case BUF_VIDEO_ATIVCR2: /* Video in ATI VCR2 format */ this->yuv_supported=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "ATI VCR2 (win32)"); return "ativcr2.dll"; - + case BUF_VIDEO_I263: /* Video in I263 format */ this->flipped=1; this->yuv_supported=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "I263 (win32)"); return "i263_32.drv"; @@ -438,22 +442,22 @@ static char* get_vids_codec_name(w32v_decoder_t *this, /* note: can't play streams with 8bpp */ this->flipped=1; this->yuv_supported=0; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "MS Windows Video 1 (win32)"); - return "msvidc32.dll"; - + return "msvidc32.dll"; + case BUF_VIDEO_DV: /* Sony DV Codec (not working yet) */ this->yuv_supported=1; this->driver_type = DRIVER_DS; this->guid=&dvsd_clsid; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Sony DV (win32)"); - return "qdv.dll"; - + return "qdv.dll"; + case BUF_VIDEO_WMV7: this->yuv_supported=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "MS WMV 7 (win32)"); if (n == 2) { this->driver_type = DRIVER_DMO; @@ -462,11 +466,11 @@ static char* get_vids_codec_name(w32v_decoder_t *this, } this->driver_type = DRIVER_DS; this->guid=&wmv1_clsid; - return "wmvds32.ax"; - + return "wmvds32.ax"; + case BUF_VIDEO_WMV8: this->yuv_supported=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "MS WMV 8 (win32)"); if (n == 2) { this->driver_type = DRIVER_DMO; @@ -476,11 +480,11 @@ static char* get_vids_codec_name(w32v_decoder_t *this, this->driver_type = DRIVER_DS; this->guid=&wmv2_clsid; return "wmv8ds32.ax"; - + case BUF_VIDEO_WMV9: this->yuv_supported=1; this->driver_type = DRIVER_DMO; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "MS WMV 9 (win32)"); if (n == 2) { this->guid=&wmvdmo_clsid; @@ -488,14 +492,14 @@ static char* get_vids_codec_name(w32v_decoder_t *this, } this->guid=&wmv3_clsid; return "wmv9dmod.dll"; - + case BUF_VIDEO_VP31: this->yuv_supported=1; this->ex_functions=1; this->flipped=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "On2 VP3.1 (win32)"); - return "vp31vfw.dll"; + return "vp31vfw.dll"; case BUF_VIDEO_VP4: this->yuv_supported=1; @@ -503,46 +507,46 @@ static char* get_vids_codec_name(w32v_decoder_t *this, _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "On2 VP4 (win32)"); return "vp4vfw.dll"; - + case BUF_VIDEO_VP5: this->yuv_supported=1; this->ex_functions=1; _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "On2 VP5 (win32)"); return "vp5vfw.dll"; - + case BUF_VIDEO_VP6: this->yuv_supported=1; this->ex_functions=1; _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "On2 VP6 (win32)"); return "vp6vfw.dll"; - + case BUF_VIDEO_MSS1: this->driver_type = DRIVER_DS; this->guid=&mss1_clsid; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Windows Screen Video (win32)"); - return "msscds32.ax"; + return "msscds32.ax"; case BUF_VIDEO_TSCC: this->flipped=1; this->yuv_supported=0; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "TechSmith Screen Capture Codec (win32)"); - return "tsccvid.dll"; - + return "tsccvid.dll"; + case BUF_VIDEO_UCOD: this->yuv_supported=1; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "ClearVideo (win32)"); - return "clrviddd.dll"; - + return "clrviddd.dll"; + } xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: this didn't happen: unknown video buf type %08x\n", buf_type); - + return NULL; } @@ -566,9 +570,9 @@ static void w32v_init_codec (w32v_decoder_t *this, int buf_type) { memset(&this->o_bih, 0, sizeof(BITMAPINFOHEADER)); this->o_bih.biSize = sizeof(BITMAPINFOHEADER); - + this->ldt_fs = Setup_LDT_Keeper(); - + outfmt = IMGFMT_15RGB; if (this->yuv_supported) { vo_cap = this->stream->video_out->get_capabilities (this->stream->video_out); @@ -576,12 +580,12 @@ static void w32v_init_codec (w32v_decoder_t *this, int buf_type) { outfmt = IMGFMT_YUY2; } - this->hic = ICOpen ((int)win32_codec_name, - this->bih->biCompression, + this->hic = ICOpen ((int)win32_codec_name, + this->bih->biCompression, ICMODE_FASTDECOMPRESS); if(!this->hic){ - xine_log (this->stream->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: ICOpen failed! unknown codec %08lx / wrong parameters?\n"), this->bih->biCompression); this->decoder_ok = 0; @@ -590,14 +594,14 @@ static void w32v_init_codec (w32v_decoder_t *this, int buf_type) { ret = ICDecompressGetFormat(this->hic, this->bih, &this->o_bih); if(ret){ - xine_log (this->stream->xine, XINE_LOG_MSG, + xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: ICDecompressGetFormat (%.4s %08lx/%d) failed: Error %ld\n"), - (char*)&this->o_bih.biCompression, this->bih->biCompression, - this->bih->biBitCount, (long)ret); + (char*)&this->o_bih.biCompression, this->bih->biCompression, + this->bih->biBitCount, (long)ret); this->decoder_ok = 0; return; } - + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: video output format: %.4s %08lx\n", (char*)&this->o_bih.biCompression, this->o_bih.biCompression); @@ -611,28 +615,28 @@ static void w32v_init_codec (w32v_decoder_t *this, int buf_type) { * this->o_bih.biBitCount / 8; if (this->flipped) - this->o_bih.biHeight=-this->bih->biHeight; + this->o_bih.biHeight=-this->bih->biHeight; if(outfmt==IMGFMT_YUY2 && !this->yuv_hack_needed) this->o_bih.biCompression = mmioFOURCC('Y','U','Y','2'); - else + else this->o_bih.biCompression = 0; - - ret = (!this->ex_functions) + + ret = (!this->ex_functions) ?ICDecompressQuery(this->hic, this->bih, &this->o_bih) :ICDecompressQueryEx(this->hic, this->bih, &this->o_bih); - + if(ret){ xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: ICDecompressQuery failed: Error %ld\n"), (long)ret); this->decoder_ok = 0; return; } - - ret = (!this->ex_functions) + + ret = (!this->ex_functions) ?ICDecompressBegin(this->hic, this->bih, &this->o_bih) :ICDecompressBeginEx(this->hic, this->bih, &this->o_bih); - + if(ret){ xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: ICDecompressBegin failed: Error %ld\n"), (long)ret); @@ -641,14 +645,14 @@ static void w32v_init_codec (w32v_decoder_t *this, int buf_type) { } if (outfmt==IMGFMT_YUY2 && this->yuv_hack_needed) - this->o_bih.biCompression = mmioFOURCC('Y','U','Y','2'); + this->o_bih.biCompression = mmioFOURCC('Y','U','Y','2'); this->size = 0; if ( this->img_buffer ) free (this->img_buffer); this->img_buffer = malloc (this->o_bih.biSizeImage); - + if ( this->buf ) free (this->buf); this->bufsize = VIDEOBUFSIZE; @@ -663,14 +667,14 @@ static void w32v_init_codec (w32v_decoder_t *this, int buf_type) { static void w32v_init_ds_dmo_codec (w32v_decoder_t *this, int buf_type) { uint32_t vo_cap; int outfmt; - + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: init DirectShow/DMO video codec...\n"); - + memset(&this->o_bih, 0, sizeof(BITMAPINFOHEADER)); this->o_bih.biSize = sizeof(BITMAPINFOHEADER); this->ldt_fs = Setup_LDT_Keeper(); - + /* hack: dvsd is the only fourcc accepted by qdv.dll */ if( buf_type == BUF_VIDEO_DV ) this->bih->biCompression = mmioFOURCC('d','v','s','d'); @@ -678,7 +682,7 @@ static void w32v_init_ds_dmo_codec (w32v_decoder_t *this, int buf_type) { if( this->driver_type == DRIVER_DS ) { this->ds_dec = DS_VideoDecoder_Open(win32_codec_name, this->guid, this->bih, this->flipped, 0); - + if(!this->ds_dec){ xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: DS_VideoDecoder failed! unknown codec %08lx / wrong parameters?\n"), @@ -689,7 +693,7 @@ static void w32v_init_ds_dmo_codec (w32v_decoder_t *this, int buf_type) { } else { this->dmo_dec = DMO_VideoDecoder_Open(win32_codec_name, this->guid, this->bih, this->flipped, 0); - + if(!this->dmo_dec){ xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: DMO_VideoDecoder failed! unknown codec %08lx / wrong parameters?\n"), @@ -698,7 +702,7 @@ static void w32v_init_ds_dmo_codec (w32v_decoder_t *this, int buf_type) { return; } } - + outfmt = IMGFMT_15RGB; if (this->yuv_supported) { vo_cap = this->stream->video_out->get_capabilities (this->stream->video_out); @@ -713,42 +717,42 @@ static void w32v_init_ds_dmo_codec (w32v_decoder_t *this, int buf_type) { this->o_bih.biWidth = this->bih->biWidth; this->o_bih.biHeight = this->bih->biHeight; - + this->o_bih.biSizeImage = this->o_bih.biWidth * this->o_bih.biHeight * this->o_bih.biBitCount / 8; if (this->flipped) - this->o_bih.biHeight=-this->bih->biHeight; + this->o_bih.biHeight=-this->bih->biHeight; if(outfmt==IMGFMT_YUY2 && !this->yuv_hack_needed) this->o_bih.biCompression = mmioFOURCC('Y','U','Y','2'); - else + else this->o_bih.biCompression = 0; - + if( this->driver_type == DRIVER_DS ) DS_VideoDecoder_SetDestFmt(this->ds_dec, this->o_bih.biBitCount, this->o_bih.biCompression); else DMO_VideoDecoder_SetDestFmt(this->dmo_dec, this->o_bih.biBitCount, this->o_bih.biCompression); - + if (outfmt==IMGFMT_YUY2 && this->yuv_hack_needed) - this->o_bih.biCompression = mmioFOURCC('Y','U','Y','2'); - + this->o_bih.biCompression = mmioFOURCC('Y','U','Y','2'); + if( this->driver_type == DRIVER_DS ) DS_VideoDecoder_StartInternal(this->ds_dec); else DMO_VideoDecoder_StartInternal(this->dmo_dec); - + this->size = 0; if ( this->img_buffer ) free (this->img_buffer); this->img_buffer = malloc (this->o_bih.biSizeImage); - + if ( this->buf ) free (this->buf); this->bufsize = VIDEOBUFSIZE; this->buf = malloc(this->bufsize); - + (this->stream->video_out->open) (this->stream->video_out, this->stream); this->outfmt = outfmt; @@ -759,26 +763,26 @@ static void w32v_init_ds_dmo_codec (w32v_decoder_t *this, int buf_type) { static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { w32v_decoder_t *this = (w32v_decoder_t *) this_gen; - lprintf ("processing packet type = %08x, buf->decoder_flags=%08x\n", + lprintf ("processing packet type = %08x, buf->decoder_flags=%08x\n", buf->type, buf->decoder_flags); - + if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; - + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); - + lprintf ("video_step is %lld\n", this->video_step); } - + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { int num_decoders; if ( buf->type & 0xff ) return; - - lprintf ("processing header ...\n"); + + lprintf ("processing header ...\n"); /* init package containing bih */ if( this->bih ) @@ -812,7 +816,7 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if( !this->decoder_ok ) { xine_log (this->stream->xine, XINE_LOG_MSG, - _("w32codec: decoder failed to start. Is '%s' installed?\n"), + _("w32codec: decoder failed to start. Is '%s' installed?\n"), win32_codec_name ); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HANDLED, 0); _x_message(this->stream, XINE_MSG_LIBRARY_LOAD_ERROR, @@ -820,30 +824,30 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } pthread_mutex_unlock(&win32_codec_mutex); - + this->stream_id = -1; this->skipframes = 0; - + } else if (this->decoder_ok) { - lprintf ("processing packet ...\n"); + lprintf ("processing packet ...\n"); if( (int) buf->size <= 0 ) return; - + if( this->stream_id < 0 ) this->stream_id = buf->type & 0xff; - + if( this->stream_id != (buf->type & 0xff) ) return; - + if( this->size + buf->size > this->bufsize ) { this->bufsize = this->size + 2 * buf->size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: increasing source buffer to %d to avoid overflow.\n", this->bufsize); this->buf = realloc( this->buf, this->bufsize ); } - + xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; @@ -860,11 +864,11 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { /* decoder video frame */ this->bih->biSizeImage = this->size; - + img = this->stream->video_out->get_frame (this->stream->video_out, - this->bih->biWidth, - this->bih->biHeight, - this->ratio, + this->bih->biWidth, + this->bih->biHeight, + this->ratio, IMGFMT_YUY2, VO_BOTH_FIELDS); @@ -874,7 +878,7 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if (this->outfmt==IMGFMT_YUY2) img_buffer = img->base[0]; - + flags = 0; if( !(buf->decoder_flags & BUF_FLAG_KEYFRAME) ) flags |= ICDECOMPRESS_NOTKEYFRAME; @@ -883,16 +887,16 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { if( this->skipframes && (buf->type & ~0xff) != BUF_VIDEO_IV32 ) img_buffer = NULL; - + pthread_mutex_lock(&win32_codec_mutex); if( this->driver_type == DRIVER_STD ) ret = (!this->ex_functions) ?ICDecompress(this->hic, flags, - this->bih, this->buf, &this->o_bih, + this->bih, this->buf, &this->o_bih, img_buffer) :ICDecompressEx(this->hic, flags, this->bih, this->buf, &this->o_bih, - img_buffer); + img_buffer); else if( this->driver_type == DRIVER_DS ) { ret = DS_VideoDecoder_DecodeInternal(this->ds_dec, this->buf, this->size, buf->decoder_flags & BUF_FLAG_KEYFRAME, @@ -903,7 +907,7 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { img_buffer); } pthread_mutex_unlock(&win32_codec_mutex); - + if (!this->skipframes) { if (this->outfmt==IMGFMT_YUY2) { /* already decoded into YUY2 format by DLL */ @@ -917,23 +921,23 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { #if HAS_SLOW_MULT int32_t *ctab = rgb_ycc_tab; #endif - + for (row=0; row<this->bih->biHeight; row++) { - + uint16_t *pixel, *out; - + pixel = (uint16_t *) ( (uint8_t *)this->img_buffer + 2 * row * this->o_bih.biWidth ); out = (uint16_t *) (img->base[0] + row * img->pitches[0] ); - + for (col=0; col<this->o_bih.biWidth; col++, pixel++, out++) { - + uint8_t r,g,b; uint8_t y,u,v; - + b = (*pixel & 0x001F) << 3; g = (*pixel & 0x03E0) >> 5 << 3; r = (*pixel & 0x7C00) >> 10 << 3; - + #if HAS_SLOW_MULT y = (ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF]) >> SCALEBITS; if (!(col & 0x0001)) { @@ -962,19 +966,19 @@ static void w32v_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } } } - + img->pts = buf->pts; if (ret || this->skipframes) { if (!this->skipframes) xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "w32codec: Error decompressing frame, err=%ld\n", (long)ret); + "w32codec: Error decompressing frame, err=%ld\n", (long)ret); img->bad_frame = 1; lprintf ("BAD FRAME, duration is %d\n", img->duration); } else { img->bad_frame = 0; lprintf ("GOOD FRAME, duration is %d\n\n", img->duration); } - + this->skipframes = img->draw(img, this->stream); lprintf ("skipframes is %d\n", this->skipframes); @@ -996,15 +1000,15 @@ static void w32v_flush (video_decoder_t *this_gen) { static void w32v_reset (video_decoder_t *this_gen) { w32v_decoder_t *this = (w32v_decoder_t *) this_gen; - + /* FIXME: need to improve this function. currently it doesn't avoid artifacts when seeking. */ - + pthread_mutex_lock(&win32_codec_mutex); if( this->driver_type == DRIVER_STD ) { if( this->hic ) { - if (!this->ex_functions) + if (!this->ex_functions) ICDecompressBegin(this->hic, this->bih, &this->o_bih); else ICDecompressBeginEx(this->hic, this->bih, &this->o_bih); @@ -1045,7 +1049,7 @@ static void w32v_dispose (video_decoder_t *this_gen) { free (this->img_buffer); this->img_buffer = NULL; } - + if ( this->buf ) { free (this->buf); this->buf = NULL; @@ -1056,7 +1060,7 @@ static void w32v_dispose (video_decoder_t *this_gen) { this->bih = NULL; } - if( this->decoder_ok ) { + if( this->decoder_ok ) { this->decoder_ok = 0; this->stream->video_out->close(this->stream->video_out, this->stream); } @@ -1075,23 +1079,23 @@ static char* get_auds_codec_name(w32a_decoder_t *this, int buf_type) { switch (buf_type) { case BUF_AUDIO_WMAV1: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Windows Media Audio v1 (win32)"); return "divxa32.acm"; case BUF_AUDIO_WMAV2: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Windows Media Audio v2 (win32)"); return "divxa32.acm"; case BUF_AUDIO_WMAV3: this->driver_type = DRIVER_DMO; this->guid=&wma3_clsid; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Windows Media Audio v3 (win32)"); return "wma9dmod.dll"; case BUF_AUDIO_WMALL: this->driver_type = DRIVER_DMO; this->guid=&wma3_clsid; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Windows Media Audio Lossless (win32)"); return "wma9dmod.dll"; case BUF_AUDIO_WMAV: @@ -1101,43 +1105,43 @@ static char* get_auds_codec_name(w32a_decoder_t *this, int buf_type) { "Windows Media Audio Voice (win32)"); return "wmspdmod.dll"; case BUF_AUDIO_MSADPCM: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "MS ADPCM (win32)"); return "msadp32.acm"; case BUF_AUDIO_MSIMAADPCM: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "MS IMA ADPCM (win32)"); return "imaadp32.acm"; case BUF_AUDIO_MSGSM: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "MS GSM (win32)"); return "msgsm32.acm"; case BUF_AUDIO_IMC: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Intel Music Coder (win32)"); return "imc32.acm"; case BUF_AUDIO_LH: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Lernout & Hauspie (win32)"); return "lhacm.acm"; case BUF_AUDIO_VOXWARE: this->driver_type = DRIVER_DS; this->guid=&CLSID_Voxware; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Voxware Metasound (win32)"); return "voxmsdec.ax"; case BUF_AUDIO_ACELPNET: this->driver_type = DRIVER_DS; this->guid=&CLSID_Acelp; - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "ACELP.net (win32)"); return "acelpdec.ax"; case BUF_AUDIO_VIVOG723: - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Vivo G.723/Siren Audio Codec (win32)"); return "vivog723.acm"; } - + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: this didn't happen: unknown audio buf type %08x\n", buf_type); return NULL; @@ -1161,7 +1165,7 @@ static int w32a_init_audio (w32a_decoder_t *this, uint8_t *buf, int bufsize, int buftype) { HRESULT ret; - WAVEFORMATEX wf; + WAVEFORMATEX wf; WAVEFORMATEX *in_fmt; unsigned long in_size; unsigned long out_size; @@ -1174,19 +1178,19 @@ static int w32a_init_audio (w32a_decoder_t *this, this->srcstream = 0; this->num_channels = (in_fmt->nChannels >= 2)?2:1; this->rate = in_fmt->nSamplesPerSec; - + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = (this->stream->audio_out->open) ( this->stream->audio_out, this->stream, - 16, in_fmt->nSamplesPerSec, + 16, in_fmt->nSamplesPerSec, _x_ao_channels2mode(in_fmt->nChannels)); if (!this->output_open) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: (ACM_Decoder) Cannot open audio output device\n"); return 0; } - + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); audio_buffer_mem_size = audio_buffer->mem_size; audio_buffer->num_frames = 0; @@ -1200,12 +1204,12 @@ static int w32a_init_audio (w32a_decoder_t *this, wf.nBlockAlign = 2*in_fmt->nChannels; wf.wBitsPerSample = 16; wf.cbSize = 0; - + this->ldt_fs = Setup_LDT_Keeper(); win32_codec_name = get_auds_codec_name (this, buftype); - + if( this->driver_type == DRIVER_STD ) { - + MSACM_RegisterDriver(win32_codec_name, in_fmt->wFormatTag, 0); ret=acmStreamOpen(&this->srcstream,(HACMDRIVER)NULL, @@ -1225,73 +1229,73 @@ static int w32a_init_audio (w32a_decoder_t *this, acmStreamSize(this->srcstream, in_size, &out_size, ACM_STREAMSIZEF_SOURCE); out_size*=2; - if(out_size < audio_buffer_mem_size) + if(out_size < audio_buffer_mem_size) out_size=audio_buffer_mem_size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: Audio buffer min. size: %d\n",(int)out_size); - - acmStreamSize(this->srcstream, out_size, (LPDWORD) &this->rec_audio_src_size, + + acmStreamSize(this->srcstream, out_size, (LPDWORD) &this->rec_audio_src_size, ACM_STREAMSIZEF_DESTINATION); } else if( this->driver_type == DRIVER_DS ) { this->ds_dec=DS_AudioDecoder_Open(win32_codec_name,this->guid, in_fmt); - + if( this->ds_dec == NULL ) { xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: Error initializing DirectShow Audio\n")); this->srcstream = 0; return 0; } - - out_size = audio_buffer_mem_size; + + out_size = audio_buffer_mem_size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: output buffer size: %d\n",(int)out_size); this->rec_audio_src_size=DS_AudioDecoder_GetSrcSize(this->ds_dec,out_size); - - /* somehow DS_Filters seems to eat more than rec_audio_src_size if the output - buffer is big enough. Doubling rec_audio_src_size should make this + + /* somehow DS_Filters seems to eat more than rec_audio_src_size if the output + buffer is big enough. Doubling rec_audio_src_size should make this impossible */ - this->rec_audio_src_size*=2; + this->rec_audio_src_size*=2; } else if( this->driver_type == DRIVER_DMO ) { this->dmo_dec=DMO_AudioDecoder_Open(win32_codec_name,this->guid, in_fmt, wf.nChannels); - + if( this->dmo_dec == NULL ) { xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: Error initializing DMO Audio\n")); this->srcstream = 0; return 0; } - - out_size = audio_buffer_mem_size; + + out_size = audio_buffer_mem_size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: output buffer size: %d\n",(int)out_size); this->rec_audio_src_size=DMO_AudioDecoder_GetSrcSize(this->dmo_dec,out_size); - + /* i don't know if DMO has the same problem as above. so, just in case... */ - this->rec_audio_src_size*=2; + this->rec_audio_src_size*=2; } - + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "w32codec: Recommended source buffer size: %d\n", this->rec_audio_src_size); + "w32codec: Recommended source buffer size: %d\n", this->rec_audio_src_size); if( this->rec_audio_src_size < in_fmt->nBlockAlign ) { this->rec_audio_src_size = in_fmt->nBlockAlign; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "w32codec: adjusting source buffer size to %d\n", this->rec_audio_src_size); + "w32codec: adjusting source buffer size to %d\n", this->rec_audio_src_size); } - + if( this->buf ) free(this->buf); - + if( this->outbuf ) free(this->outbuf); this->max_audio_src_size = 2 * this->rec_audio_src_size; - + this->buf = malloc( this->max_audio_src_size ); out_size += 32768; this->outbuf = malloc( out_size ); this->outsize = out_size; - + this->size = 0; this->pts = this->lastpts = this->sumpts = this->sumsize = 0; @@ -1303,7 +1307,7 @@ static void w32a_ensure_buffer_size(w32a_decoder_t *this, int size) { if( this->size + size > this->max_audio_src_size ) { this->max_audio_src_size = this->size + 2 * size; xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "w32codec: increasing source buffer to %d to avoid overflow.\n", + "w32codec: increasing source buffer to %d to avoid overflow.\n", this->max_audio_src_size); this->buf = realloc( this->buf, this->max_audio_src_size ); } @@ -1311,9 +1315,9 @@ static void w32a_ensure_buffer_size(w32a_decoder_t *this, int size) { static void w32a_decode_audio (w32a_decoder_t *this, - unsigned char *data, - uint32_t size, - int frame_end, + unsigned char *data, + uint32_t size, + int frame_end, int64_t pts) { static ACMSTREAMHEADER ash; @@ -1346,7 +1350,7 @@ static void w32a_decode_audio (w32a_decoder_t *this, delay = (int)((double)this->size / this->byterate); else delay = 0; - + this->sumsize += size; w32a_ensure_buffer_size(this, this->size + size); @@ -1361,17 +1365,17 @@ static void w32a_decode_audio (w32a_decoder_t *this, memset(&ash, 0, sizeof(ash)); ash.cbStruct=sizeof(ash); ash.fdwStatus=0; - ash.dwUser=0; + ash.dwUser=0; ash.pbSrc=this->buf; ash.cbSrcLength=this->rec_audio_src_size; ash.pbDst=this->outbuf; ash.cbDstLength=this->outsize; - - lprintf ("decoding %d of %d bytes (%02x %02x %02x %02x ... %02x %02x)\n", + + lprintf ("decoding %d of %d bytes (%02x %02x %02x %02x ... %02x %02x)\n", this->rec_audio_src_size, this->size, this->buf[0], this->buf[1], this->buf[2], this->buf[3], - this->buf[this->rec_audio_src_size-2], this->buf[this->rec_audio_src_size-1]); - + this->buf[this->rec_audio_src_size-2], this->buf[this->rec_audio_src_size-1]); + pthread_mutex_lock(&win32_codec_mutex); if( this->driver_type == DRIVER_STD ) { hr=acmStreamPrepareHeader(this->srcstream,&ash,0); @@ -1381,7 +1385,7 @@ static void w32a_decode_audio (w32a_decoder_t *this, pthread_mutex_unlock(&win32_codec_mutex); return; } - + hr=acmStreamConvert(this->srcstream,&ash,0); } else if( this->driver_type == DRIVER_DS ){ hr=DS_AudioDecoder_Convert(this->ds_dec, ash.pbSrc, ash.cbSrcLength, @@ -1397,7 +1401,7 @@ static void w32a_decode_audio (w32a_decoder_t *this, ash.cbDstLengthUsed = size_written; } pthread_mutex_unlock(&win32_codec_mutex); - + if(hr){ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "w32codec: stream convert error %d, used %d bytes\n", (int)hr,(int)ash.cbSrcLengthUsed); @@ -1412,18 +1416,18 @@ static void w32a_decode_audio (w32a_decoder_t *this, DstLengthUsed = ash.cbDstLengthUsed; p = this->outbuf; - + while( DstLengthUsed ) { audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); - + if( DstLengthUsed < audio_buffer->mem_size ) bufsize = DstLengthUsed; else bufsize = audio_buffer->mem_size; xine_fast_memcpy( audio_buffer->mem, p, bufsize ); - + audio_buffer->num_frames = bufsize / (this->num_channels*2); if (this->pts) audio_buffer->vpts = this->pts - delay; @@ -1433,7 +1437,7 @@ static void w32a_decode_audio (w32a_decoder_t *this, lprintf("w32a_decode_audio: decoder pts=%lld\n", audio_buffer->vpts); this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - + this->pts = 0; DstLengthUsed -= bufsize; p += bufsize; @@ -1466,19 +1470,19 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { lprintf ("preview data ignored.\n"); return; } - + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { lprintf ("got audio header\n"); - + /* accumulate init data */ w32a_ensure_buffer_size(this, this->size + buf->size); memcpy(this->buf + this->size, buf->content, buf->size); this->size += buf->size; - + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { pthread_mutex_lock(&win32_codec_mutex); this->decoder_ok = w32a_init_audio (this, this->buf, this->size, buf->type); - + if( !this->decoder_ok ) { xine_log (this->stream->xine, XINE_LOG_MSG, _("w32codec: decoder failed to start. Is '%s' installed?\n"), win32_codec_name ); @@ -1486,7 +1490,7 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } pthread_mutex_unlock(&win32_codec_mutex); } - + } else if (this->decoder_ok) { lprintf ("decoding %d data bytes...\n", buf->size); @@ -1494,9 +1498,9 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { return; Check_FS_Segment(this->ldt_fs); - + w32a_decode_audio (this, buf->content, buf->size, - buf->decoder_flags & BUF_FLAG_FRAME_END, + buf->decoder_flags & BUF_FLAG_FRAME_END, buf->pts); } } @@ -1505,7 +1509,7 @@ static void w32a_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { static void w32a_dispose (audio_decoder_t *this_gen) { w32a_decoder_t *this = (w32a_decoder_t *) this_gen; - + pthread_mutex_lock(&win32_codec_mutex); if( this->driver_type == DRIVER_STD ) { if( this->srcstream ) { @@ -1529,12 +1533,12 @@ static void w32a_dispose (audio_decoder_t *this_gen) { free(this->buf); this->buf = NULL; } - + if( this->outbuf ) { free(this->outbuf); this->outbuf = NULL; } - + this->decoder_ok = 0; if (this->output_open) { @@ -1545,12 +1549,12 @@ static void w32a_dispose (audio_decoder_t *this_gen) { free (this); } -static video_decoder_t *open_video_decoder_plugin (video_decoder_class_t *class_gen, +static video_decoder_t *open_video_decoder_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { w32v_decoder_t *this ; - this = (w32v_decoder_t *) xine_xmalloc (sizeof (w32v_decoder_t)); + this = (w32v_decoder_t *) calloc(1, sizeof(w32v_decoder_t)); this->video_decoder.decode_data = w32v_decode_data; this->video_decoder.flush = w32v_flush; @@ -1593,7 +1597,7 @@ static void *init_video_decoder_class (xine_t *xine, void *data) { cfg = xine->config; if ((win32_def_path = get_win32_codecs_path(cfg)) == NULL) return NULL; - this = (w32v_class_t *) xine_xmalloc (sizeof (w32v_class_t)); + this = (w32v_class_t *) calloc(1, sizeof(w32v_class_t)); this->decoder_class.open_plugin = open_video_decoder_plugin; this->decoder_class.get_identifier = get_video_identifier; @@ -1601,7 +1605,7 @@ static void *init_video_decoder_class (xine_t *xine, void *data) { this->decoder_class.dispose = dispose_video_class; pthread_once (&once_control, init_routine); - + return this; } @@ -1609,22 +1613,22 @@ static void *init_video_decoder_class (xine_t *xine, void *data) { * audio part */ -static audio_decoder_t *open_audio_decoder_plugin (audio_decoder_class_t *class_gen, +static audio_decoder_t *open_audio_decoder_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { w32a_decoder_t *this ; - this = (w32a_decoder_t *) xine_xmalloc (sizeof (w32a_decoder_t)); + this = (w32a_decoder_t *) calloc(1, sizeof(w32a_decoder_t)); this->audio_decoder.decode_data = w32a_decode_data; this->audio_decoder.reset = w32a_reset; this->audio_decoder.discontinuity = w32a_discontinuity; this->audio_decoder.dispose = w32a_dispose; - + this->stream = stream; this->output_open = 0; this->decoder_ok = 0; - + this->buf = NULL; this->outbuf = NULL; @@ -1651,11 +1655,11 @@ static void *init_audio_decoder_class (xine_t *xine, void *data) { w32a_class_t *this; config_values_t *cfg; - + cfg = xine->config; if ((win32_def_path = get_win32_codecs_path(cfg)) == NULL) return NULL; - this = (w32a_class_t *) xine_xmalloc (sizeof (w32a_class_t)); + this = (w32a_class_t *) calloc(1, sizeof(w32a_class_t)); this->decoder_class.open_plugin = open_audio_decoder_plugin; this->decoder_class.get_identifier = get_identifier; @@ -1672,12 +1676,12 @@ static void *init_audio_decoder_class (xine_t *xine, void *data) { * exported plugin catalog entry */ -static uint32_t video_types[] = { +static uint32_t video_types[] = { BUF_VIDEO_MSMPEG4_V1, BUF_VIDEO_MSMPEG4_V2, BUF_VIDEO_MSMPEG4_V3, BUF_VIDEO_IV50, BUF_VIDEO_IV41, BUF_VIDEO_IV32, BUF_VIDEO_IV31, BUF_VIDEO_CINEPAK, /* BUF_VIDEO_ATIVCR1, */ BUF_VIDEO_ATIVCR2, BUF_VIDEO_I263, BUF_VIDEO_MSVC, - BUF_VIDEO_DV, BUF_VIDEO_WMV7, BUF_VIDEO_WMV8, BUF_VIDEO_WMV9, + BUF_VIDEO_DV, BUF_VIDEO_WMV7, BUF_VIDEO_WMV8, BUF_VIDEO_WMV9, BUF_VIDEO_VP31, BUF_VIDEO_MSS1, BUF_VIDEO_TSCC, BUF_VIDEO_UCOD, BUF_VIDEO_VP4, BUF_VIDEO_VP5, BUF_VIDEO_VP6, 0 @@ -1688,8 +1692,8 @@ static const decoder_info_t dec_info_video = { 1 /* priority */ }; -static uint32_t audio_types[] = { - BUF_AUDIO_WMAV1, BUF_AUDIO_WMAV2, BUF_AUDIO_WMAV3, BUF_AUDIO_MSADPCM, +static uint32_t audio_types[] = { + BUF_AUDIO_WMAV1, BUF_AUDIO_WMAV2, BUF_AUDIO_WMAV3, BUF_AUDIO_MSADPCM, BUF_AUDIO_MSIMAADPCM, BUF_AUDIO_MSGSM, BUF_AUDIO_IMC, BUF_AUDIO_LH, BUF_AUDIO_VOXWARE, BUF_AUDIO_ACELPNET, BUF_AUDIO_VIVOG723, BUF_AUDIO_WMAV, BUF_AUDIO_WMALL, @@ -1702,7 +1706,7 @@ static const decoder_info_t dec_info_audio = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER | PLUGIN_MUST_PRELOAD, 18, "win32v", XINE_VERSION_CODE, &dec_info_video, init_video_decoder_class }, { PLUGIN_AUDIO_DECODER | PLUGIN_MUST_PRELOAD, 15, "win32a", XINE_VERSION_CODE, &dec_info_audio, init_audio_decoder_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/libw32dll/w32codec.h b/src/libw32dll/w32codec.h index 1f02ba764..78dcb5c88 100644 --- a/src/libw32dll/w32codec.h +++ b/src/libw32dll/w32codec.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2001 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/libw32dll/wine/Makefile.am b/src/libw32dll/wine/Makefile.am index 63da4068e..f04560130 100644 --- a/src/libw32dll/wine/Makefile.am +++ b/src/libw32dll/wine/Makefile.am @@ -9,7 +9,8 @@ noinst_LTLIBRARIES = $(wine_lib) AM_CFLAGS = $(X_CFLAGS) @W32_NO_OPTIMIZE@ \ -Wmissing-prototypes -Wimplicit-function-declaration \ -DWIN32_PATH=\"@w32_path@\" -I$(srcdir)/.. -D__WINE__ \ - -Ddbg_printf=__vprintf -DTRACE=__vprintf + -Ddbg_printf=__vprintf -DTRACE=__vprintf \ + -I$(top_srcdir)/src/xine-utils # CFLAGS is here to filter out -fomit-frame-pointer, # -finline-functions and -frename-registers because they cause bad @@ -34,7 +35,7 @@ libwine_la_SOURCES = \ vfl.c \ win32.c \ stubs.s \ - wrapper.S + wrapper.S noinst_HEADERS = \ avifmt.h \ diff --git a/src/libw32dll/wine/driver.c b/src/libw32dll/wine/driver.c index ef8761628..296fcd25a 100644 --- a/src/libw32dll/wine/driver.c +++ b/src/libw32dll/wine/driver.c @@ -1,4 +1,4 @@ -#include <config.h> +#include "config.h" #include <stdio.h> #ifdef HAVE_MALLOC_H #include <malloc.h> diff --git a/src/libw32dll/wine/elfdll.c b/src/libw32dll/wine/elfdll.c index 7853ffe71..e81467b5a 100644 --- a/src/libw32dll/wine/elfdll.c +++ b/src/libw32dll/wine/elfdll.c @@ -3,7 +3,7 @@ * * Copyright 1999 Bertho A. Stultiens */ -#include <config.h> +#include "config.h" #ifdef HAVE_LIBDL diff --git a/src/libw32dll/wine/pe_image.c b/src/libw32dll/wine/pe_image.c index c99bbaed0..1366cc396 100644 --- a/src/libw32dll/wine/pe_image.c +++ b/src/libw32dll/wine/pe_image.c @@ -900,7 +900,7 @@ void PE_UnloadLibrary(WINE_MODREF *wm) */ static void extend_stack_for_dll_alloca(void) { -#ifndef __FreeBSD__ +#if !defined(__FreeBSD__) && !defined(__OpenBSD__) void* mem=alloca(0x20000); *(int*)mem=0x1234; #endif diff --git a/src/libw32dll/wine/pe_resource.c b/src/libw32dll/wine/pe_resource.c index 6acfef2f0..16dc85389 100644 --- a/src/libw32dll/wine/pe_resource.c +++ b/src/libw32dll/wine/pe_resource.c @@ -9,7 +9,7 @@ * Copyright 1995 Alexandre Julliard * Copyright 1997 Marcus Meissner */ -#include <config.h> +#include "config.h" #include <stdlib.h> #include <sys/types.h> diff --git a/src/libw32dll/wine/registry.c b/src/libw32dll/wine/registry.c index 0f91499b3..0ccf3de9b 100644 --- a/src/libw32dll/wine/registry.c +++ b/src/libw32dll/wine/registry.c @@ -311,8 +311,7 @@ static void init_registry(void) localregpathname = regpathname; #else #ifdef XINE_MAJOR - localregpathname = (char *)malloc(strlen(xine_get_homedir()) + 21); - sprintf(localregpathname, "%s/.xine/win32registry", xine_get_homedir()); + asprintf(&localregpathname, "%s/.xine/win32registry", xine_get_homedir()); #else // regpathname is an external pointer // diff --git a/src/libw32dll/wine/resource.c b/src/libw32dll/wine/resource.c index 9d4fa80bb..a38c1dd1e 100644 --- a/src/libw32dll/wine/resource.c +++ b/src/libw32dll/wine/resource.c @@ -4,7 +4,7 @@ * Copyright 1993 Robert J. Amstadt * Copyright 1995 Alexandre Julliard */ -#include <config.h> +#include "config.h" #include <assert.h> #include <stdio.h> diff --git a/src/libw32dll/wine/vfl.c b/src/libw32dll/wine/vfl.c index e8eb7969f..f509995de 100644 --- a/src/libw32dll/wine/vfl.c +++ b/src/libw32dll/wine/vfl.c @@ -1,7 +1,7 @@ /* * Copyright 1998 Marcus Meissner */ -#include <config.h> +#include "config.h" #include <stdio.h> #include <stdlib.h> diff --git a/src/libw32dll/wine/win32.c b/src/libw32dll/wine/win32.c index 3b0941391..d9744ae35 100644 --- a/src/libw32dll/wine/win32.c +++ b/src/libw32dll/wine/win32.c @@ -1430,7 +1430,7 @@ static void WINAPI expDeleteCriticalSection(CRITICAL_SECTION *c) } static int WINAPI expGetCurrentThreadId() { - dbgprintf("GetCurrentThreadId() => %ld\n", pthread_self()); + dbgprintf("GetCurrentThreadId() => %ld\n", (long int)pthread_self()); return (int)pthread_self(); } static int WINAPI expGetCurrentProcess() @@ -2134,7 +2134,6 @@ static const char* WINAPI expGetCommandLineA() dbgprintf("GetCommandLineA() => \"c:\\aviplay.exe\"\n"); return "c:\\aviplay.exe"; } -static short envs[]={'p', 'a', 't', 'h', ' ', 'c', ':', '\\', 0, 0}; static LPWSTR WINAPI expGetEnvironmentStringsW() { dbgprintf("GetEnvironmentStringsW() => 0\n"); @@ -3491,9 +3490,9 @@ static HANDLE WINAPI expCreateFileA(LPCSTR cs1,DWORD i1,DWORD i2, if(strstr(cs1, ".qtx")) { int result; - char* tmp=(char*)malloc(strlen(win32_def_path)+250); char* x=strrchr(cs1,'\\'); - sprintf(tmp,"%s/%s",win32_def_path,x?(x+1):cs1); + char* tmp; + asprintf(&tmp,"%s/%s",win32_def_path,x?(x+1):cs1); // printf("### Open: %s -> %s\n",cs1,tmp); result=open(tmp, O_RDONLY); free(tmp); @@ -3998,7 +3997,7 @@ static int XINE_FORMAT_PRINTF(2, 3) expsprintf(char* str, const char* format, .. va_end(args); return r; } -static int XINE_FORMAT_PRINTF(2, 3) expsscanf(const char* str, const char* format, ...) +static int XINE_FORMAT_SCANF(2, 3) expsscanf(const char* str, const char* format, ...) { va_list args; int r; @@ -4162,7 +4161,7 @@ static void* expmemset(void* dest, int c, size_t n) static time_t exptime(time_t* t) { time_t result = time(t); - dbgprintf("time(%p) => %ld\n", t, result); + dbgprintf("time(%p) => %ld\n", t, (long int)result); return result; } @@ -5058,11 +5057,9 @@ struct libs libraries[]={ LL(ddraw) #endif }; -#if defined(__CYGWIN__) || defined(__OS2__) || defined (__OpenBSD__) -#define MANGLE(a) "_" #a -#else -#define MANGLE(a) #a -#endif + +#include "mangle.h" + static void ext_stubs(void) { // expects: diff --git a/src/libxineadec/Makefile.am b/src/libxineadec/Makefile.am index d502b7955..ae261e60c 100644 --- a/src/libxineadec/Makefile.am +++ b/src/libxineadec/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = fooaudio.c @@ -39,7 +40,7 @@ xineplug_decode_lpcm_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_decode_lpcm_la_LIBADD = $(XINE_LIB) xineplug_decode_vorbis_la_SOURCES = xine_vorbis_decoder.c -xineplug_decode_vorbis_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(OGG_LIBS) +xineplug_decode_vorbis_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(OGG_LIBS) $(LTLIBINTL) xineplug_decode_vorbis_la_CFLAGS = $(VISIBILITY_FLAG) $(VORBIS_CFLAGS) xineplug_decode_speex_la_SOURCES = xine_speex_decoder.c diff --git a/src/libxineadec/fooaudio.c b/src/libxineadec/fooaudio.c index 5ab4fa1f6..776136fc2 100644 --- a/src/libxineadec/fooaudio.c +++ b/src/libxineadec/fooaudio.c @@ -22,6 +22,10 @@ * place of the data it should actually send. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -91,7 +95,7 @@ static void fooaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->channels = buf->decoder_info[3]; /* initialize the data accumulation buffer */ - this->buf = xine_xmalloc(AUDIOBUFSIZE); + this->buf = calloc(1, AUDIOBUFSIZE); this->bufsize = AUDIOBUFSIZE; this->size = 0; @@ -126,7 +130,7 @@ static void fooaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) * the accumulator buffer size as necessary */ if( this->size + buf->size > this->bufsize ) { this->bufsize = this->size + 2 * buf->size; - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "fooaudio: increasing source buffer to %d to avoid overflow.\n", this->bufsize); this->buf = realloc( this->buf, this->bufsize ); } @@ -147,8 +151,8 @@ static void fooaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) * This decoder generates a continuous sine pattern based on the pts * values sent by the xine engine. Two pts values are needed to know * how long to make the audio. Thus, If this is the first frame or - * a seek has occurred (indicated by this->last_pts = -1), - * log the pts but do not create any audio. + * a seek has occurred (indicated by this->last_pts = -1), + * log the pts but do not create any audio. * * When a valid pts delta is generated, create n audio samples, where * n is given as: @@ -177,7 +181,7 @@ static void fooaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* get an audio buffer */ audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); if (audio_buffer->mem_size == 0) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "fooaudio: Help! Allocated audio buffer with nothing in it!\n"); return; } @@ -192,7 +196,7 @@ static void fooaudio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) #define WAVE_HZ 300 /* fill up the samples in the buffer */ for (i = 0; i < samples_to_send; i++) - audio_buffer->mem[i] = + audio_buffer->mem[i] = (short)(sin(2 * M_PI * this->iteration++ / WAVE_HZ) * 32767); /* final prep for audio buffer dispatch */ @@ -255,7 +259,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre fooaudio_decoder_t *this ; - this = (fooaudio_decoder_t *) xine_xmalloc (sizeof (fooaudio_decoder_t)); + this = (fooaudio_decoder_t *) calloc(1, sizeof(fooaudio_decoder_t)); /* connect the member functions */ this->audio_decoder.decode_data = fooaudio_decode_data; @@ -304,7 +308,7 @@ static void dispose_class (audio_decoder_class_t *this_gen) { free (this); } -/* This function allocates a private audio decoder class and initializes +/* This function allocates a private audio decoder class and initializes * the class's member functions. */ static void *init_plugin (xine_t *xine, void *data) { @@ -320,18 +324,18 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -/* This is a list of all of the internal xine audio buffer types that +/* This is a list of all of the internal xine audio buffer types that * this decoder is able to handle. Check src/xine-engine/buffer.h for a * list of valid buffer types (and add a new one if the one you need does * not exist). Terminate the list with a 0. */ -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { /* BUF_AUDIO_FOO, */ 0 }; /* This data structure combines the list of supported xine buffer types and * the priority that the plugin should be given with respect to other - * plugins that handle the same buffer type. A plugin with priority (n+1) + * plugins that handle the same buffer type. A plugin with priority (n+1) * will be used instead of a plugin with priority (n). */ static const decoder_info_t dec_info_audio = { audio_types, /* supported types */ diff --git a/src/libxineadec/gsm610.c b/src/libxineadec/gsm610.c index 23c0d2104..c67382bc5 100644 --- a/src/libxineadec/gsm610.c +++ b/src/libxineadec/gsm610.c @@ -101,7 +101,7 @@ static void gsm610_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (buf->decoder_flags & BUF_FLAG_STDHEADER) { this->sample_rate = buf->decoder_info[1]; - this->buf = xine_xmalloc(AUDIOBUFSIZE); + this->buf = calloc(1, AUDIOBUFSIZE); this->bufsize = AUDIOBUFSIZE; this->size = 0; @@ -233,7 +233,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre gsm610_decoder_t *this ; - this = (gsm610_decoder_t *) xine_xmalloc (sizeof (gsm610_decoder_t)); + this = (gsm610_decoder_t *) calloc(1, sizeof(gsm610_decoder_t)); this->audio_decoder.decode_data = gsm610_decode_data; this->audio_decoder.reset = gsm610_reset; @@ -265,7 +265,7 @@ static void *init_plugin (xine_t *xine, void *data) { gsm610_class_t *this ; - this = (gsm610_class_t *) xine_xmalloc (sizeof (gsm610_class_t)); + this = (gsm610_class_t *) calloc(1, sizeof(gsm610_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; diff --git a/src/libxineadec/gsm610/long_term.c b/src/libxineadec/gsm610/long_term.c index 625662e1f..d3ef1b63d 100644 --- a/src/libxineadec/gsm610/long_term.c +++ b/src/libxineadec/gsm610/long_term.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/long_term.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" diff --git a/src/libxineadec/gsm610/lpc.c b/src/libxineadec/gsm610/lpc.c index 0f51fa55f..7a8a8e2bc 100644 --- a/src/libxineadec/gsm610/lpc.c +++ b/src/libxineadec/gsm610/lpc.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/lpc.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" diff --git a/src/libxineadec/gsm610/rpe.c b/src/libxineadec/gsm610/rpe.c index 67d94d30e..be1b1529b 100644 --- a/src/libxineadec/gsm610/rpe.c +++ b/src/libxineadec/gsm610/rpe.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/rpe.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" #include "private.h" diff --git a/src/libxineadec/gsm610/short_term.c b/src/libxineadec/gsm610/short_term.c index 8222b2caa..c2d64853b 100644 --- a/src/libxineadec/gsm610/short_term.c +++ b/src/libxineadec/gsm610/short_term.c @@ -6,6 +6,10 @@ /* $Header: /nfshome/cvs/xine-lib/src/libxineadec/gsm610/short_term.c,v 1.3 2003/12/07 15:34:30 f1rmb Exp $ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xineutils.h" #include "private.h" diff --git a/src/libxineadec/nosefart/Makefile.am b/src/libxineadec/nosefart/Makefile.am index 51cc3f238..4ca4f75b6 100644 --- a/src/libxineadec/nosefart/Makefile.am +++ b/src/libxineadec/nosefart/Makefile.am @@ -13,7 +13,7 @@ libnosefart_la_SOURCES = \ memguard.c \ nes6502.c \ nsf.c \ - vrcvisnd.c + vrcvisnd.c libnosefart_la_CFLAGS = $(VISIBILITY_FLAG) -DNSF_PLAYER -fno-strict-aliasing diff --git a/src/libxineadec/nsf.c b/src/libxineadec/nsf.c index bdf523f1d..643d431a2 100644 --- a/src/libxineadec/nsf.c +++ b/src/libxineadec/nsf.c @@ -21,6 +21,10 @@ * http://www.baisoku.org/ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -90,7 +94,7 @@ static void nsf_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->song_number = buf->content[4]; /* allocate a buffer for the file */ this->nsf_size = _X_BE_32(&buf->content[0]); - this->nsf_file = xine_xmalloc(this->nsf_size); + this->nsf_file = calloc(1, this->nsf_size); this->nsf_index = 0; /* peform any other required initialization */ @@ -205,7 +209,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre nsf_decoder_t *this ; - this = (nsf_decoder_t *) xine_xmalloc (sizeof (nsf_decoder_t)); + this = (nsf_decoder_t *) calloc(1, sizeof(nsf_decoder_t)); /* connect the member functions */ this->audio_decoder.decode_data = nsf_decode_data; @@ -249,13 +253,13 @@ static void dispose_class (audio_decoder_class_t *this_gen) { free (this); } -/* This function allocates a private audio decoder class and initializes +/* This function allocates a private audio decoder class and initializes * the class's member functions. */ static void *init_plugin (xine_t *xine, void *data) { nsf_class_t *this ; - this = (nsf_class_t *) xine_xmalloc (sizeof (nsf_class_t)); + this = (nsf_class_t *) calloc(1, sizeof(nsf_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -265,18 +269,18 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -/* This is a list of all of the internal xine audio buffer types that +/* This is a list of all of the internal xine audio buffer types that * this decoder is able to handle. Check src/xine-engine/buffer.h for a * list of valid buffer types (and add a new one if the one you need does * not exist). Terminate the list with a 0. */ -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_NSF, 0 }; /* This data structure combines the list of supported xine buffer types and * the priority that the plugin should be given with respect to other - * plugins that handle the same buffer type. A plugin with priority (n+1) + * plugins that handle the same buffer type. A plugin with priority (n+1) * will be used instead of a plugin with priority (n). */ static const decoder_info_t dec_info_audio = { audio_types, /* supported types */ diff --git a/src/libxineadec/xine_lpcm_decoder.c b/src/libxineadec/xine_lpcm_decoder.c index 8d8f23a05..630d5a120 100644 --- a/src/libxineadec/xine_lpcm_decoder.c +++ b/src/libxineadec/xine_lpcm_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,11 @@ * 31-8-2001 Added LPCM rate sensing. * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifndef __sun #define _XOPEN_SOURCE 500 #endif @@ -53,31 +58,43 @@ typedef struct lpcm_decoder_s { xine_stream_t *stream; uint32_t rate; - uint32_t bits_per_sample; - uint32_t number_of_channels; - uint32_t ao_cap_mode; - + uint32_t bits_per_sample; + uint32_t number_of_channels; + uint32_t ao_cap_mode; + int output_open; int cpu_be; /* TRUE, if we're a Big endian CPU */ + + int64_t pts; + + uint8_t *buf; + size_t buffered_bytes; + size_t buf_size; + } lpcm_decoder_t; static void lpcm_reset (audio_decoder_t *this_gen) { - /* lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen; */ + lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen; + free (this->buf); + this->buf = NULL; } static void lpcm_discontinuity (audio_decoder_t *this_gen) { + + lpcm_reset(this_gen); } static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen; int16_t *sample_buffer=(int16_t *)buf->content; + int buf_size = buf->size; int stream_be; audio_buffer_t *audio_buffer; int format_changed = 0; - + /* Drop preview data */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; @@ -88,20 +105,57 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { unsigned int bits_per_sample = 16; unsigned int sample_rate = 0; unsigned int num_channels; - - num_channels = (buf->decoder_info[2] & 0x7) + 1; - switch ((buf->decoder_info[2]>>4) & 3) { - case 0: sample_rate = 48000; break; - case 1: sample_rate = 96000; break; - case 2: sample_rate = 44100; break; - case 3: sample_rate = 32000; break; - } - switch ((buf->decoder_info[2]>>6) & 3) { - case 0: bits_per_sample = 16; break; - case 1: bits_per_sample = 20; break; - case 2: bits_per_sample = 24; break; + + lprintf("lpcm_decoder: config data 0x%x\n", buf->decoder_info[2]); + + /* BluRay PCM header is 4 bytes */ + if (buf->decoder_info[2] & 0xffffff00) { + static const uint8_t channels[16] = {0, 1, 0, 2, 3, 3, 4, 4, 5, 6, 7, 8, 0, 0, 0, 0}; + + num_channels = channels[(buf->decoder_info[2] >> (16+4)) & 0x0f]; + switch ((buf->decoder_info[2] >> (24+6)) & 0x03) { + case 1: bits_per_sample = 16; break; + case 2: bits_per_sample = 20; break; + case 3: bits_per_sample = 24; break; + default: bits_per_sample = 0; break; + } + switch ((buf->decoder_info[2] >> 16) & 0x0f) { + case 1: sample_rate = 48000; break; + case 4: sample_rate = 96000; break; + case 5: sample_rate = 192000; break; + default: sample_rate = 0; break; + } + + if (!num_channels || !sample_rate || !bits_per_sample) + xine_log (this->stream->xine, XINE_LOG_MSG, + "lpcm_decoder: unsupported BluRay PCM format: 0x%08x\n", buf->decoder_info[2]); + + if (this->buffered_bytes) + xine_log (this->stream->xine, XINE_LOG_MSG, "lpcm_decoder: %zd bytes lost !\n", this->buffered_bytes); + + if (!this->buf) { + this->buffered_bytes = 0; + this->buf_size = 8128; + this->buf = malloc(this->buf_size); + } + + } else { + + /* MPEG2/DVD PCM header is one byte */ + num_channels = (buf->decoder_info[2] & 0x7) + 1; + switch ((buf->decoder_info[2]>>4) & 3) { + case 0: sample_rate = 48000; break; + case 1: sample_rate = 96000; break; + case 2: sample_rate = 44100; break; + case 3: sample_rate = 32000; break; + } + switch ((buf->decoder_info[2]>>6) & 3) { + case 0: bits_per_sample = 16; break; + case 1: bits_per_sample = 20; break; + case 2: bits_per_sample = 24; break; + } } - + if( this->bits_per_sample != bits_per_sample || this->number_of_channels != num_channels || this->rate != sample_rate || @@ -110,16 +164,20 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->number_of_channels = num_channels; this->rate = sample_rate; format_changed++; - } + + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "lpcm_decoder: format changed to %d channels, %d bits per sample, %d Hz, %d kbit/s\n", + num_channels, bits_per_sample, sample_rate, (num_channels * sample_rate * bits_per_sample)/1024); + } } - + if( buf->decoder_flags & BUF_FLAG_STDHEADER ) { this->rate=buf->decoder_info[1]; - this->bits_per_sample=buf->decoder_info[2] ; - this->number_of_channels=buf->decoder_info[3] ; + this->bits_per_sample=buf->decoder_info[2]; + this->number_of_channels=buf->decoder_info[3]; format_changed++; } - + /* * (re-)open output device */ @@ -143,80 +201,123 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { /* stream/meta info */ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Linear PCM"); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->bits_per_sample * this->rate * this->number_of_channels); } - if (!this->output_open || (buf->decoder_flags & BUF_FLAG_HEADER) ) + if (!this->output_open || (buf->decoder_flags & BUF_FLAG_HEADER) ) return; + if (buf->pts && !this->pts) + this->pts = buf->pts; + + /* data accumulation */ + if (this->buf) { + int frame_end = buf->decoder_flags & BUF_FLAG_FRAME_END; + if (this->buffered_bytes || !frame_end) { + if (this->buf_size < this->buffered_bytes + buf->size) { + this->buf_size *= 2; + this->buf = realloc(this->buf, this->buf_size); + } + + memcpy(this->buf + this->buffered_bytes, buf->content, buf->size); + this->buffered_bytes += buf->size; + + if (!frame_end) + return; + + sample_buffer = (int16_t*)this->buf; + buf_size = this->buffered_bytes; + this->buffered_bytes = 0; + } + } + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); /* Swap LPCM samples into native byte order, if necessary */ buf->type &= 0xffff0000; stream_be = ( buf->type == BUF_AUDIO_LPCM_BE ); - + if( this->bits_per_sample == 16 ){ if (stream_be != this->cpu_be) - swab (sample_buffer, audio_buffer->mem, buf->size); + swab (sample_buffer, audio_buffer->mem, buf_size); else - memcpy (audio_buffer->mem, sample_buffer, buf->size); + memcpy (audio_buffer->mem, sample_buffer, buf_size); } else if( this->bits_per_sample == 20 ) { uint8_t *s = (uint8_t *)sample_buffer; uint8_t *d = (uint8_t *)audio_buffer->mem; - int n = buf->size; - + int n = buf_size; + if (stream_be != this->cpu_be) { while( n >= 0 ) { swab( s, d, 8 ); s += 10; d += 8; - n -= 10; + n -= 10; } } else { while( n >= 0 ) { memcpy( d, s, 8 ); s += 10; d += 8; - n -= 10; + n -= 10; } } } else if( this->bits_per_sample == 24 ) { uint8_t *s = (uint8_t *)sample_buffer; uint8_t *d = (uint8_t *)audio_buffer->mem; - int n = buf->size; + int n = buf_size; - while (n >= 0) { + while (n >= 3) { if ( stream_be ) { - *d++ = s[0]; - *d++ = s[1]; + if ( stream_be == this->cpu_be ) { + *d++ = s[0]; + *d++ = s[1]; + } else { + *d++ = s[1]; + *d++ = s[0]; + } } else { - *d++ = s[1]; - *d++ = s[2]; + if ( stream_be == this->cpu_be ) { + *d++ = s[1]; + *d++ = s[2]; + } + else + { + *d++ = s[2]; + *d++ = s[1]; + } } s += 3; n -= 3; } + + if ( (d - (uint8_t*)audio_buffer->mem)/2*3 < buf_size ) + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "lpcm_decoder: lost %i bytes\n", (int)(buf_size - (d - (uint8_t*)audio_buffer->mem))/2*3); + } else { - memcpy (audio_buffer->mem, sample_buffer, buf->size); + memcpy (audio_buffer->mem, sample_buffer, buf_size); } - - audio_buffer->vpts = buf->pts; - audio_buffer->num_frames = (((buf->size*8)/this->number_of_channels)/this->bits_per_sample); + + audio_buffer->vpts = this->pts; + audio_buffer->num_frames = (((buf_size*8)/this->number_of_channels)/this->bits_per_sample); this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); + this->pts = 0; } static void lpcm_dispose (audio_decoder_t *this_gen) { - lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen; + lpcm_decoder_t *this = (lpcm_decoder_t *) this_gen; - if (this->output_open) + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); this->output_open = 0; + free (this->buf); + free (this_gen); } @@ -224,7 +325,7 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre lpcm_decoder_t *this ; - this = (lpcm_decoder_t *) xine_xmalloc (sizeof (lpcm_decoder_t)); + this = (lpcm_decoder_t *) calloc(1, sizeof(lpcm_decoder_t)); this->audio_decoder.decode_data = lpcm_decode_data; this->audio_decoder.reset = lpcm_reset; @@ -233,11 +334,11 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stre this->output_open = 0; this->rate = 0; - this->bits_per_sample=0; - this->number_of_channels=0; - this->ao_cap_mode=0; + this->bits_per_sample=0; + this->number_of_channels=0; + this->ao_cap_mode=0; this->stream = stream; - + this->cpu_be = ( htons(1) == 1 ); return &this->audio_decoder; @@ -259,7 +360,7 @@ static void *init_plugin (xine_t *xine, void *data) { lpcm_class_t *this ; - this = (lpcm_class_t *) xine_xmalloc (sizeof (lpcm_class_t)); + this = (lpcm_class_t *) calloc(1, sizeof(lpcm_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -269,7 +370,7 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_LPCM_BE, BUF_AUDIO_LPCM_LE, 0 }; @@ -279,7 +380,7 @@ static const decoder_info_t dec_info_audio = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 15, "pcm", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxineadec/xine_speex_decoder.c b/src/libxineadec/xine_speex_decoder.c index aa8234385..9ae2e9718 100644 --- a/src/libxineadec/xine_speex_decoder.c +++ b/src/libxineadec/xine_speex_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -170,16 +170,16 @@ void read_metadata (speex_decoder_t *this, char * comments, int length) #endif for (i = 0; speex_comment_keys[i].key != NULL; i++) { + size_t keylen = strlen(speex_comment_keys[i].key); if ( !strncasecmp (speex_comment_keys[i].key, c, - strlen(speex_comment_keys[i].key)) ) { - int keylen = strlen(speex_comment_keys[i].key); + keylen) ) { char meta_info[(len - keylen) + 1]; - + lprintf ("known metadata %d %d\n", i, speex_comment_keys[i].xine_metainfo_index); - - snprintf(meta_info, (len - keylen), "%s", c + keylen); + + strncpy(meta_info, &c[keylen], len-keylen); _x_meta_info_set_utf8(this->stream, speex_comment_keys[i].xine_metainfo_index, meta_info); } } @@ -204,7 +204,7 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (!this->st) { SpeexMode * spx_mode; SpeexHeader * spx_header; - int modeID; + unsigned int modeID; int bitrate; speex_bits_init (&this->bits); @@ -216,7 +216,12 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { return; } - modeID = spx_header->mode; + modeID = (unsigned int)spx_header->mode; + if (modeID >= SPEEX_NB_MODES) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": invalid mode ID %u\n", modeID); + return; + } + spx_mode = (SpeexMode *) speex_mode_list[modeID]; if (spx_mode->bitstream_version != spx_header->mode_bitstream_version) { @@ -238,7 +243,7 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->channels = spx_header->nb_channels; if (this->channels == 2) { SpeexCallback callback; - + callback.callback_id = SPEEX_INBAND_STEREO; callback.func = speex_std_stereo_request_handler; callback.data = &this->stereo; @@ -247,7 +252,7 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { this->nframes = spx_header->frames_per_packet; if (!this->nframes) this->nframes = 1; - + speex_decoder_ctl (this->st, SPEEX_GET_FRAME_SIZE, &this->frame_size); speex_decoder_ctl (this->st, SPEEX_GET_BITRATE, &bitrate); @@ -266,10 +271,10 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { if (!this->header_count) { int mode = _x_ao_channels2mode(this->channels); - + if (!this->output_open) { this->output_open = - (this->stream->audio_out->open) (this->stream->audio_out, + (this->stream->audio_out->open) (this->stream->audio_out, this->stream, 16, this->rate, @@ -278,9 +283,9 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { } } } - + } else if (this->output_open) { - int i, j; + int j; audio_buffer_t *audio_buffer; @@ -317,9 +322,9 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { audio_buffer->vpts = this->pts; this->pts=0; audio_buffer->num_frames = this->frame_size; - + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - + buf->pts=0; } @@ -331,26 +336,26 @@ static void speex_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { static void speex_dispose (audio_decoder_t *this_gen) { - speex_decoder_t *this = (speex_decoder_t *) this_gen; - + speex_decoder_t *this = (speex_decoder_t *) this_gen; + if (this->st) { speex_decoder_destroy (this->st); } speex_bits_destroy (&this->bits); - if (this->output_open) + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); free (this_gen); } -static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { speex_decoder_t *this ; static SpeexStereoState init_stereo = SPEEX_STEREO_STATE_INIT; - this = (speex_decoder_t *) xine_xmalloc (sizeof (speex_decoder_t)); + this = (speex_decoder_t *) calloc(1, sizeof(speex_decoder_t)); this->audio_decoder.decode_data = speex_decode_data; this->audio_decoder.reset = speex_reset; @@ -390,8 +395,8 @@ static void dispose_class (audio_decoder_class_t *this) { static void *init_plugin (xine_t *xine, void *data) { speex_class_t *this; - - this = (speex_class_t *) xine_xmalloc (sizeof (speex_class_t)); + + this = (speex_class_t *) calloc(1, sizeof(speex_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -401,7 +406,7 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_SPEEX, 0 }; @@ -411,7 +416,7 @@ static const decoder_info_t dec_info_audio = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 15, "speex", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxineadec/xine_vorbis_decoder.c b/src/libxineadec/xine_vorbis_decoder.c index 4b7a6c15d..99012c40d 100644 --- a/src/libxineadec/xine_vorbis_decoder.c +++ b/src/libxineadec/xine_vorbis_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -41,6 +41,7 @@ #include <vorbis/codec.h> #define MAX_NUM_SAMPLES 4096 +#define INIT_BUFSIZE 8192 typedef struct { audio_decoder_class_t decoder_class; @@ -70,6 +71,11 @@ typedef struct vorbis_decoder_s { xine_stream_t *stream; + /* data accumulation stuff */ + unsigned char *buf; + int bufsize; + int size; + } vorbis_decoder_t; @@ -78,10 +84,11 @@ static void vorbis_reset (audio_decoder_t *this_gen) { vorbis_decoder_t *this = (vorbis_decoder_t *) this_gen; if( this->header_count ) return; + this->size = 0; /* clear block first, as it might contain allocated data */ vorbis_block_clear(&this->vb); - vorbis_block_init(&this->vd,&this->vb); + vorbis_block_init(&this->vd,&this->vb); } static void vorbis_discontinuity (audio_decoder_t *this_gen) { @@ -136,132 +143,153 @@ static void get_metadata (vorbis_decoder_t *this) { _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "vorbis"); } +static void vorbis_check_bufsize (vorbis_decoder_t *this, int size) { + if (size > this->bufsize) { + this->bufsize = size + size / 2; + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + _("vorbis: increasing buffer to %d to avoid overflow.\n"), + this->bufsize); + this->buf = realloc(this->buf, this->bufsize); + } +} + static void vorbis_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { vorbis_decoder_t *this = (vorbis_decoder_t *) this_gen; memset( &this->op, 0, sizeof(this->op) ); - this->op.packet = buf->content; - this->op.bytes = buf->size; - if ( (buf->decoder_flags & BUF_FLAG_HEADER) && - !(buf->decoder_flags & BUF_FLAG_STDHEADER) ) { - lprintf ("%d headers to go\n", this->header_count); + /* data accumulation */ + vorbis_check_bufsize(this, this->size + buf->size); + xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); + this->size += buf->size; - if (this->header_count) { - int res = 0; + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + this->op.packet = this->buf; + this->op.bytes = this->size; - if (this->header_count == 3) - this->op.b_o_s = 1; + /* reset accumultaion buffer */ + this->size = 0; - - if( (res = vorbis_synthesis_headerin(&this->vi,&this->vc,&this->op)) < 0 ){ - /* error case; not a vorbis header */ - xine_log(this->stream->xine, XINE_LOG_MSG, "libvorbis: this bitstream does not contain vorbis audio data. Following first 64 bytes (return: %d).\n", res); - xine_hexdump((char *)this->op.packet, this->op.bytes < 64 ? this->op.bytes : 64); - return; - } + if ( (buf->decoder_flags & BUF_FLAG_HEADER) && + !(buf->decoder_flags & BUF_FLAG_STDHEADER) ) { - this->header_count--; - - if (!this->header_count) { - - int mode = AO_CAP_MODE_MONO; - - get_metadata (this); - - mode = _x_ao_channels2mode(this->vi.channels); - - this->convsize=MAX_NUM_SAMPLES/this->vi.channels; - - if (!this->output_open) { - this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, - this->stream, - 16, - this->vi.rate, - mode) ; - - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, - this->vi.bitrate_nominal); - - } - - /* OK, got and parsed all three headers. Initialize the Vorbis - * packet->PCM decoder. */ - lprintf("all three headers parsed. initializing decoder.\n"); - /* initialize central decode state */ - vorbis_synthesis_init(&this->vd,&this->vi); - /* initialize local state for most of the decode so multiple - * block decodes can proceed in parallel. We could init - * multiple vorbis_block structures for vd here */ - vorbis_block_init(&this->vd,&this->vb); - } - } - - } else if (this->output_open) { - - float **pcm; - int samples; - - if(vorbis_synthesis(&this->vb,&this->op)==0) - vorbis_synthesis_blockin(&this->vd,&this->vb); - - if (buf->pts!=0) - this->pts=buf->pts; - - while ((samples=vorbis_synthesis_pcmout(&this->vd,&pcm))>0){ - - /* **pcm is a multichannel float vector. In stereo, for - * example, pcm[0][...] is left, and pcm[1][...] is right. - * samples is the size of each channel. Convert the float - * values (-1.<=range<=1.) to whatever PCM format and write - * it out - */ - - int i,j; - int bout=(samples<this->convsize?samples:this->convsize); - audio_buffer_t *audio_buffer; - - audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); - - /* convert floats to 16 bit signed ints (host order) and - interleave */ - for(i=0;i<this->vi.channels;i++){ - ogg_int16_t *ptr=audio_buffer->mem+i; - float *mono=pcm[i]; - for(j=0;j<bout;j++){ - int val=(mono[j] + 1.0f) * 32768.f; - val -= 32768; - /* might as well guard against clipping */ - if(val>32767){ - val=32767; - } else if(val<-32768){ - val=-32768; - } - *ptr=val; - ptr+=this->vi.channels; - } - } + lprintf ("%d headers to go\n", this->header_count); + + if (this->header_count) { + int res = 0; - audio_buffer->vpts = this->pts; - this->pts=0; - audio_buffer->num_frames = bout; + if (this->header_count == 3) + this->op.b_o_s = 1; - this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); + if ( (res = vorbis_synthesis_headerin(&this->vi,&this->vc,&this->op)) < 0 ) { + /* error case; not a vorbis header */ + xine_log(this->stream->xine, XINE_LOG_MSG, "libvorbis: this bitstream does not contain vorbis audio data. Following first 64 bytes (return: %d).\n", res); + xine_hexdump((char *)this->op.packet, this->op.bytes < 64 ? this->op.bytes : 64); + return; + } - buf->pts=0; + this->header_count--; - /* tell libvorbis how many samples we actually consumed */ - vorbis_synthesis_read(&this->vd,bout); + if (!this->header_count) { + + int mode = AO_CAP_MODE_MONO; + + get_metadata (this); + + mode = _x_ao_channels2mode(this->vi.channels); + + this->convsize=MAX_NUM_SAMPLES/this->vi.channels; + + if (!this->output_open) { + this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, + this->stream, + 16, + this->vi.rate, + mode) ; + + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, + this->vi.bitrate_nominal); + + } + + /* OK, got and parsed all three headers. Initialize the Vorbis + * packet->PCM decoder. */ + lprintf("all three headers parsed. initializing decoder.\n"); + /* initialize central decode state */ + vorbis_synthesis_init(&this->vd,&this->vi); + /* initialize local state for most of the decode so multiple + * block decodes can proceed in parallel. We could init + * multiple vorbis_block structures for vd here */ + vorbis_block_init(&this->vd,&this->vb); + } + } + + } else if (this->output_open) { + + float **pcm; + int samples; + + if(vorbis_synthesis(&this->vb,&this->op)==0) + vorbis_synthesis_blockin(&this->vd,&this->vb); + + if (buf->pts!=0) + this->pts=buf->pts; + + while ((samples=vorbis_synthesis_pcmout(&this->vd,&pcm))>0){ + + /* **pcm is a multichannel float vector. In stereo, for + * example, pcm[0][...] is left, and pcm[1][...] is right. + * samples is the size of each channel. Convert the float + * values (-1.<=range<=1.) to whatever PCM format and write + * it out + */ + + int i,j; + int bout=(samples<this->convsize?samples:this->convsize); + audio_buffer_t *audio_buffer; + + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); + + /* convert floats to 16 bit signed ints (host order) and + interleave */ + for(i=0;i<this->vi.channels;i++){ + ogg_int16_t *ptr=audio_buffer->mem+i; + float *mono=pcm[i]; + for(j=0;j<bout;j++){ + int val=(mono[j] + 1.0f) * 32768.f; + val -= 32768; + /* might as well guard against clipping */ + if(val>32767){ + val=32767; + } else if(val<-32768){ + val=-32768; + } + *ptr=val; + ptr+=this->vi.channels; + } + } + + audio_buffer->vpts = this->pts; + this->pts=0; + audio_buffer->num_frames = bout; + + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); + + buf->pts=0; + + /* tell libvorbis how many samples we actually consumed */ + vorbis_synthesis_read(&this->vd,bout); + } + } else { + lprintf("output not open\n"); } - } else { - lprintf("output not open\n"); } } static void vorbis_dispose (audio_decoder_t *this_gen) { - vorbis_decoder_t *this = (vorbis_decoder_t *) this_gen; + vorbis_decoder_t *this = (vorbis_decoder_t *) this_gen; if( !this->header_count ) { lprintf("deinitializing decoder\n"); @@ -274,7 +302,7 @@ static void vorbis_dispose (audio_decoder_t *this_gen) { vorbis_info_clear(&this->vi); /* must be called last */ - if (this->output_open) + if (this->output_open) this->stream->audio_out->close (this->stream->audio_out, this->stream); lprintf("libvorbis instance destroyed\n"); @@ -282,12 +310,12 @@ static void vorbis_dispose (audio_decoder_t *this_gen) { free (this_gen); } -static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { vorbis_decoder_t *this ; - this = (vorbis_decoder_t *) xine_xmalloc (sizeof (vorbis_decoder_t)); + this = (vorbis_decoder_t *) calloc(1, sizeof(vorbis_decoder_t)); this->audio_decoder.decode_data = vorbis_decode_data; this->audio_decoder.reset = vorbis_reset; @@ -299,6 +327,10 @@ static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, this->header_count = 3; this->convsize = 0; + this->bufsize = INIT_BUFSIZE; + this->buf = calloc(1, INIT_BUFSIZE); + this->size = 0; + vorbis_info_init(&this->vi); vorbis_comment_init(&this->vc); @@ -326,8 +358,8 @@ static void dispose_class (audio_decoder_class_t *this) { static void *init_plugin (xine_t *xine, void *data) { vorbis_class_t *this; - - this = (vorbis_class_t *) xine_xmalloc (sizeof (vorbis_class_t)); + + this = (vorbis_class_t *) calloc(1, sizeof(vorbis_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -337,7 +369,7 @@ static void *init_plugin (xine_t *xine, void *data) { return this; } -static uint32_t audio_types[] = { +static uint32_t audio_types[] = { BUF_AUDIO_VORBIS, 0 }; @@ -347,7 +379,7 @@ static const decoder_info_t dec_info_audio = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_AUDIO_DECODER, 15, "vorbis", XINE_VERSION_CODE, &dec_info_audio, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxinevdec/Makefile.am b/src/libxinevdec/Makefile.am index 9805eb09e..b7dbe1db1 100644 --- a/src/libxinevdec/Makefile.am +++ b/src/libxinevdec/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(VISIBILITY_FLAG) @@ -43,4 +44,4 @@ xineplug_decode_gdk_pixbuf_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(GDK_PIXB xineplug_decode_theora_la_SOURCES = xine_theora_decoder.c xineplug_decode_theora_la_CFLAGS = $(AM_CFLAGS) $(OGG_CFLAGS) $(THEORA_CFLAGS) -xineplug_decode_theora_la_LIBADD = $(XINE_LIB) $(OGG_LIBS) $(THEORA_LIBS) +xineplug_decode_theora_la_LIBADD = $(XINE_LIB) $(OGG_LIBS) $(THEORA_LIBS) $(LTLIBINTL) diff --git a/src/libxinevdec/bitplane.c b/src/libxinevdec/bitplane.c index bf868ad2a..76b7c8a89 100644 --- a/src/libxinevdec/bitplane.c +++ b/src/libxinevdec/bitplane.c @@ -29,6 +29,10 @@ * - untested (found no testfiles) IFF-ANIM OPT 3, 4 and 6 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -252,7 +256,7 @@ static uint8_t *bitplane_decode_byterun1 (uint8_t *compressed, int i = 0; int j = 0; - uint8_t *uncompressed = xine_xmalloc( size_uncompressed ); + uint8_t *uncompressed = calloc(1, size_uncompressed ); while ( i < size_compressed && pixel_ptr < size_uncompressed ) { @@ -1158,8 +1162,8 @@ static void bitplane_decode_data (video_decoder_t *this_gen, this->bytes_per_pixel = 1; /* New Buffer for indexes (palette based formats) */ - this->index_buf = xine_xmalloc( this->num_pixel * this->bytes_per_pixel ); - this->index_buf_hist = xine_xmalloc( this->num_pixel * this->bytes_per_pixel ); + this->index_buf = calloc( this->num_pixel, this->bytes_per_pixel ); + this->index_buf_hist = calloc( this->num_pixel, this->bytes_per_pixel ); this->num_bitplanes = bih->biPlanes; this->camg_mode = bih->biCompression; @@ -1189,7 +1193,7 @@ static void bitplane_decode_data (video_decoder_t *this_gen, if (this->buf) free (this->buf); this->bufsize = VIDEOBUFSIZE; - this->buf = xine_xmalloc(this->bufsize); + this->buf = calloc(1, this->bufsize); this->size = 0; this->framenumber = 0; @@ -1255,7 +1259,7 @@ static void bitplane_decode_data (video_decoder_t *this_gen, case BUF_VIDEO_BITPLANE: /* uncompressed Buffer, set decoded_buf pointer direct to input stream */ if( this->buf_uk == NULL ) - this->buf_uk = xine_xmalloc( (this->size) ); + this->buf_uk = malloc(this->size); xine_fast_memcpy (this->buf_uk, this->buf, this->size); break; case BUF_VIDEO_BITPLANE_BR1: @@ -1294,7 +1298,7 @@ static void bitplane_decode_data (video_decoder_t *this_gen, } } if( this->buf_uk_hist == NULL ) { - this->buf_uk_hist = xine_xmalloc( (this->size_uk) ); + this->buf_uk_hist = malloc(this->size_uk); xine_fast_memcpy (this->buf_uk_hist, this->buf_uk, this->size_uk); xine_fast_memcpy (this->index_buf_hist, this->index_buf, (this->num_pixel * this->bytes_per_pixel)); @@ -1306,20 +1310,12 @@ static void bitplane_decode_data (video_decoder_t *this_gen, /* when no start-picture is given, create a empty one */ if( this->buf_uk_hist == NULL ) { this->size_uk = (((this->num_pixel) / 8) * this->num_bitplanes); - this->buf_uk = xine_xmalloc( (this->size_uk) ); - this->buf_uk_hist = xine_xmalloc( (this->size_uk) ); - for (i = 0; i < this->size_uk; i++) { - this->buf_uk[i] = 0; - this->buf_uk_hist[i] = 0; - } + this->buf_uk = calloc(this->num_bitplanes, ((this->num_pixel) / 8)); + this->buf_uk_hist = calloc(this->num_bitplanes, ((this->num_pixel) / 8)); } if( this->index_buf == NULL ) { - this->index_buf = xine_xmalloc( (this->num_pixel * this->bytes_per_pixel) ); - this->index_buf_hist = xine_xmalloc( (this->num_pixel * this->bytes_per_pixel) ); - for (i = 0; i < (this->num_pixel * this->bytes_per_pixel); i++) { - this->index_buf[i] = 0; - this->index_buf_hist[i] = 0; - } + this->index_buf = calloc( this->num_pixel, this->bytes_per_pixel ); + this->index_buf_hist = calloc( this->num_pixel, this->bytes_per_pixel ); } switch( anhd->operation ) { @@ -1523,7 +1519,7 @@ static void bitplane_dispose (video_decoder_t *this_gen) { static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { - bitplane_decoder_t *this = (bitplane_decoder_t *) xine_xmalloc (sizeof (bitplane_decoder_t)); + bitplane_decoder_t *this = (bitplane_decoder_t *) calloc(1, sizeof(bitplane_decoder_t)); this->video_decoder.decode_data = bitplane_decode_data; this->video_decoder.flush = bitplane_flush; @@ -1558,7 +1554,7 @@ static void dispose_class (video_decoder_class_t *this) { static void *init_plugin (xine_t *xine, void *data) { - bitplane_class_t *this = (bitplane_class_t *) xine_xmalloc (sizeof (bitplane_class_t)); + bitplane_class_t *this = (bitplane_class_t *) calloc(1, sizeof(bitplane_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; diff --git a/src/libxinevdec/foovideo.c b/src/libxinevdec/foovideo.c index 98e0ebc0b..6e1fd0ac3 100644 --- a/src/libxinevdec/foovideo.c +++ b/src/libxinevdec/foovideo.c @@ -24,6 +24,10 @@ * frame when the frames are played in succession. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -63,7 +67,7 @@ typedef struct foovideo_decoder_s { /* these are variables exclusive to the foo video decoder */ unsigned char current_yuv_byte; - + } foovideo_decoder_t; /************************************************************************** @@ -94,7 +98,7 @@ static void foovideo_decode_data (video_decoder_t *this_gen, this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } - + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ (this->stream->video_out->open) (this->stream->video_out, this->stream); @@ -206,7 +210,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre foovideo_decoder_t *this ; - this = (foovideo_decoder_t *) xine_xmalloc (sizeof (foovideo_decoder_t)); + this = (foovideo_decoder_t *) calloc(1, sizeof(foovideo_decoder_t)); this->video_decoder.decode_data = foovideo_decode_data; this->video_decoder.flush = foovideo_flush; @@ -256,7 +260,7 @@ static void *init_plugin (xine_t *xine, void *data) { foovideo_class_t *this; - this = (foovideo_class_t *) xine_xmalloc (sizeof (foovideo_class_t)); + this = (foovideo_class_t *) calloc(1, sizeof(foovideo_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -272,7 +276,7 @@ static void *init_plugin (xine_t *xine, void *data) { * list of valid buffer types (and add a new one if the one you need does * not exist). Terminate the list with a 0. */ -static const uint32_t video_types[] = { +static const uint32_t video_types[] = { /* BUF_VIDEO_FOOVIDEO, */ BUF_VIDEO_VQA, BUF_VIDEO_SORENSON_V3, diff --git a/src/libxinevdec/gdkpixbuf.c b/src/libxinevdec/gdkpixbuf.c index b5acdfa42..8815edabe 100644 --- a/src/libxinevdec/gdkpixbuf.c +++ b/src/libxinevdec/gdkpixbuf.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,11 @@ * a gdk-pixbuf-based image video decoder */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + + #include <stdlib.h> #include <string.h> @@ -60,7 +65,7 @@ typedef struct image_decoder_s { xine_stream_t *stream; int video_open; - + GdkPixbufLoader *loader; } image_decoder_t; @@ -153,8 +158,8 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { * alloc and draw video frame */ img = this->stream->video_out->get_frame (this->stream->video_out, width, - height, (double)width/(double)height, - XINE_IMGFMT_YUY2, + height, (double)width/(double)height, + XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); img->pts = buf->pts; img->duration = 3600; @@ -162,9 +167,9 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { yuv444_to_yuy2(&yuv_planes, img->base[0], img->pitches[0]); free_yuv_planes(&yuv_planes); - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, img->duration); - + img->draw(img, this->stream); img->free(img); } @@ -173,7 +178,7 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { static void image_flush (video_decoder_t *this_gen) { /* image_decoder_t *this = (image_decoder_t *) this_gen; */ - + /* * flush out any frames that are still stored in the decoder */ @@ -182,7 +187,7 @@ static void image_flush (video_decoder_t *this_gen) { static void image_reset (video_decoder_t *this_gen) { image_decoder_t *this = (image_decoder_t *) this_gen; - + /* * reset decoder after engine flush (prepare for new * video data not related to recently decoded data) @@ -198,7 +203,7 @@ static void image_reset (video_decoder_t *this_gen) { static void image_discontinuity (video_decoder_t *this_gen) { /* image_decoder_t *this = (image_decoder_t *) this_gen; */ - + /* * a time reference discontinuity has happened. * that is, it must forget any currently held pts value @@ -226,7 +231,7 @@ static void image_dispose (video_decoder_t *this_gen) { } -static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { image_class_t *cls = (image_class_t *) class_gen; @@ -236,7 +241,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, g_type_init (); - this = (image_decoder_t *) xine_xmalloc (sizeof (image_decoder_t)); + this = (image_decoder_t *) calloc(1, sizeof(image_decoder_t)); this->video_decoder.decode_data = image_decode_data; this->video_decoder.flush = image_flush; @@ -269,7 +274,7 @@ static void dispose_class (video_decoder_class_t *this_gen) { image_class_t *this = (image_class_t *) this_gen; lprintf("class closed\n"); - + free (this); } @@ -277,7 +282,7 @@ static void *init_class (xine_t *xine, void *data) { image_class_t *this; - this = (image_class_t *) xine_xmalloc (sizeof (image_class_t)); + this = (image_class_t *) calloc(1, sizeof(image_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -289,7 +294,7 @@ static void *init_class (xine_t *xine, void *data) { */ lprintf("class opened\n"); - + return this; } @@ -305,7 +310,7 @@ static const decoder_info_t dec_info_image = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "gdkpixbuf", XINE_VERSION_CODE, &dec_info_image, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxinevdec/image.c b/src/libxinevdec/image.c index a338e3cab..2c19d36fb 100644 --- a/src/libxinevdec/image.c +++ b/src/libxinevdec/image.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2003-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,10 @@ * a image video decoder */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <string.h> @@ -67,7 +71,7 @@ typedef struct image_decoder_s { xine_stream_t *stream; int video_open; - + unsigned char *image; int index; @@ -85,10 +89,10 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { xine_buffer_copyin(this->image, this->index, buf->mem, buf->size); this->index += buf->size; - + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { int width, height, i; - MagickBooleanType status; + int status; MagickWand *wand; uint8_t *img_buf, *img_buf_ptr; yuv_planes_t yuv_planes; @@ -101,7 +105,7 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { status = MagickReadImageBlob(wand, this->image, this->index); this->index = 0; - if (status == MagickFalse) { + if (!status) { DestroyMagickWand(wand); lprintf("error loading image\n"); return; @@ -139,8 +143,8 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { * alloc and draw video frame */ img = this->stream->video_out->get_frame (this->stream->video_out, width, - height, (double)width/(double)height, - XINE_IMGFMT_YUY2, + height, (double)width/(double)height, + XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); img->pts = buf->pts; img->duration = 3600; @@ -148,9 +152,9 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { yuv444_to_yuy2(&yuv_planes, img->base[0], img->pitches[0]); free_yuv_planes(&yuv_planes); - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, img->duration); - + img->draw(img, this->stream); img->free(img); } @@ -159,7 +163,7 @@ static void image_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { static void image_flush (video_decoder_t *this_gen) { /* image_decoder_t *this = (image_decoder_t *) this_gen; */ - + /* * flush out any frames that are still stored in the decoder */ @@ -168,19 +172,19 @@ static void image_flush (video_decoder_t *this_gen) { static void image_reset (video_decoder_t *this_gen) { image_decoder_t *this = (image_decoder_t *) this_gen; - + /* * reset decoder after engine flush (prepare for new * video data not related to recently decoded data) */ - + this->index = 0; } static void image_discontinuity (video_decoder_t *this_gen) { /* image_decoder_t *this = (image_decoder_t *) this_gen; */ - + /* * a time reference discontinuity has happened. * that is, it must forget any currently held pts value @@ -204,7 +208,7 @@ static void image_dispose (video_decoder_t *this_gen) { } -static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { image_class_t *cls = (image_class_t *) class_gen; @@ -212,7 +216,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, lprintf("opened\n"); - this = (image_decoder_t *) xine_xmalloc (sizeof (image_decoder_t)); + this = (image_decoder_t *) calloc(1, sizeof(image_decoder_t)); this->video_decoder.decode_data = image_decode_data; this->video_decoder.flush = image_flush; @@ -247,7 +251,7 @@ static void dispose_class (video_decoder_class_t *this_gen) { image_class_t *this = (image_class_t *) this_gen; lprintf("class closed\n"); - + free (this); } @@ -255,7 +259,7 @@ static void *init_class (xine_t *xine, void *data) { image_class_t *this; - this = (image_class_t *) xine_xmalloc (sizeof (image_class_t)); + this = (image_class_t *) calloc(1, sizeof(image_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -267,7 +271,7 @@ static void *init_class (xine_t *xine, void *data) { */ lprintf("class opened\n"); - + return this; } @@ -284,7 +288,7 @@ static const decoder_info_t dec_info_image = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "image", XINE_VERSION_CODE, &dec_info_image, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxinevdec/rgb.c b/src/libxinevdec/rgb.c index 0e7be4c18..9e28afd90 100644 --- a/src/libxinevdec/rgb.c +++ b/src/libxinevdec/rgb.c @@ -27,10 +27,14 @@ * file can be 32-, 24-, 16-, 8-, 4-, 2-, or 1-bit. Any resolutions <= 8 * can also be greyscale depending on what the QT file specifies. * - * One more catch: Raw RGB from a Microsoft file is upside down. This is + * One more catch: Raw RGB from a Microsoft file is upside down. This is * indicated by a negative height parameter. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -76,7 +80,7 @@ typedef struct rgb_decoder_s { unsigned char yuv_palette[256 * 4]; yuv_planes_t yuv_planes; - + } rgb_decoder_t; static void rgb_decode_data (video_decoder_t *this_gen, @@ -117,7 +121,7 @@ static void rgb_decode_data (video_decoder_t *this_gen, this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } - + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ (this->stream->video_out->open) (this->stream->video_out, this->stream); @@ -145,7 +149,7 @@ static void rgb_decode_data (video_decoder_t *this_gen, /* minimal buffer size */ this->bufsize = this->width * this->height * this->bytes_per_pixel; - this->buf = xine_xmalloc(this->bufsize); + this->buf = calloc(1, this->bufsize); this->size = 0; init_yuv_planes(&this->yuv_planes, this->width, this->height); @@ -191,11 +195,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, palette_index = this->buf[buf_ptr++]; - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; } else if (this->bytes_per_pixel == 2) { @@ -205,11 +209,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, buf_ptr += 2; UNPACK_BGR15(packed_pixel, r, g, b); - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } else { @@ -222,11 +226,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, /* the next line takes care of 'A' in the 32-bit case */ buf_ptr += this->bytes_per_pixel - 3; - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } @@ -246,18 +250,18 @@ static void rgb_decode_data (video_decoder_t *this_gen, } if (pixel_byte & 0x80) { - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[1 * 4 + 0]; - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[1 * 4 + 1]; - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[1 * 4 + 2]; } else { - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[0 * 4 + 0]; - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[0 * 4 + 1]; - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[0 * 4 + 2]; } pixels_left--; @@ -271,11 +275,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, } palette_index = (pixel_byte & 0xC0) >> 6; - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; pixels_left--; @@ -289,11 +293,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, } palette_index = (pixel_byte & 0xF0) >> 4; - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; pixels_left--; @@ -303,11 +307,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, palette_index = this->buf[buf_ptr++]; - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 0]; - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 1]; - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = this->yuv_palette[palette_index * 4 + 2]; } else if (this->bytes_per_pixel == 2) { @@ -317,16 +321,16 @@ static void rgb_decode_data (video_decoder_t *this_gen, buf_ptr += 2; UNPACK_RGB15(packed_pixel, r, g, b); - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } else { - /* RGB24 or ARGB32; the next line takes care of 'A' in the + /* RGB24 or ARGB32; the next line takes care of 'A' in the * 32-bit case */ buf_ptr += this->bytes_per_pixel - 3; @@ -334,11 +338,11 @@ static void rgb_decode_data (video_decoder_t *this_gen, g = this->buf[buf_ptr++]; b = this->buf[buf_ptr++]; - this->yuv_planes.y[row_ptr + pixel_ptr] = + this->yuv_planes.y[row_ptr + pixel_ptr] = COMPUTE_Y(r, g, b); - this->yuv_planes.u[row_ptr + pixel_ptr] = + this->yuv_planes.u[row_ptr + pixel_ptr] = COMPUTE_U(r, g, b); - this->yuv_planes.v[row_ptr + pixel_ptr] = + this->yuv_planes.v[row_ptr + pixel_ptr] = COMPUTE_V(r, g, b); } @@ -398,7 +402,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre rgb_decoder_t *this ; - this = (rgb_decoder_t *) xine_xmalloc (sizeof (rgb_decoder_t)); + this = (rgb_decoder_t *) calloc(1, sizeof(rgb_decoder_t)); this->video_decoder.decode_data = rgb_decode_data; this->video_decoder.flush = rgb_flush; @@ -432,7 +436,7 @@ static void *init_plugin (xine_t *xine, void *data) { rgb_class_t *this; - this = (rgb_class_t *) xine_xmalloc (sizeof (rgb_class_t)); + this = (rgb_class_t *) calloc(1, sizeof(rgb_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -446,7 +450,7 @@ static void *init_plugin (xine_t *xine, void *data) { * exported plugin catalog entry */ -static const uint32_t video_types[] = { +static const uint32_t video_types[] = { BUF_VIDEO_RGB, 0 }; @@ -457,7 +461,7 @@ static const decoder_info_t dec_info_video = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "rgb", XINE_VERSION_CODE, &dec_info_video, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxinevdec/xine_theora_decoder.c b/src/libxinevdec/xine_theora_decoder.c index c71ce7559..bf51a8779 100644 --- a/src/libxinevdec/xine_theora_decoder.c +++ b/src/libxinevdec/xine_theora_decoder.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2001-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -101,17 +101,17 @@ static void yuv2frame(yuv_buffer *yuv, vo_frame_t *frame, int offset_x, int offs crop_offset=offset_x+yuv->y_stride*offset_y; for(i=0;i<frame->height;i++) - xine_fast_memcpy(frame->base[0]+frame->pitches[0]*i, - yuv->y+crop_offset+yuv->y_stride*i, + xine_fast_memcpy(frame->base[0]+frame->pitches[0]*i, + yuv->y+crop_offset+yuv->y_stride*i, frame->width); crop_offset=(offset_x/2)+(yuv->uv_stride)*(offset_y/2); for(i=0;i<frame->height/2;i++){ - xine_fast_memcpy(frame->base[1]+frame->pitches[1]*i, - yuv->u+crop_offset+yuv->uv_stride*i, + xine_fast_memcpy(frame->base[1]+frame->pitches[1]*i, + yuv->u+crop_offset+yuv->uv_stride*i, frame->width/2); - xine_fast_memcpy(frame->base[2]+frame->pitches[2]*i, - yuv->v+crop_offset+yuv->uv_stride*i, + xine_fast_memcpy(frame->base[2]+frame->pitches[2]*i, + yuv->v+crop_offset+yuv->uv_stride*i, frame->width/2); } @@ -123,7 +123,7 @@ static int collect_data (theora_decoder_t *this, buf_element_t *buf ) { if (buf->decoder_flags & BUF_FLAG_FRAME_START) { this->done=0; /*start from the beginnig*/ - this->reject=0;/*new packet - new try*/ + this->reject=0;/*new packet - new try*/ /*copy the ogg_packet struct and the sum, correct the adress of the packet*/ xine_fast_memcpy (&this->op, buf->content, sizeof(ogg_packet)); @@ -142,7 +142,7 @@ static int collect_data (theora_decoder_t *this, buf_element_t *buf ) { } readin_op (this, buf->content, buf->size ); } - + if ((buf->decoder_flags & BUF_FLAG_FRAME_END) && !this->reject) { if ( this->done != this->op.bytes ) { printf ("libtheora: A packet changed its size during transfer - rejected\n"); @@ -156,8 +156,8 @@ static int collect_data (theora_decoder_t *this, buf_element_t *buf ) { static void theora_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { /* - * decode data from buf and feed decoded frames to - * video output + * decode data from buf and feed decoded frames to + * video output */ theora_decoder_t *this = (theora_decoder_t *) this_gen; vo_frame_t *frame; @@ -195,7 +195,7 @@ static void theora_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { } /*headers are now decoded. initialize the decoder*/ theora_decode_init (&this->t_state, &this->t_info); - + lprintf("theora stream is Theora %dx%d %.02f fps video.\n" " frame content is %dx%d with offset (%d,%d).\n" " pixel aspect is %d:%d.\n", @@ -312,7 +312,7 @@ static video_decoder_t *theora_open_plugin (video_decoder_class_t *class_gen, xi theora_decoder_t *this ; - this = (theora_decoder_t *) xine_xmalloc (sizeof (theora_decoder_t)); + this = (theora_decoder_t *) calloc(1, sizeof(theora_decoder_t)); this->theora_decoder.decode_data = theora_decode_data; this->theora_decoder.flush = theora_flush; @@ -353,7 +353,7 @@ static char *theora_get_identifier (video_decoder_class_t *this) { static char *theora_get_description (video_decoder_class_t *this) { /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ return "theora video decoder plugin"; @@ -369,8 +369,8 @@ static void theora_dispose_class (video_decoder_class_t *this) { static void *init_plugin (xine_t *xine, void *data) { /*initialize our plugin*/ theora_class_t *this; - - this = (theora_class_t *) xine_xmalloc (sizeof (theora_class_t)); + + this = (theora_class_t *) calloc(1, sizeof(theora_class_t)); this->decoder_class.open_plugin = theora_open_plugin; this->decoder_class.get_identifier = theora_get_identifier; @@ -392,7 +392,7 @@ static const decoder_info_t dec_info_video = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "theora", XINE_VERSION_CODE, &dec_info_video, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxinevdec/yuv.c b/src/libxinevdec/yuv.c index 2b8657685..6cb1b240c 100644 --- a/src/libxinevdec/yuv.c +++ b/src/libxinevdec/yuv.c @@ -22,6 +22,10 @@ * a way that xine can display them. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -58,7 +62,7 @@ typedef struct yuv_decoder_s { int width; /* the width of a video frame */ int height; /* the height of a video frame */ double ratio; /* the width to height ratio */ - + int progressive; int top_field_first; @@ -100,10 +104,10 @@ static void yuv_decode_data (video_decoder_t *this_gen, this->ratio = (double)buf->decoder_info[1] / (double)buf->decoder_info[2]; else this->ratio = (double)this->width / (double)this->height; - + this->progressive = buf->decoder_info[3]; this->top_field_first = buf->decoder_info[4]; - + if (this->buf) { free (this->buf); this->buf = NULL; @@ -121,7 +125,7 @@ static void yuv_decode_data (video_decoder_t *this_gen, case BUF_VIDEO_YUY2: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Raw YUY2"); break; - + case BUF_VIDEO_YV12: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Raw YV12"); break; @@ -133,13 +137,13 @@ static void yuv_decode_data (video_decoder_t *this_gen, case BUF_VIDEO_GREY: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Greyscale YUV"); break; - + case BUF_VIDEO_I420: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Raw I420"); break; } - + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height); _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_RATIO, this->ratio*10000); @@ -162,14 +166,14 @@ static void yuv_decode_data (video_decoder_t *this_gen, xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); this->size += buf->size; - + src = this->buf; } if (buf->decoder_flags & BUF_FLAG_FRAME_END) { if (buf->type == BUF_VIDEO_YUY2) { - + img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); @@ -180,14 +184,14 @@ static void yuv_decode_data (video_decoder_t *this_gen, /* dst */ img->base[0], img->pitches[0], /* width x height */ - this->width, this->height); - + this->width, this->height); + } else if (buf->type == BUF_VIDEO_YV12) { img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_YV12, VO_BOTH_FIELDS); - + yv12_to_yv12( /* Y */ src, this->width, @@ -202,7 +206,7 @@ static void yuv_decode_data (video_decoder_t *this_gen, this->width, this->height); } else if (buf->type == BUF_VIDEO_I420) { - + img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_YV12, VO_BOTH_FIELDS); @@ -229,17 +233,17 @@ static void yuv_decode_data (video_decoder_t *this_gen, yuv9_to_yv12( /* Y */ - src, + src, this->width, - img->base[0], + img->base[0], img->pitches[0], /* U */ - src + (this->width * this->height), + src + (this->width * this->height), this->width / 4, img->base[1], img->pitches[1], /* V */ - src + (this->width * this->height) + + src + (this->width * this->height) + (this->width * this->height / 16), this->width / 4, img->base[2], @@ -321,7 +325,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre yuv_decoder_t *this ; - this = (yuv_decoder_t *) xine_xmalloc (sizeof (yuv_decoder_t)); + this = (yuv_decoder_t *) calloc(1, sizeof(yuv_decoder_t)); this->video_decoder.decode_data = yuv_decode_data; this->video_decoder.flush = yuv_flush; @@ -355,7 +359,7 @@ static void *init_plugin (xine_t *xine, void *data) { yuv_class_t *this; - this = (yuv_class_t *) xine_xmalloc (sizeof (yuv_class_t)); + this = (yuv_class_t *) calloc(1, sizeof(yuv_class_t)); this->decoder_class.open_plugin = open_plugin; this->decoder_class.get_identifier = get_identifier; @@ -369,8 +373,8 @@ static void *init_plugin (xine_t *xine, void *data) { * exported plugin catalog entry */ -static const uint32_t video_types[] = { - BUF_VIDEO_YUY2, +static const uint32_t video_types[] = { + BUF_VIDEO_YUY2, BUF_VIDEO_YV12, BUF_VIDEO_YVU9, BUF_VIDEO_GREY, @@ -384,7 +388,7 @@ static const decoder_info_t dec_info_video = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_DECODER, 18, "yuv", XINE_VERSION_CODE, &dec_info_video, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/post/audio/Makefile.am b/src/post/audio/Makefile.am index 41a364d0d..5e587ef2f 100644 --- a/src/post/audio/Makefile.am +++ b/src/post/audio/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common noinst_HEADERS = dsp.h filter.h window.h audio_filters.h diff --git a/src/post/audio/audio_filters.c b/src/post/audio/audio_filters.c index 8200db51b..eb90d38cb 100644 --- a/src/post/audio/audio_filters.c +++ b/src/post/audio/audio_filters.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,9 @@ * catalog for audio filter plugins */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "xine_internal.h" #include "xineutils.h" @@ -35,7 +38,7 @@ static const post_info_t volnorm_special_info = { XINE_POST_TYPE_AUDIO_FILTER const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST, 9, "upmix", XINE_VERSION_CODE, &upmix_special_info, &upmix_init_plugin }, { PLUGIN_POST, 9, "upmix_mono", XINE_VERSION_CODE, &upmix_mono_special_info, &upmix_mono_init_plugin }, { PLUGIN_POST, 9, "stretch", XINE_VERSION_CODE, &stretch_special_info, &stretch_init_plugin }, diff --git a/src/post/audio/audio_filters.h b/src/post/audio/audio_filters.h index 6c064945a..c2bf88cf8 100644 --- a/src/post/audio/audio_filters.h +++ b/src/post/audio/audio_filters.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/post/audio/dsp.h b/src/post/audio/dsp.h index 237640283..8dabe4f36 100644 --- a/src/post/audio/dsp.h +++ b/src/post/audio/dsp.h @@ -1,5 +1,5 @@ /*============================================================================= - * + * * This software has been released under the terms of the GNU Public * license. See http://www.gnu.org/copyleft/gpl.html for details. * @@ -9,7 +9,7 @@ */ #ifndef _DSP_H -#define _DSP_H 1 +#define _DSP_H 1 /* Implementation of routines used for DSP */ diff --git a/src/post/audio/filter.c b/src/post/audio/filter.c index c5602736c..f41d880fc 100644 --- a/src/post/audio/filter.c +++ b/src/post/audio/filter.c @@ -1,5 +1,5 @@ /*============================================================================= - * + * * This software has been released under the terms of the GNU Public * license. See http://www.gnu.org/copyleft/gpl.html for details. * @@ -25,12 +25,12 @@ * * n number of filter taps, where mod(n,4)==0 * w filter taps - * x input signal must be a circular buffer which is indexed backwards + * x input signal must be a circular buffer which is indexed backwards */ inline _ftype_t fir(register unsigned int n, _ftype_t* w, _ftype_t* x) { register _ftype_t y; /* Output */ - y = 0.0; + y = 0.0; do{ n--; y+=w[n]*x[n]; @@ -44,7 +44,7 @@ inline _ftype_t fir(register unsigned int n, _ftype_t* w, _ftype_t* x) * d number of filters * xi current index in xq * w filter taps k by n big - * x input signal must be a circular buffers which are indexed backwards + * x input signal must be a circular buffers which are indexed backwards * y output buffer * s output buffer stride */ @@ -67,11 +67,11 @@ inline _ftype_t* pfir(unsigned int n, unsigned int d, unsigned int xi, _ftype_t* at the new samples, xi current index in xq and n the length of the filter. xq must be n*2 by k big, s is the index for in. */ -inline int updatepq(unsigned int n, unsigned int d, unsigned int xi, _ftype_t** xq, _ftype_t* in, unsigned int s) +inline int updatepq(unsigned int n, unsigned int d, unsigned int xi, _ftype_t** xq, _ftype_t* in, unsigned int s) { register _ftype_t* txq = *xq + xi; register int nt = n*2; - + while(d-- >0){ *txq= *(txq+n) = *in; txq+=nt; @@ -88,26 +88,26 @@ inline int updatepq(unsigned int n, unsigned int d, unsigned int xi, _ftype_t** n filter length must be odd for HP and BS filters w buffer for the filter taps (must be n long) - fc cutoff frequencies (1 for LP and HP, 2 for BP and BS) + fc cutoff frequencies (1 for LP and HP, 2 for BP and BS) 0 < fc < 1 where 1 <=> Fs/2 flags window and filter type as defined in filter.h - variables are ored together: i.e. LP|HAMMING will give a - low pass filter designed using a hamming window + variables are ored together: i.e. LP|HAMMING will give a + low pass filter designed using a hamming window opt beta constant used only when designing using kaiser windows - + returns 0 if OK, -1 if fail */ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _ftype_t opt) { - unsigned int o = n & 1; /* Indicator for odd filter length */ + unsigned int o = n & 1; /* Indicator for odd filter length */ unsigned int end = ((n + 1) >> 1) - o; /* Loop end */ unsigned int i; /* Loop index */ _ftype_t k1 = 2 * M_PI; /* 2*pi*fc1 */ _ftype_t k2 = 0.5 * (_ftype_t)(1 - o);/* Constant used if the filter has even length */ _ftype_t k3; /* 2*pi*fc2 Constant used in BP and BS design */ - _ftype_t g = 0.0; /* Gain */ - _ftype_t t1,t2,t3; /* Temporary variables */ + _ftype_t g = 0.0; /* Gain */ + _ftype_t t1,t2,t3; /* Temporary variables */ _ftype_t fc1,fc2; /* Cutoff frequencies */ /* Sanity check */ @@ -130,10 +130,10 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f case(KAISER): kaiser(n,w,opt); break; default: - return -1; + return -1; } - if(flags & (LP | HP)){ + if(flags & (LP | HP)){ fc1=*fc; /* Cutoff frequency must be < 0.5 where 0.5 <=> Fs/2 */ fc1 = ((fc1 <= 1.0) && (fc1 > 0.0)) ? fc1/2 : 0.25; @@ -143,7 +143,7 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f /* * If the filter length is odd, there is one point which is exactly - * in the middle. The value at this point is 2*fCutoff*sin(x)/x, + * in the middle. The value at this point is 2*fCutoff*sin(x)/x, * where x is zero. To make sure nothing strange happens, we set this * value separately. */ @@ -196,9 +196,9 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f t2 = sin(k3 * t1)/(M_PI * t1); /* Sinc fc2 */ t3 = sin(k1 * t1)/(M_PI * t1); /* Sinc fc1 */ g += w[end-i-1] * (t3 + t2); /* Total gain in filter */ - w[end-i-1] = w[n-end+i] = w[end-i-1] * (t2 - t3); + w[end-i-1] = w[n-end+i] = w[end-i-1] * (t2 - t3); } - } + } else{ /* Band stop */ if (!o) /* Band stop filters must have odd length */ return -1; @@ -210,7 +210,7 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f t1 = (_ftype_t)(i+1); t2 = sin(k1 * t1)/(M_PI * t1); /* Sinc fc1 */ t3 = sin(k3 * t1)/(M_PI * t1); /* Sinc fc2 */ - w[end-i-1] = w[n-end+i] = w[end-i-1] * (t2 - t3); + w[end-i-1] = w[n-end+i] = w[end-i-1] * (t2 - t3); g += 2*w[end-i-1]; /* Total gain in filter */ } } @@ -218,9 +218,9 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f /* Normalize gain */ g=1/g; - for (i=0; i<n; i++) + for (i=0; i<n; i++) w[i] *= g; - + return 0; } @@ -229,7 +229,7 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f * n length of prototype filter * k number of polyphase components * w prototype filter taps - * pw Parallel FIR filter + * pw Parallel FIR filter * g Filter gain * flags FWD forward indexing * REW reverse indexing @@ -240,10 +240,10 @@ int design_fir(unsigned int n, _ftype_t* w, _ftype_t* fc, unsigned int flags, _f int design_pfir(unsigned int n, unsigned int k, _ftype_t* w, _ftype_t** pw, _ftype_t g, unsigned int flags) { int l = (int)n/k; /* Length of individual FIR filters */ - int i; /* Counters */ + int i; /* Counters */ int j; _ftype_t t; /* g * w[i] */ - + /* Sanity check */ if(l<1 || k<1 || !w || !pw) return -1; @@ -276,7 +276,7 @@ int design_pfir(unsigned int n, unsigned int k, _ftype_t* w, _ftype_t** pw, _fty /* Pre-warp the coefficients of a numerator or denominator. * Note that a0 is assumed to be 1, so there is no wrapping - * of it. + * of it. */ void prewarp(_ftype_t* a, _ftype_t fc, _ftype_t fs) { @@ -303,12 +303,12 @@ void prewarp(_ftype_t* a, _ftype_t fc, _ftype_t fs) * Arguments: * a - s-domain numerator coefficients * b - s-domain denominator coefficients - * k - filter gain factor. Initially set to 1 and modified by each + * k - filter gain factor. Initially set to 1 and modified by each * biquad section in such a way, as to make it the * coefficient by which to multiply the overall filter gain * in order to achieve a desired overall filter gain, - * specified in initial value of k. - * fs - sampling rate (Hz) + * specified in initial value of k. + * fs - sampling rate (Hz) * coef - array of z-domain coefficients to be filled in. * * Return: On return, set coef z-domain coefficients and k to the gain @@ -342,7 +342,7 @@ void bilinear(_ftype_t* a, _ftype_t* b, _ftype_t* k, _ftype_t fs, _ftype_t *coef * create a filter fill in a, b, Q and fs and make space for coef and k. * * - * Example Butterworth design: + * Example Butterworth design: * * Below are Butterworth polynomials, arranged as a series of 2nd * order sections: @@ -398,12 +398,12 @@ void bilinear(_ftype_t* a, _ftype_t* b, _ftype_t* k, _ftype_t fs, _ftype_t *coef * a - s-domain numerator coefficients, a[1] is always assumed to be 1.0 * b - s-domain denominator coefficients * Q - Q value for the filter - * k - filter gain factor. Initially set to 1 and modified by each + * k - filter gain factor. Initially set to 1 and modified by each * biquad section in such a way, as to make it the * coefficient by which to multiply the overall filter gain * in order to achieve a desired overall filter gain, - * specified in initial value of k. - * fs - sampling rate (Hz) + * specified in initial value of k. + * fs - sampling rate (Hz) * coef - array of z-domain coefficients to be filled in. * * Note: Upon return from each call, the k argument will be set to a @@ -414,12 +414,12 @@ void bilinear(_ftype_t* a, _ftype_t* b, _ftype_t* k, _ftype_t fs, _ftype_t *coef * * return -1 if fail 0 if success. */ -int szxform(_ftype_t* a, _ftype_t* b, _ftype_t Q, _ftype_t fc, _ftype_t fs, _ftype_t *k, _ftype_t *coef) +int szxform(const _ftype_t* a, const _ftype_t* b, _ftype_t Q, _ftype_t fc, _ftype_t fs, _ftype_t *k, _ftype_t *coef) { _ftype_t at[3]; _ftype_t bt[3]; - if(!a || !b || !k || !coef || (Q>1000.0 || Q< 1.0)) + if(!a || !b || !k || !coef || (Q>1000.0 || Q< 1.0)) return -1; memcpy(at,a,3*sizeof(_ftype_t)); diff --git a/src/post/audio/filter.h b/src/post/audio/filter.h index 0b0ce1c1b..4d756a618 100644 --- a/src/post/audio/filter.h +++ b/src/post/audio/filter.h @@ -1,5 +1,5 @@ /*============================================================================= - * + * * This software has been released under the terms of the GNU Public * license. See http://www.gnu.org/copyleft/gpl.html for details. * @@ -37,7 +37,7 @@ #define WINDOW_MASK 0x0000001F /* Parallel filter design */ -#define FWD 0x00000001 /* Forward indexing of polyphase filter */ +#define FWD 0x00000001 /* Forward indexing of polyphase filter */ #define REW 0x00000002 /* Reverse indexing of polyphase filter */ #define ODD 0x00000010 /* Make filter HP */ @@ -55,12 +55,12 @@ extern int design_pfir(unsigned int n, unsigned int k, _ftype_t* w, _ftype_t** p extern void prewarp(_ftype_t* a, _ftype_t fc, _ftype_t fs); void bilinear(_ftype_t* a, _ftype_t* b, _ftype_t* k, _ftype_t fs, _ftype_t *coef); -extern int szxform(_ftype_t* a, _ftype_t* b, _ftype_t Q, _ftype_t fc, _ftype_t fs, _ftype_t *k, _ftype_t *coef); +extern int szxform(const _ftype_t* a, const _ftype_t* b, _ftype_t Q, _ftype_t fc, _ftype_t fs, _ftype_t *k, _ftype_t *coef); /* Add new data to circular queue designed to be used with a FIR * filter. xq is the circular queue, in pointing at the new sample, xi * current index for xq and n the length of the filter. xq must be n*2 - * long. + * long. */ #define updateq(n,xi,xq,in)\ xq[xi]=(xq)[(xi)+(n)]=*(in);\ diff --git a/src/post/audio/stretch.c b/src/post/audio/stretch.c index 5aa7a0617..154202da4 100644 --- a/src/post/audio/stretch.c +++ b/src/post/audio/stretch.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,10 @@ * Time stretch by a given factor, optionally preserving pitch */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" @@ -66,19 +70,19 @@ static void stretchscr_set_pivot (stretchscr_t *this) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; -/* This next part introduces a one off inaccuracy - * to the scr due to rounding tv to pts. +/* This next part introduces a one off inaccuracy + * to the scr due to rounding tv to pts. */ this->cur_time.tv_sec=tv.tv_sec; this->cur_time.tv_usec=tv.tv_usec; - this->cur_pts=pts; + this->cur_pts=pts; return ; } @@ -90,7 +94,7 @@ static int stretchscr_set_speed (scr_plugin_t *scr, int speed) { stretchscr_set_pivot( this ); this->xine_speed = speed; - this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL / + this->speed_factor = (double) speed * 90000.0 / XINE_FINE_SPEED_NORMAL / (*this->stretch_factor); pthread_mutex_unlock (&this->lock); @@ -121,7 +125,7 @@ static void stretchscr_start (scr_plugin_t *scr, int64_t start_vpts) { this->cur_pts = start_vpts; pthread_mutex_unlock (&this->lock); - + stretchscr_set_speed (&this->scr, XINE_FINE_SPEED_NORMAL); } @@ -130,16 +134,16 @@ static int64_t stretchscr_get_current (scr_plugin_t *scr) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&tv, NULL); - + pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; - + pthread_mutex_unlock (&this->lock); return pts; @@ -152,10 +156,10 @@ static void stretchscr_exit (scr_plugin_t *scr) { free(this); } -static stretchscr_t* stretchscr_init (double *stretch_factor) { +static stretchscr_t *XINE_MALLOC stretchscr_init (double *stretch_factor) { stretchscr_t *this; - this = (stretchscr_t *) xine_xmalloc(sizeof(stretchscr_t)); + this = calloc(1, sizeof(stretchscr_t)); this->scr.interface_version = 3; this->scr.get_priority = stretchscr_get_priority; @@ -164,9 +168,9 @@ static stretchscr_t* stretchscr_init (double *stretch_factor) { this->scr.start = stretchscr_start; this->scr.get_current = stretchscr_get_current; this->scr.exit = stretchscr_exit; - + pthread_mutex_init (&this->lock, NULL); - + this->stretch_factor = stretch_factor; stretchscr_set_speed (&this->scr, XINE_SPEED_PAUSE); @@ -198,21 +202,21 @@ typedef struct stretch_parameters_s { START_PARAM_DESCR( stretch_parameters_t ) PARAM_ITEM( POST_PARAM_TYPE_BOOL, preserve_pitch, NULL, 0, 1, 0, "Preserve pitch" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, factor, NULL, 0.5, 1.5, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, factor, NULL, 0.5, 1.5, 0, "Time stretch factor (<1.0 shorten duration)" ) END_PARAM_DESCR( param_descr ) /* plugin structure */ struct post_plugin_stretch_s { post_plugin_t post; - + stretchscr_t* scr; /* private data */ stretch_parameters_t params; xine_post_in_t params_input; int params_changed; - + int channels; int bytes_per_frame; @@ -224,9 +228,9 @@ struct post_plugin_stretch_s { int num_frames; /* current # of frames on audiofrag */ int16_t last_sample[RESAMPLE_MAX_CHANNELS]; - + int64_t pts; /* pts for audiofrag */ - + pthread_mutex_t lock; }; @@ -286,16 +290,16 @@ static int stretch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; int64_t time; - + _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - - /* register our own scr provider */ + + /* register our own scr provider */ time = port->stream->xine->clock->get_current_time(port->stream->xine->clock); this->scr = stretchscr_init(&this->params.factor); this->scr->scr.start(&this->scr->scr, time); @@ -303,7 +307,7 @@ static int stretch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, /* force updating on stretch_port_put_buffer */ this->params_changed = 1; - + return (port->original_port->open) (port->original_port, stream, bits, rate, mode); } @@ -316,34 +320,34 @@ static void stretch_port_close(xine_audio_port_t *port_gen, xine_stream_t *strea port->stream->xine->clock->unregister_scr(port->stream->xine->clock, &this->scr->scr); this->scr->scr.exit(&this->scr->scr); } - + if(this->audiofrag) { free(this->audiofrag); this->audiofrag = NULL; } - + if(this->outfrag) { free(this->outfrag); this->outfrag = NULL; } - + if(this->w) { free(this->w); this->w = NULL; } - + port->stream = NULL; port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } -static void stretch_process_fragment( post_audio_port_t *port, +static void stretch_process_fragment( post_audio_port_t *port, xine_stream_t *stream, extra_info_t *extra_info ) { post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; - + audio_buffer_t *outbuf; int16_t *data_out = this->outfrag; int num_frames_in = this->num_frames; @@ -370,52 +374,52 @@ static void stretch_process_fragment( post_audio_port_t *port, * input chunk has two halves, A and B. * output chunk is composed as follow: * - some frames copied directly from A - * - some frames copied from A merged with frames from B + * - some frames copied from A merged with frames from B * weighted by an increasing factor (0 -> 1.0) * - frames from A weighted by a decreasing factor (1.0 -> 0) * merged with frames copied from B * - some frames copied directly from B */ - + int merge_frames = num_frames_in - num_frames_out; int copy_frames; int16_t *src = this->audiofrag; int16_t *dst = this->outfrag; int i, j; - + if( merge_frames > num_frames_out ) merge_frames = num_frames_out; copy_frames = num_frames_out - merge_frames; - + memcpy(dst, src, copy_frames/2 * this->bytes_per_frame); dst += copy_frames/2 * this->channels; src += copy_frames/2 * this->channels; - + for( i = 0; i < merge_frames/2; i++ ) { for( j = 0; j < this->channels; j++, src++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) src[0] + src[merge_frames * this->channels] * this->w[i]); *dst = CLIP_INT16(s); } } - + for( ; i < merge_frames; i++ ) { for( j = 0; j < this->channels; j++, src++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) src[0] * this->w[i] + src[merge_frames * this->channels]); *dst = CLIP_INT16(s); } } - + src += merge_frames * this->channels; - + memcpy(dst, src, (copy_frames - copy_frames/2) * this->bytes_per_frame); - + } else { /* * time expansion strategy @@ -423,13 +427,13 @@ static void stretch_process_fragment( post_audio_port_t *port, * output chunk is composed of two versions of the * input chunk: * - first part copied directly from input, and then - * merged with the second (delayed) part using a + * merged with the second (delayed) part using a * decreasing factor (1.0 -> 0) * - the delayed version of the input is merged with - * an increasing factor (0 -> 1.0) and then (when - * factor reaches 1.0) just copied until the end. + * an increasing factor (0 -> 1.0) and then (when + * factor reaches 1.0) just copied until the end. */ - + int merge_frames = num_frames_out - num_frames_in; int copy_frames = num_frames_out - merge_frames; int16_t *src1 = this->audiofrag; @@ -445,67 +449,67 @@ static void stretch_process_fragment( post_audio_port_t *port, for( i = 0; i < merge_frames/2; i++ ) { for( j = 0; j < this->channels; j++, src1++, src2++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) *src1 + *src2 * this->w[i]); *dst = CLIP_INT16(s); } } - + for( ; i < merge_frames; i++ ) { for( j = 0; j < this->channels; j++, src1++, src2++, dst++ ) { - + int32_t s = (int32_t) ((_ftype_t) *src1 * this->w[i] + *src2); *dst = CLIP_INT16(s); } } - + memcpy(dst, src2, (copy_frames - copy_frames/2) * this->bytes_per_frame); } } - + /* copy processed fragment into multiple audio buffers, if needed */ while( num_frames_out ) { - outbuf = port->original_port->get_buffer(port->original_port); - + outbuf = port->original_port->get_buffer(port->original_port); + outbuf->num_frames = outbuf->mem_size / this->bytes_per_frame; if( outbuf->num_frames > num_frames_out ) outbuf->num_frames = num_frames_out; - - memcpy( outbuf->mem, data_out, + + memcpy( outbuf->mem, data_out, outbuf->num_frames * this->bytes_per_frame ); num_frames_out -= outbuf->num_frames; data_out = (uint16_t *)((uint8_t *)data_out + outbuf->num_frames * this->bytes_per_frame); - + outbuf->vpts = this->pts; this->pts = 0; outbuf->stream = stream; outbuf->format.bits = port->bits; outbuf->format.rate = port->rate; outbuf->format.mode = port->mode; - + _x_extra_info_merge( outbuf->extra_info, extra_info ); - - port->original_port->put_buffer(port->original_port, outbuf, stream ); + + port->original_port->put_buffer(port->original_port, outbuf, stream ); } - + this->num_frames = 0; } -static void stretch_port_put_buffer (xine_audio_port_t *port_gen, +static void stretch_port_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_stretch_t *this = (post_plugin_stretch_t *)port->post; int16_t *data_in; - + pthread_mutex_lock (&this->lock); - + if( this->params_changed ) { int64_t audio_step; @@ -513,40 +517,40 @@ static void stretch_port_put_buffer (xine_audio_port_t *port_gen, /* output whatever we have before changing parameters */ stretch_process_fragment( port, stream, buf->extra_info ); } - + this->channels = _x_ao_mode2channels(port->mode); this->bytes_per_frame = port->bits / 8 * this->channels; - + audio_step = ((int64_t)90000 * (int64_t)32768) / (int64_t)port->rate; audio_step = (int64_t) ((double)audio_step / this->params.factor); stream->metronom->set_audio_rate(stream->metronom, audio_step); stretchscr_set_speed(&this->scr->scr, this->scr->xine_speed); - + if(this->audiofrag) { free(this->audiofrag); this->audiofrag = NULL; } - + if(this->outfrag) { free(this->outfrag); this->outfrag = NULL; } - + if(this->w) { free(this->w); this->w = NULL; } - + this->frames_per_frag = port->rate * AUDIO_FRAGMENT; this->frames_per_outfrag = (int) ((double)this->params.factor * this->frames_per_frag); if( this->frames_per_frag != this->frames_per_outfrag ) { int wsize; - - this->audiofrag = malloc( this->frames_per_frag * this->bytes_per_frame ); - this->outfrag = malloc( this->frames_per_outfrag * this->bytes_per_frame ); - + + this->audiofrag = malloc( this->frames_per_frag * this->bytes_per_frame ); + this->outfrag = malloc( this->frames_per_outfrag * this->bytes_per_frame ); + if( this->frames_per_frag > this->frames_per_outfrag ) wsize = this->frames_per_frag - this->frames_per_outfrag; else @@ -555,41 +559,41 @@ static void stretch_port_put_buffer (xine_audio_port_t *port_gen, this->w = (_ftype_t*) malloc( wsize * sizeof(_ftype_t) ); triang(wsize, this->w); } - + this->num_frames = 0; this->pts = 0; - + this->params_changed = 0; } - + pthread_mutex_unlock (&this->lock); /* just pass data through if we have nothing to do */ if( this->frames_per_frag == this->frames_per_outfrag || /* FIXME: we only handle 1 or 2 channels, 16 bits for now */ - (this->channels != 1 && this->channels != 2) || + (this->channels != 1 && this->channels != 2) || port->bits != 16 ) { - - port->original_port->put_buffer(port->original_port, buf, stream ); - + + port->original_port->put_buffer(port->original_port, buf, stream ); + return; } - + /* update pts for our current audio fragment */ if( buf->vpts ) this->pts = buf->vpts - (this->num_frames * 90000 / port->rate); - + data_in = buf->mem; while( buf->num_frames ) { int frames_to_copy = this->frames_per_frag - this->num_frames; - + if( frames_to_copy > buf->num_frames ) frames_to_copy = buf->num_frames; /* copy up to one fragment from input buf to our buffer */ memcpy( (uint8_t *)this->audiofrag + this->num_frames * this->bytes_per_frame, data_in, frames_to_copy * this->bytes_per_frame ); - + data_in = (uint16_t *)((uint8_t *)data_in + frames_to_copy * this->bytes_per_frame); this->num_frames += frames_to_copy; buf->num_frames -= frames_to_copy; @@ -599,10 +603,10 @@ static void stretch_port_put_buffer (xine_audio_port_t *port_gen, stretch_process_fragment( port, stream, buf->extra_info ); } } - + buf->num_frames=0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ - port->original_port->put_buffer(port->original_port, buf, stream ); - + port->original_port->put_buffer(port->original_port, buf, stream ); + return; } @@ -620,27 +624,27 @@ static post_plugin_t *stretch_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_stretch_t *this = (post_plugin_stretch_t *)xine_xmalloc(sizeof(post_plugin_stretch_t)); + post_plugin_stretch_t *this = calloc(1, sizeof(post_plugin_stretch_t)); post_in_t *input; post_out_t *output; xine_post_in_t *input_api; post_audio_port_t *port; stretch_parameters_t init_params; - + if (!this || !audio_target || !audio_target[0] ) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); init_params.preserve_pitch = 1; init_params.factor = 0.80; - + pthread_mutex_init (&this->lock, NULL); set_parameters ((xine_post_t *)&this->post, &init_params); - + port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output); port->new_port.open = stretch_port_open; port->new_port.close = stretch_port_close; @@ -678,16 +682,16 @@ static void stretch_class_dispose(post_class_t *class_gen) void *stretch_init_plugin(xine_t *xine, void *data) { post_class_stretch_t *class = (post_class_stretch_t *)malloc(sizeof(post_class_stretch_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = stretch_open_plugin; class->post_class.get_identifier = stretch_get_identifier; class->post_class.get_description = stretch_get_description; class->post_class.dispose = stretch_class_dispose; - + class->xine = xine; - + return class; } diff --git a/src/post/audio/upmix.c b/src/post/audio/upmix.c index e1b2afbe3..9cf68b365 100644 --- a/src/post/audio/upmix.c +++ b/src/post/audio/upmix.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -24,6 +24,10 @@ * E.g. Converts Stereo into Surround 5.1 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" @@ -163,13 +167,13 @@ static int upmix_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; capabilities = port->original_port->get_capabilities(port->original_port); - + this->channels = _x_ao_mode2channels(mode); /* FIXME: Handle all desired output formats */ if ((capabilities & AO_CAP_MODE_5_1CHANNEL) && (capabilities & AO_CAP_FLOAT32)) { @@ -181,7 +185,7 @@ static int upmix_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, } pthread_mutex_lock (&this->lock); - this->sub = xine_xmalloc(sizeof(af_sub_t)); + this->sub = calloc(1, sizeof(af_sub_t)); if (!this->sub) { pthread_mutex_unlock (&this->lock); return 0; @@ -228,7 +232,7 @@ static int upmix_frames_2to51_any_to_float( uint8_t *dst8, uint8_t *src8, int nu float right; float sum; int frame; - int src_units_per_sample=1; + int src_units_per_sample=1; if (step_channel_in == 3) src_units_per_sample=step_channel_in; /* Special handling for 24 bit 3byte input */ for (frame=0;frame < num_frames; frame++) { @@ -293,9 +297,9 @@ static int upmix_frames_2to51_any_to_float( uint8_t *dst8, uint8_t *src8, int nu return frame; } -static void upmix_port_put_buffer (xine_audio_port_t *port_gen, +static void upmix_port_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_upmix_t *this = (post_plugin_upmix_t *)port->post; int src_step_frame; @@ -311,7 +315,7 @@ static void upmix_port_put_buffer (xine_audio_port_t *port_gen, if ((this->channels==2) && (this->channels_out==6)) { while (num_frames_processed < buf->num_frames) { - this->buf = port->original_port->get_buffer(port->original_port); + this->buf = port->original_port->get_buffer(port->original_port); /* this->buf->num_frames is handled after the upmix */ this->buf->vpts = buf->vpts; if (num_frames_processed != 0) this->buf->vpts = 0; @@ -323,7 +327,7 @@ static void upmix_port_put_buffer (xine_audio_port_t *port_gen, this->buf->format.bits = 32; /* Upmix to floats */ this->buf->format.rate = port->rate; this->buf->format.mode = AO_CAP_MODE_5_1CHANNEL; - _x_extra_info_merge( this->buf->extra_info, buf->extra_info); + _x_extra_info_merge( this->buf->extra_info, buf->extra_info); step_channel_in = port->bits>>3; step_channel_out = this->buf->format.bits>>3; dst_step_frame = this->channels_out*step_channel_out; @@ -349,18 +353,18 @@ static void upmix_port_put_buffer (xine_audio_port_t *port_gen, } } pthread_mutex_unlock (&this->lock); - + num_frames_done = upmix_frames_2to51_any_to_float(data8dst, data8src, num_frames, step_channel_in, this->sub); this->buf->num_frames = num_frames_done; num_frames_processed+= num_frames_done; /* pass data to original port */ - port->original_port->put_buffer(port->original_port, this->buf, stream ); + port->original_port->put_buffer(port->original_port, this->buf, stream ); } /* free data from origial buffer */ buf->num_frames=0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ } - port->original_port->put_buffer(port->original_port, buf, stream ); - + port->original_port->put_buffer(port->original_port, buf, stream ); + return; } @@ -379,21 +383,21 @@ static post_plugin_t *upmix_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_upmix_t *this = (post_plugin_upmix_t *)xine_xmalloc(sizeof(post_plugin_upmix_t)); + post_plugin_upmix_t *this = calloc(1, sizeof(post_plugin_upmix_t)); post_in_t *input; post_out_t *output; xine_post_in_t *input_api; post_audio_port_t *port; - + if (!this || !audio_target || !audio_target[0] ) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); this->params.cut_off_freq = 100; - + port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output); port->new_port.open = upmix_port_open; #if 0 @@ -433,16 +437,16 @@ static void upmix_class_dispose(post_class_t *class_gen) void *upmix_init_plugin(xine_t *xine, void *data) { post_class_upmix_t *class = (post_class_upmix_t *)malloc(sizeof(post_class_upmix_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = upmix_open_plugin; class->post_class.get_identifier = upmix_get_identifier; class->post_class.get_description = upmix_get_description; class->post_class.dispose = upmix_class_dispose; - + class->xine = xine; - + return class; } diff --git a/src/post/audio/upmix_mono.c b/src/post/audio/upmix_mono.c index 195831123..43fe3df0d 100644 --- a/src/post/audio/upmix_mono.c +++ b/src/post/audio/upmix_mono.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -23,6 +23,10 @@ * It simply converts Mono into Stereo. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #define LOG_MODULE "upmix_mono" @@ -64,11 +68,11 @@ struct post_plugin_upmix_mono_s { /* private data */ int channels; - + upmix_mono_parameters_t params; xine_post_in_t params_input; int params_changed; - + pthread_mutex_t lock; }; @@ -130,7 +134,7 @@ static int upmix_mono_port_open(xine_audio_port_t *port_gen, xine_stream_t *stre _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; @@ -138,7 +142,7 @@ static int upmix_mono_port_open(xine_audio_port_t *port_gen, xine_stream_t *stre this->channels = _x_ao_mode2channels(mode); capabilities = port->original_port->get_capabilities(port->original_port); - + if (this->channels == 1 && (capabilities & AO_CAP_MODE_STEREO)) { xprintf(stream->xine, XINE_VERBOSITY_LOG, _(LOG_MODULE ": upmixing Mono to Stereo.\n")); @@ -147,7 +151,7 @@ static int upmix_mono_port_open(xine_audio_port_t *port_gen, xine_stream_t *stre if ( this->channels != 1) xprintf(stream->xine, XINE_VERBOSITY_LOG, ngettext(LOG_MODULE ": upmixing a single channel from original %d channel stream.\n", - LOG_MODULE ": upmixing a single channel from original %d channels stream.\n", + LOG_MODULE ": upmixing a single channel from original %d channels stream.\n", this->channels), this->channels); else { xprintf(stream->xine, XINE_VERBOSITY_LOG, @@ -159,15 +163,15 @@ static int upmix_mono_port_open(xine_audio_port_t *port_gen, xine_stream_t *stre return (port->original_port->open) (port->original_port, stream, bits, rate, mode); } -static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen, +static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)port->post; - + pthread_mutex_lock (&this->lock); - if (this->channels == 1) + if (this->channels == 1) { audio_buffer_t *buf0 = port->original_port->get_buffer(port->original_port); audio_buffer_t *buf1 = port->original_port->get_buffer(port->original_port); @@ -192,32 +196,32 @@ static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen, _x_extra_info_merge(buf1->extra_info, buf->extra_info); { - int step = buf->format.bits / 8; + const size_t step = buf->format.bits / 8; uint8_t *src = (uint8_t *)buf->mem; uint8_t *dst0 = (uint8_t *)buf0->mem; uint8_t *dst1 = (uint8_t *)buf1->mem; - int i, k; + int i; for (i = 0; i < buf->num_frames / 2; i++) { - for (k = 0; k < step; k++) - *dst0++ = *src++; + memcpy(dst0, src, step); + dst0 += step; - src -= step; + memcpy(dst0, src, step); + dst0 += step; - for (k = 0; k < step; k++) - *dst0++ = *src++; + src += step; } for (i = buf->num_frames / 2; i < buf->num_frames; i++) { - for (k = 0; k < step; k++) - *dst1++ = *src++; + memcpy(dst1, src, step); + dst1 += step; - src -= step; + memcpy(dst1, src, step); + dst1 += step; - for (k = 0; k < step; k++) - *dst1++ = *src++; + src += step; } } @@ -228,7 +232,7 @@ static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen, /* free data from origial buffer */ buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ } - else if (this->channels && this->params.channel >= 0) + else if (this->channels && this->params.channel >= 0) { audio_buffer_t *buf0 = port->original_port->get_buffer(port->original_port); buf0->num_frames = buf->num_frames; @@ -244,23 +248,23 @@ static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen, _x_extra_info_merge(buf0->extra_info, buf->extra_info); { - int step = buf->format.bits / 8; + const size_t step = buf->format.bits / 8; uint8_t *src = (uint8_t *)buf->mem; uint8_t *dst0 = (uint8_t *)buf0->mem; int cur_channel = this->params.channel; - int i, j, k; - + int i, j; + if( cur_channel >= this->channels ) cur_channel = this->channels-1; src += cur_channel * step; - + for (i = 0; i < buf->num_frames; i++) { for (j = 0; j < this->channels; j++ ) { - for (k = 0; k < step; k++) - *dst0++ = *(src+k); + memcpy(dst0, src, step); + dst0 += step; } src += this->channels * step; } @@ -272,11 +276,11 @@ static void upmix_mono_port_put_buffer(xine_audio_port_t *port_gen, /* free data from origial buffer */ buf->num_frames = 0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */ } - + pthread_mutex_unlock (&this->lock); - + port->original_port->put_buffer(port->original_port, buf, stream); - + return; } @@ -293,30 +297,30 @@ static post_plugin_t *upmix_mono_open_plugin(post_class_t *class_gen, int inputs xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_upmix_mono_t *this = (post_plugin_upmix_mono_t *)xine_xmalloc(sizeof(post_plugin_upmix_mono_t)); + post_plugin_upmix_mono_t *this = calloc(1, sizeof(post_plugin_upmix_mono_t)); post_in_t *input; post_out_t *output; xine_post_in_t *input_api; post_audio_port_t *port; upmix_mono_parameters_t init_params; - + if (!this || !audio_target || !audio_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); init_params.channel = -1; - + pthread_mutex_init (&this->lock, NULL); set_parameters ((xine_post_t *)&this->post, &init_params); - + port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output); port->new_port.open = upmix_mono_port_open; port->new_port.put_buffer = upmix_mono_port_put_buffer; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -348,17 +352,17 @@ static void upmix_mono_class_dispose(post_class_t *class_gen) void *upmix_mono_init_plugin(xine_t *xine, void *data) { post_class_upmix_mono_t *class = (post_class_upmix_mono_t *)malloc(sizeof(post_class_upmix_mono_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = upmix_mono_open_plugin; class->post_class.get_identifier = upmix_mono_get_identifier; class->post_class.get_description = upmix_mono_get_description; class->post_class.dispose = upmix_mono_class_dispose; - + class->xine = xine; - + return class; } diff --git a/src/post/audio/volnorm.c b/src/post/audio/volnorm.c index 783c1e26d..945fd2505 100644 --- a/src/post/audio/volnorm.c +++ b/src/post/audio/volnorm.c @@ -1,27 +1,31 @@ /* - * Copyright (C) 2000-2005 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * Volume normalization audio filter for xine. Ported by Jason Tackaberry - * from MPlayer's af_volnorm, which is copyright 2004 by Alex Beregszaszi + * from MPlayer's af_volnorm, which is copyright 2004 by Alex Beregszaszi * & Pierre Lombard. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <math.h> @@ -113,7 +117,7 @@ struct post_plugin_volnorm_s { /************************************************************************** * volnorm parameters functions *************************************************************************/ -static int set_parameters (xine_post_t *this_gen, void *param_gen) +static int set_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_volnorm_t *this = (post_plugin_volnorm_t *)this_gen; volnorm_parameters_t *param = (volnorm_parameters_t *)param_gen; @@ -125,7 +129,7 @@ static int set_parameters (xine_post_t *this_gen, void *param_gen) return 1; } -static int get_parameters (xine_post_t *this_gen, void *param_gen) +static int get_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_volnorm_t *this = (post_plugin_volnorm_t *)this_gen; volnorm_parameters_t *param = (volnorm_parameters_t *)param_gen; @@ -137,12 +141,12 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) return 1; } -static xine_post_api_descr_t * get_param_descr (void) +static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } -static char * get_help (void) +static char * get_help (void) { return _("Normalizes audio by maximizing the volume without distorting " "the sound.\n" @@ -168,14 +172,14 @@ static xine_post_api_t post_api = { *************************************************************************/ static int volnorm_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, - uint32_t bits, uint32_t rate, int mode) + uint32_t bits, uint32_t rate, int mode) { post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_volnorm_t *this = (post_plugin_volnorm_t *)port->post; _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; @@ -369,10 +373,10 @@ static void method2_float(post_plugin_volnorm_t *this, audio_buffer_t *buf) } -static void volnorm_port_put_buffer (xine_audio_port_t *port_gen, - audio_buffer_t *buf, xine_stream_t *stream) +static void volnorm_port_put_buffer (xine_audio_port_t *port_gen, + audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_volnorm_t *this = (post_plugin_volnorm_t *)port->post; @@ -387,8 +391,8 @@ static void volnorm_port_put_buffer (xine_audio_port_t *port_gen, else if (buf->format.bits == 32) method2_float(this, buf); } - port->original_port->put_buffer(port->original_port, buf, stream ); - + port->original_port->put_buffer(port->original_port, buf, stream ); + return; } @@ -407,18 +411,17 @@ static post_plugin_t *volnorm_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_volnorm_t *this = (post_plugin_volnorm_t *)xine_xmalloc(sizeof(post_plugin_volnorm_t)); + post_plugin_volnorm_t *this = calloc(1, sizeof(post_plugin_volnorm_t)); post_in_t *input; post_out_t *output; xine_post_in_t *input_api; post_audio_port_t *port; - int i; - + if (!this || !audio_target || !audio_target[0] ) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); pthread_mutex_init (&this->lock, NULL); @@ -426,9 +429,8 @@ static post_plugin_t *volnorm_open_plugin(post_class_t *class_gen, int inputs, this->mul = MUL_INIT; this->lastavg = MID_S16; this->idx = 0; - for (i = 0; i < NSAMPLES; i++) - this->mem[i].len = this->mem[i].avg = 0; - + memset(this->mem, 0, sizeof(this->mem)); + port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output); port->new_port.open = volnorm_port_open; port->new_port.close = volnorm_port_close; @@ -466,16 +468,16 @@ static void volnorm_class_dispose(post_class_t *class_gen) void *volnorm_init_plugin(xine_t *xine, void *data) { post_class_volnorm_t *class = (post_class_volnorm_t *)malloc(sizeof(post_class_volnorm_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = volnorm_open_plugin; class->post_class.get_identifier = volnorm_get_identifier; class->post_class.get_description = volnorm_get_description; class->post_class.dispose = volnorm_class_dispose; - + class->xine = xine; - + return class; } diff --git a/src/post/audio/window.c b/src/post/audio/window.c index fdea90590..ca58152d5 100644 --- a/src/post/audio/window.c +++ b/src/post/audio/window.c @@ -1,5 +1,5 @@ /*============================================================================= - * + * * This software has been released under the terms of the GNU Public * license. See http://www.gnu.org/copyleft/gpl.html for details. * @@ -39,7 +39,7 @@ void boxcar(int n, _ftype_t* w) /* * Triang a.k.a Bartlett * - * | (N-1)| + * | (N-1)| * 2 * |k - -----| * | 2 | * w = 1.0 - --------------- @@ -53,7 +53,7 @@ void triang(int n, _ftype_t* w) _ftype_t k2 = 1/((_ftype_t)n + k1); int end = (n + 1) >> 1; int i; - + /* Calculate window coefficients */ for (i=0 ; i<end ; i++) w[i] = w[n-i-1] = (2.0*((_ftype_t)(i+1))-(1.0-k1))*k2; @@ -72,7 +72,7 @@ void hanning(int n, _ftype_t* w) { int i; _ftype_t k = 2*M_PI/((_ftype_t)(n+1)); /* 2*pi/(N+1) */ - + /* Calculate window coefficients */ for (i=0; i<n; i++) *w++ = 0.5*(1.0 - cos(k*(_ftype_t)(i+1))); @@ -131,22 +131,22 @@ void flattop(int n,_ftype_t* w) int i; _ftype_t k1 = 2*M_PI/((_ftype_t)(n-1)); /* 2*pi/(N-1) */ _ftype_t k2 = 2*k1; /* 4*pi/(N-1) */ - + /* Calculate window coefficients */ for (i=0; i<n; i++) *w++ = 0.2810638602 - 0.5208971735*cos(k1*(_ftype_t)i) + 0.1980389663*cos(k2*(_ftype_t)i); } -/* Computes the 0th order modified Bessel function of the first kind. - * (Needed to compute Kaiser window) - * +/* Computes the 0th order modified Bessel function of the first kind. + * (Needed to compute Kaiser window) + * * y = sum( (x/(2*n))^2 ) * n */ #define BIZ_EPSILON 1E-21 /* Max error acceptable */ static _ftype_t besselizero(_ftype_t x) -{ +{ _ftype_t temp; _ftype_t sum = 1.0; _ftype_t u = 1.0; @@ -175,10 +175,10 @@ static _ftype_t besselizero(_ftype_t x) * Gold (Theory and Application of DSP) under Kaiser windows for more * about Beta. The following table from Rabiner and Gold gives some * feel for the effect of Beta: - * + * * All ripples in dB, width of transition band = D*N where N = window * length - * + * * BETA D PB RIP SB RIP * 2.120 1.50 +-0.27 -30 * 3.384 2.23 0.0864 -40 @@ -195,8 +195,8 @@ void kaiser(int n, _ftype_t* w, _ftype_t b) _ftype_t k1 = 1.0/besselizero(b); int k2 = 1 - (n & 1); int end = (n + 1) >> 1; - int i; - + int i; + /* Calculate window coefficients */ for (i=0 ; i<end ; i++){ tmp = (_ftype_t)(2*i + k2) / ((_ftype_t)n - 1.0); diff --git a/src/post/audio/window.h b/src/post/audio/window.h index d0a7446eb..638707809 100644 --- a/src/post/audio/window.h +++ b/src/post/audio/window.h @@ -1,5 +1,5 @@ /*============================================================================= - * + * * This software has been released under the terms of the GNU Public * license. See http://www.gnu.org/copyleft/gpl.html for details. * diff --git a/src/post/deinterlace/Makefile.am b/src/post/deinterlace/Makefile.am index d382a2e98..bf5b281a8 100644 --- a/src/post/deinterlace/Makefile.am +++ b/src/post/deinterlace/Makefile.am @@ -1,14 +1,15 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common SUBDIRS = plugins -EXTRA_DIST = +EXTRA_DIST = xinepost_LTLIBRARIES = xineplug_post_tvtime.la xineplug_post_tvtime_la_SOURCES = xine_plugin.c \ - deinterlace.c pulldown.c speedy.c tvtime.c -xineplug_post_tvtime_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) \ + deinterlace.c pulldown.c speedy.c tvtime.c +xineplug_post_tvtime_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) $(PTHREAD_LIBS) \ $(top_builddir)/src/post/deinterlace/plugins/libdeinterlaceplugins.la xineplug_post_tvtime_la_CFLAGS = $(VISIBILITY_FLAG) diff --git a/src/post/deinterlace/plugins/Makefile.am b/src/post/deinterlace/plugins/Makefile.am index 17d170127..5f0997eb8 100644 --- a/src/post/deinterlace/plugins/Makefile.am +++ b/src/post/deinterlace/plugins/Makefile.am @@ -30,7 +30,10 @@ EXTRA_DIST = greedy2frame_template.c greedyh.asm \ # libpostproc is here so we can use their nice mangle.h AM_CFLAGS = -I$(top_srcdir)/src/post/deinterlace \ - -I$(top_srcdir)/src/libffmpeg/libavcodec/libpostproc + -I$(top_srcdir)/src/xine-utils + +# Avoid "can't find register" failures with -O0, -O2, -O3 (gcc 4.0) +libdeinterlaceplugins_la-kdetv_greedyh.o libdeinterlaceplugins_la-kdetv_greedyh.lo: CFLAGS=$(shell echo @CFLAGS@ | sed -e 's/$$/ -O1/') noinst_LTLIBRARIES = libdeinterlaceplugins.la @@ -45,7 +48,6 @@ libdeinterlaceplugins_la_SOURCES = \ scalerbob.c \ kdetv_greedyh.c \ kdetv_tomsmocomp.c -libdeinterlaceplugins_la_LIBADD = $(XINE_LIB) libdeinterlaceplugins_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) libdeinterlaceplugins_la_LDFLAGS = -avoid-version -module diff --git a/src/post/deinterlace/plugins/greedy.c b/src/post/deinterlace/plugins/greedy.c index b5fcad3e5..925779224 100644 --- a/src/post/deinterlace/plugins/greedy.c +++ b/src/post/deinterlace/plugins/greedy.c @@ -48,7 +48,7 @@ // upon which give the smaller comb factor, and then clip to avoid large damage // when wrong. // -// I'd intended this to be part of a larger more elaborate method added to +// I'd intended this to be part of a larger more elaborate method added to // Blended Clip but this give too good results for the CPU to ignore here. static void copy_scanline( uint8_t *output, @@ -134,7 +134,7 @@ static void deinterlace_greedy_packed422_scanline_mmxext( uint8_t *output, paddusb_r2r( mm3, mm2 ); // now = Max(L1,L3) pcmpeqb_r2r( mm7, mm7 ); // all ffffffff - psubusb_r2r( mm1, mm7 ); // - L1 + psubusb_r2r( mm1, mm7 ); // - L1 paddusb_r2r( mm7, mm3 ); // add, may sat at fff.. psubusb_r2r( mm7, mm3 ); // now = Min(L1,L3) @@ -146,7 +146,7 @@ static void deinterlace_greedy_packed422_scanline_mmxext( uint8_t *output, paddusb_r2r( mm3, mm4 ); // now = Max(best,Min(L1,L3) pcmpeqb_r2r( mm7, mm7 ); // all ffffffff - psubusb_r2r( mm4, mm7 ); // - Max(best,Min(best,L3) + psubusb_r2r( mm4, mm7 ); // - Max(best,Min(best,L3) paddusb_r2r( mm7, mm2 ); // add may sat at FFF.. psubusb_r2r( mm7, mm2 ); // now = Min( Max(best, Min(L1,L3), L2 )=L2 clipped diff --git a/src/post/deinterlace/plugins/greedy2frame_template.c b/src/post/deinterlace/plugins/greedy2frame_template.c index 1067e2cb8..7fe52519f 100644 --- a/src/post/deinterlace/plugins/greedy2frame_template.c +++ b/src/post/deinterlace/plugins/greedy2frame_template.c @@ -79,9 +79,9 @@ /**************************************************************************** ** Field 1 | Field 2 | Field 3 | Field 4 | -** T0 | | T1 | | -** | M0 | | M1 | -** B0 | | B1 | | +** T0 | | T1 | | +** | M0 | | M1 | +** B0 | | B1 | | */ @@ -95,15 +95,15 @@ #define MASKS_DEFINED static const int64_t __attribute__((__used__)) YMask = 0x00ff00ff00ff00ffll; static const int64_t __attribute__((__used__)) Mask = 0x7f7f7f7f7f7f7f7fll; - static const int64_t __attribute__((__used__)) DwordOne = 0x0000000100000001ll; - static const int64_t __attribute__((__used__)) DwordTwo = 0x0000000200000002ll; + static const int64_t __attribute__((__used__)) DwordOne = 0x0000000100000001ll; + static const int64_t __attribute__((__used__)) DwordTwo = 0x0000000200000002ll; static int64_t qwGreedyTwoFrameThreshold; #endif #include <mangle.h> #if defined(IS_SSE) -static void DeinterlaceGreedy2Frame_SSE(uint8_t *output, int outstride, +static void DeinterlaceGreedy2Frame_SSE(uint8_t *output, int outstride, deinterlace_frame_data_t *data, int bottom_field, int second_field, int width, int height ) #elif defined(IS_3DNOW) @@ -135,7 +135,7 @@ static void DeinterlaceGreedy2Frame_MMX(uint8_t *output, int outstride, qwGreedyTwoFrameThreshold = GreedyTwoFrameThreshold; qwGreedyTwoFrameThreshold += (GreedyTwoFrameThreshold2 << 8); qwGreedyTwoFrameThreshold += (qwGreedyTwoFrameThreshold << 48) + - (qwGreedyTwoFrameThreshold << 32) + + (qwGreedyTwoFrameThreshold << 32) + (qwGreedyTwoFrameThreshold << 16); @@ -150,7 +150,7 @@ static void DeinterlaceGreedy2Frame_MMX(uint8_t *output, int outstride, M0 = data->f1; T0 = data->f2; } - + if( bottom_field ) { M1 += stride; T1 += 0; @@ -194,9 +194,9 @@ static void DeinterlaceGreedy2Frame_MMX(uint8_t *output, int outstride, "movq %2, %%mm3 \n\t" // B1 "movq %3, %%mm2 \n\t" // M0 : /* no output */ - : "m" (*T1), "m" (*M1), + : "m" (*T1), "m" (*M1), "m" (*B1), "m" (*M0), "m" (Mask) ); - + asm volatile( /* Figure out what to do with the scanline above the one we just copied. @@ -271,7 +271,7 @@ static void DeinterlaceGreedy2Frame_MMX(uint8_t *output, int outstride, "pcmpgtb %3, %%mm5 \n\t" "pand %%mm6, %%mm5 \n\t" /* get rid of sign bit */ - "pcmpgtd %5, %%mm5 \n\t" + "pcmpgtd %5, %%mm5 \n\t" "pandn %5, %%mm5 \n\t" "paddd %%mm5, %%mm4 \n\t" @@ -307,9 +307,9 @@ static void DeinterlaceGreedy2Frame_MMX(uint8_t *output, int outstride, "movq %%mm4, %%mm5 \n\t" /* mm4 now is 1 where we want to weave and 0 where we want to bob */ - "pand %%mm0, %%mm4 \n\t" - "pandn %%mm7, %%mm5 \n\t" - "por %%mm5, %%mm4 \n\t" + "pand %%mm0, %%mm4 \n\t" + "pandn %%mm7, %%mm5 \n\t" + "por %%mm5, %%mm4 \n\t" #ifdef IS_SSE "movntq %%mm4, %0 \n\t" #else @@ -353,9 +353,9 @@ static void DeinterlaceGreedy2Frame_MMX(uint8_t *output, int outstride, } else { - xine_fast_memcpy(Dest, T1, stride); + xine_fast_memcpy(Dest, T1, stride); } - + /* clear out the MMX registers ready for doing floating point again */ asm("emms\n\t"); #endif diff --git a/src/post/deinterlace/plugins/greedyhmacros.h b/src/post/deinterlace/plugins/greedyhmacros.h index 5f65959c3..fd1eb2068 100644 --- a/src/post/deinterlace/plugins/greedyhmacros.h +++ b/src/post/deinterlace/plugins/greedyhmacros.h @@ -15,7 +15,7 @@ // ///////////////////////////////////////////////////////////////////////////// -// Define a few macros for CPU dependent instructions. +// Define a few macros for CPU dependent instructions. // I suspect I don't really understand how the C macro preprocessor works but // this seems to get the job done. // TRB 7/01 @@ -35,9 +35,9 @@ "paddusb "mmrw", "mmr1"\n\t" #define V_PAVGB_SSE(mmr1, mmr2, mmrw, smask) "pavgb "mmr2", "mmr1"\n\t" #define V_PAVGB_3DNOW(mmr1, mmr2, mmrw, smask) "pavgusb "mmr2", "mmr1"\n\t" -#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SSE_TYPE) -#define V_PAVGB2(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) -#define V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB_##ssetyp(mmr1, mmr2, mmrw, smask) +#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SSE_TYPE) +#define V_PAVGB2(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) +#define V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB_##ssetyp(mmr1, mmr2, mmrw, smask) // some macros for pmaxub instruction #define V_PMAXUB_MMX(mmr1, mmr2) \ @@ -45,9 +45,9 @@ "paddusb "mmr2", "mmr1"\n\t" #define V_PMAXUB_SSE(mmr1, mmr2) "pmaxub "mmr2", "mmr1"\n\t" #define V_PMAXUB_3DNOW(mmr1, mmr2) V_PMAXUB_MMX(mmr1, mmr2) // use MMX version -#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SSE_TYPE) -#define V_PMAXUB2(mmr1, mmr2, ssetyp) V_PMAXUB3(mmr1, mmr2, ssetyp) -#define V_PMAXUB3(mmr1, mmr2, ssetyp) V_PMAXUB_##ssetyp(mmr1, mmr2) +#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SSE_TYPE) +#define V_PMAXUB2(mmr1, mmr2, ssetyp) V_PMAXUB3(mmr1, mmr2, ssetyp) +#define V_PMAXUB3(mmr1, mmr2, ssetyp) V_PMAXUB_##ssetyp(mmr1, mmr2) // some macros for pminub instruction // V_PMINUB(mmr1, mmr2, mmr work register) mmr2 may NOT = mmrw @@ -58,17 +58,17 @@ "psubusb "mmrw", "mmr1"\n\t" #define V_PMINUB_SSE(mmr1, mmr2, mmrw) "pminub "mmr2", "mmr1"\n\t" #define V_PMINUB_3DNOW(mmr1, mmr2, mmrw) V_PMINUB_MMX(mmr1, mmr2, mmrw) // use MMX version -#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SSE_TYPE) -#define V_PMINUB2(mmr1, mmr2, mmrw, ssetyp) V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) -#define V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) V_PMINUB_##ssetyp(mmr1, mmr2, mmrw) +#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SSE_TYPE) +#define V_PMINUB2(mmr1, mmr2, mmrw, ssetyp) V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) +#define V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) V_PMINUB_##ssetyp(mmr1, mmr2, mmrw) // some macros for movntq instruction -// V_MOVNTQ(mmr1, mmr2) +// V_MOVNTQ(mmr1, mmr2) #define V_MOVNTQ_MMX(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" #define V_MOVNTQ_3DNOW(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" #define V_MOVNTQ_SSE(mmr1, mmr2) "movntq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SSE_TYPE) -#define V_MOVNTQ2(mmr1, mmr2, ssetyp) V_MOVNTQ3(mmr1, mmr2, ssetyp) +#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SSE_TYPE) +#define V_MOVNTQ2(mmr1, mmr2, ssetyp) V_MOVNTQ3(mmr1, mmr2, ssetyp) #define V_MOVNTQ3(mmr1, mmr2, ssetyp) V_MOVNTQ_##ssetyp(mmr1, mmr2) // end of macros diff --git a/src/post/deinterlace/plugins/linearblend.c b/src/post/deinterlace/plugins/linearblend.c index 96e56063f..c594f41dd 100644 --- a/src/post/deinterlace/plugins/linearblend.c +++ b/src/post/deinterlace/plugins/linearblend.c @@ -254,7 +254,7 @@ static void deinterlace_scanline_linear_blend2_mmxext( uint8_t *output, uint8_t *b1 = data->b1; int i; - + READ_PREFETCH_2048( t1 ); READ_PREFETCH_2048( b1 ); READ_PREFETCH_2048( m0 ); diff --git a/src/post/deinterlace/plugins/tomsmocomp/tomsmocompmacros.h b/src/post/deinterlace/plugins/tomsmocomp/tomsmocompmacros.h index a3b92a51c..875ed7055 100644 --- a/src/post/deinterlace/plugins/tomsmocomp/tomsmocompmacros.h +++ b/src/post/deinterlace/plugins/tomsmocomp/tomsmocompmacros.h @@ -2,11 +2,13 @@ #include <math.h> #include <stdlib.h> +#include "mangle.h" + #define USE_FOR_DSCALER #define MyMemCopy xine_fast_memcpy -// Define a few macros for CPU dependent instructions. +// Define a few macros for CPU dependent instructions. // I suspect I don't really understand how the C macro preprocessor works but // this seems to get the job done. // TRB 7/01 @@ -26,9 +28,9 @@ "paddusb "mmrw", "mmr1"\n\t" #define V_PAVGB_SSE(mmr1, mmr2, mmrw, smask) "pavgb "mmr2", "mmr1"\n\t" #define V_PAVGB_3DNOW(mmr1, mmr2, mmrw, smask) "pavgusb "mmr2", "mmr1"\n\t" -#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SSE_TYPE) -#define V_PAVGB2(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) -#define V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB_##ssetyp(mmr1, mmr2, mmrw, smask) +#define V_PAVGB(mmr1, mmr2, mmrw, smask) V_PAVGB2(mmr1, mmr2, mmrw, smask, SSE_TYPE) +#define V_PAVGB2(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) +#define V_PAVGB3(mmr1, mmr2, mmrw, smask, ssetyp) V_PAVGB_##ssetyp(mmr1, mmr2, mmrw, smask) // some macros for pmaxub instruction #define V_PMAXUB_MMX(mmr1, mmr2) \ @@ -36,9 +38,9 @@ "paddusb "mmr2", "mmr1"\n\t" #define V_PMAXUB_SSE(mmr1, mmr2) "pmaxub "mmr2", "mmr1"\n\t" #define V_PMAXUB_3DNOW(mmr1, mmr2) V_PMAXUB_MMX(mmr1, mmr2) // use MMX version -#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SSE_TYPE) -#define V_PMAXUB2(mmr1, mmr2, ssetyp) V_PMAXUB3(mmr1, mmr2, ssetyp) -#define V_PMAXUB3(mmr1, mmr2, ssetyp) V_PMAXUB_##ssetyp(mmr1, mmr2) +#define V_PMAXUB(mmr1, mmr2) V_PMAXUB2(mmr1, mmr2, SSE_TYPE) +#define V_PMAXUB2(mmr1, mmr2, ssetyp) V_PMAXUB3(mmr1, mmr2, ssetyp) +#define V_PMAXUB3(mmr1, mmr2, ssetyp) V_PMAXUB_##ssetyp(mmr1, mmr2) // some macros for pminub instruction // V_PMINUB(mmr1, mmr2, mmr work register) mmr2 may NOT = mmrw @@ -49,17 +51,17 @@ "psubusb "mmrw", "mmr1"\n\t" #define V_PMINUB_SSE(mmr1, mmr2, mmrw) "pminub "mmr2", "mmr1"\n\t" #define V_PMINUB_3DNOW(mmr1, mmr2, mmrw) V_PMINUB_MMX(mmr1, mmr2, mmrw) // use MMX version -#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SSE_TYPE) -#define V_PMINUB2(mmr1, mmr2, mmrw, ssetyp) V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) -#define V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) V_PMINUB_##ssetyp(mmr1, mmr2, mmrw) +#define V_PMINUB(mmr1, mmr2, mmrw) V_PMINUB2(mmr1, mmr2, mmrw, SSE_TYPE) +#define V_PMINUB2(mmr1, mmr2, mmrw, ssetyp) V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) +#define V_PMINUB3(mmr1, mmr2, mmrw, ssetyp) V_PMINUB_##ssetyp(mmr1, mmr2, mmrw) // some macros for movntq instruction -// V_MOVNTQ(mmr1, mmr2) +// V_MOVNTQ(mmr1, mmr2) #define V_MOVNTQ_MMX(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" #define V_MOVNTQ_3DNOW(mmr1, mmr2) "movq "mmr2", "mmr1"\n\t" #define V_MOVNTQ_SSE(mmr1, mmr2) "movntq "mmr2", "mmr1"\n\t" -#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SSE_TYPE) -#define V_MOVNTQ2(mmr1, mmr2, ssetyp) V_MOVNTQ3(mmr1, mmr2, ssetyp) +#define V_MOVNTQ(mmr1, mmr2) V_MOVNTQ2(mmr1, mmr2, SSE_TYPE) +#define V_MOVNTQ2(mmr1, mmr2, ssetyp) V_MOVNTQ3(mmr1, mmr2, ssetyp) #define V_MOVNTQ3(mmr1, mmr2, ssetyp) V_MOVNTQ_##ssetyp(mmr1, mmr2) // end of macros diff --git a/src/post/deinterlace/pulldown.c b/src/post/deinterlace/pulldown.c index 4f6247444..2218855f0 100644 --- a/src/post/deinterlace/pulldown.c +++ b/src/post/deinterlace/pulldown.c @@ -47,7 +47,7 @@ * Bot 2 : Drop * Top 3 : Merge * Bot 3 : Drop - * Top 4 : Show + * Top 4 : Show * Bot 4 : Drop * Top 5 : Drop * Bot 5 : Show @@ -69,15 +69,15 @@ * * [ ] * [ * *] | 0 top BC - * [* * ] | 1 BC bottom BC + * [* * ] | 1 BC bottom BC * * [ ] * [ * *] | 0 top CC - * [ * *] | 0 CC bottom CC + * [ * *] | 0 CC bottom CC * * [ ] * [* * ] | 1 top DD - * [ * *] | 0 DD bottom DD + * [ * *] | 0 DD bottom DD * * * [* * ] | 1 top AA @@ -608,7 +608,7 @@ int pulldown_drop( int action, int bottom_field ) if( action == PULLDOWN_SEQ_CC && !bottom_field ) ret = 0; if( action == PULLDOWN_SEQ_DD && bottom_field ) - ret = 0; + ret = 0; return ret; } diff --git a/src/post/deinterlace/speedy.c b/src/post/deinterlace/speedy.c index a980780d7..32c8b03e3 100644 --- a/src/post/deinterlace/speedy.c +++ b/src/post/deinterlace/speedy.c @@ -116,11 +116,11 @@ void (*composite_bars_packed4444_scanline)( uint8_t *output, uint8_t *background, int width, int a, int luma, int cb, int cr, int percentage ); -void (*packed444_to_nonpremultiplied_packed4444_scanline)( uint8_t *output, +void (*packed444_to_nonpremultiplied_packed4444_scanline)( uint8_t *output, uint8_t *input, int width, int alpha ); void (*aspect_adjust_packed4444_scanline)( uint8_t *output, - uint8_t *input, + uint8_t *input, int width, double pixel_aspect ); void (*packed444_to_packed422_scanline)( uint8_t *output, @@ -622,7 +622,7 @@ static void vfilter_chroma_121_packed422_scanline_mmx( uint8_t *output, int widt paddw_r2r( mm1, mm2 ); psllw_i2r( 6, mm2 ); - pand_r2r( mm6, mm2 ); + pand_r2r( mm6, mm2 ); por_r2r ( mm3, mm2 ); @@ -637,7 +637,7 @@ static void vfilter_chroma_121_packed422_scanline_mmx( uint8_t *output, int widt *output = (*t + *b + (*m << 1)) >> 2; output+=2; t+=2; b+=2; m+=2; } - + emms(); } #endif @@ -661,7 +661,7 @@ static void vfilter_chroma_332_packed422_scanline_mmx( uint8_t *output, int widt const mmx_t cmask = { 0xff00ff00ff00ff00ULL }; // Get width in bytes. - width *= 2; + width *= 2; i = width / 8; width -= i * 8; @@ -1939,7 +1939,7 @@ static int conv_YR_inited = 0; static int myround(double n) { - if (n >= 0) + if (n >= 0) return (int)(n + 0.5); else return (int)(n - 0.5); @@ -1956,7 +1956,7 @@ static void init_RGB_to_YCbCr_tables(void) * to one of each, add the following: * + (fixed-point-factor / 2) --- for rounding later * + (Q-offset * fixed-point-factor) --- to add the offset - * + * */ for (i = 0; i < 256; i++) { Y_R[i] = myround(0.299 * (double)i * 219.0 / 255.0 * (double)(1<<FP_BITS)); @@ -1988,7 +1988,7 @@ static void init_YCbCr_to_RGB_tables(void) * to one of each, add the following: * + (fixed-point-factor / 2) --- for rounding later * + (Q-offset * fixed-point-factor) --- to add the offset - * + * */ /* clip Y values under 16 */ @@ -2005,7 +2005,7 @@ static void init_YCbCr_to_RGB_tables(void) RGB_Y[i] = myround((1.0 * (double)(235) * 255.0 / 219.0 * (double)(1<<FP_BITS)) + (double)(1<<(FP_BITS-1))); } - + /* clip Cb/Cr values below 16 */ for (i = 0; i < 16; i++) { R_Cr[i] = myround(1.402 * (double)(-112) * 255.0 / 224.0 * (double)(1<<FP_BITS)); @@ -2055,7 +2055,7 @@ static void rgba32_to_packed4444_rec601_scanline_c( uint8_t *output, uint8_t *in int g = input[ 1 ]; int b = input[ 2 ]; int a = input[ 3 ]; - + output[ 0 ] = a; output[ 1 ] = (Y_R[ r ] + Y_G[ g ] + Y_B[ b ]) >> FP_BITS; output[ 2 ] = (Cb_R[ r ] + Cb_G[ g ] + Cb_B[ b ]) >> FP_BITS; @@ -2128,7 +2128,7 @@ static void packed444_to_rgb24_rec601_reference_scanline( uint8_t *output, uint8 } */ -static void packed444_to_nonpremultiplied_packed4444_scanline_c( uint8_t *output, +static void packed444_to_nonpremultiplied_packed4444_scanline_c( uint8_t *output, uint8_t *input, int width, int alpha ) { @@ -2146,7 +2146,7 @@ static void packed444_to_nonpremultiplied_packed4444_scanline_c( uint8_t *output } static void aspect_adjust_packed4444_scanline_c( uint8_t *output, - uint8_t *input, + uint8_t *input, int width, double pixel_aspect ) { @@ -2259,7 +2259,7 @@ static void chroma_422_to_444_mpeg2_plane_c( uint8_t *dst, uint8_t *src, int wid /* odd samples (21 -52 159 159 -52 21) */ dst[ i2 + 1 ] = clip255( ( 21*(src[im2]+src[ip3]) - - 52*(src[im1]+src[ip2]) + - 52*(src[im1]+src[ip2]) + 159*(src[i]+src[ip1]) + 128 ) >> 8 ); } src += w; diff --git a/src/post/deinterlace/speedy.h b/src/post/deinterlace/speedy.h index b4ad56393..55a2a1d5b 100644 --- a/src/post/deinterlace/speedy.h +++ b/src/post/deinterlace/speedy.h @@ -237,7 +237,7 @@ extern void (*subpix_blit_vertical_packed422_scanline)( uint8_t *output, uint8_t * Simple function to convert a 4:4:4 scanline to a 4:4:4:4 scanline by * adding an alpha channel. Result is non-premultiplied. */ -extern void (*packed444_to_nonpremultiplied_packed4444_scanline)( uint8_t *output, +extern void (*packed444_to_nonpremultiplied_packed4444_scanline)( uint8_t *output, uint8_t *input, int width, int alpha ); @@ -248,7 +248,7 @@ extern void (*packed444_to_nonpremultiplied_packed4444_scanline)( uint8_t *outpu * aspect ratio. */ extern void (*aspect_adjust_packed4444_scanline)( uint8_t *output, - uint8_t *input, + uint8_t *input, int width, double pixel_aspect ); diff --git a/src/post/deinterlace/tvtime.c b/src/post/deinterlace/tvtime.c index eff43d5e8..97da6543e 100644 --- a/src/post/deinterlace/tvtime.c +++ b/src/post/deinterlace/tvtime.c @@ -38,14 +38,6 @@ #include "tvtime.h" /** - * This is how many frames to wait until deciding if the pulldown phase - * has changed or if we've really found a pulldown sequence. This is - * currently set to about 1 second, that is, we won't go into film mode - * until we've seen a pulldown sequence successfully for 1 second. - */ -#define PULLDOWN_ERROR_WAIT 60 - -/** * This is how many predictions have to be incorrect before we fall back to * video mode. Right now, if we mess up, we jump to video mode immediately. */ @@ -192,13 +184,13 @@ int tvtime_build_deinterlaced_frame( tvtime_t *tvtime, uint8_t *output, if( !tvtime->pdoffset ) { /* No pulldown offset applies, drop out of pulldown immediately. */ tvtime->pdlastbusted = 0; - tvtime->pderror = PULLDOWN_ERROR_WAIT; + tvtime->pderror = tvtime->pulldown_error_wait; } else if( tvtime->pdoffset != predicted ) { if( tvtime->pdlastbusted ) { tvtime->pdlastbusted--; tvtime->pdoffset = predicted; } else { - tvtime->pderror = PULLDOWN_ERROR_WAIT; + tvtime->pderror = tvtime->pulldown_error_wait; } } else { if( tvtime->pderror ) { @@ -437,7 +429,7 @@ void tvtime_reset_context( tvtime_t *tvtime ) tvtime->last_botdiff = 0; tvtime->pdoffset = PULLDOWN_SEQ_AA; - tvtime->pderror = PULLDOWN_ERROR_WAIT; + tvtime->pderror = tvtime->pulldown_error_wait; tvtime->pdlastbusted = 0; tvtime->filmmode = 0; } diff --git a/src/post/deinterlace/tvtime.h b/src/post/deinterlace/tvtime.h index 8e4c5abc2..22d863a56 100644 --- a/src/post/deinterlace/tvtime.h +++ b/src/post/deinterlace/tvtime.h @@ -56,6 +56,11 @@ typedef struct { */ deinterlace_method_t *curmethod; + /** + * This is how many frames to wait until deciding if the pulldown phase + * has changed or if we've really found a pulldown sequence. + */ + unsigned int pulldown_error_wait; /* internal data */ int last_topdiff; @@ -93,4 +98,4 @@ tvtime_t *tvtime_new_context(void); void tvtime_reset_context( tvtime_t *this ); -#endif +#endif diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c index 477e6812b..d56c54d47 100644 --- a/src/post/deinterlace/xine_plugin.c +++ b/src/post/deinterlace/xine_plugin.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -23,6 +23,10 @@ * heavily based on tvtime.sf.net by Billy Biggs */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define LOG */ @@ -46,7 +50,7 @@ static void *deinterlace_init_plugin(xine_t *xine, void *); static const post_info_t deinterlace_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 9, "tvtime", XINE_VERSION_CODE, &deinterlace_special_info, &deinterlace_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; @@ -62,13 +66,14 @@ static char *enum_framerate[] = { "full", "half_top", "half_bottom", NULL }; static void *help_string; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct deinterlace_parameters_s { int method; int enabled; int pulldown; + int pulldown_error_wait; int framerate_mode; int judder_correction; int use_progressive_frame_flag; @@ -81,13 +86,15 @@ typedef struct deinterlace_parameters_s { * description of params struct */ START_PARAM_DESCR( deinterlace_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_INT, method, enum_methods, 0, 0, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, method, enum_methods, 0, 0, 0, "deinterlace method" ) PARAM_ITEM( POST_PARAM_TYPE_BOOL, enabled, NULL, 0, 1, 0, "enable/disable" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, pulldown, enum_pulldown, 0, 0, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, pulldown, enum_pulldown, 0, 0, 0, "pulldown algorithm" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, framerate_mode, enum_framerate, 0, 0, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, pulldown_error_wait, NULL, 0, 0, 0, + "number of frames of telecine pattern sync required before mode change" ) +PARAM_ITEM( POST_PARAM_TYPE_INT, framerate_mode, enum_framerate, 0, 0, 0, "framerate output mode" ) PARAM_ITEM( POST_PARAM_TYPE_BOOL, judder_correction, NULL, 0, 1, 0, "make frames evenly spaced for film mode (24 fps)" ) @@ -122,7 +129,7 @@ struct post_plugin_deinterlace_s { int tvtime_changed; int tvtime_last_filmmode; int vo_deinterlace_enabled; - + int framecounter; uint8_t rff_pattern; @@ -137,10 +144,10 @@ typedef struct post_class_deinterlace_s { deinterlace_parameters_t init_param; } post_class_deinterlace_t; -static void _flush_frames(post_plugin_deinterlace_t *this) +static void _flush_frames(post_plugin_deinterlace_t *this) { int i; - + for( i = 0; i < NUM_RECENT_FRAMES; i++ ) { if( this->recent_frame[i] ) { this->recent_frame[i]->free(this->recent_frame[i]); @@ -165,6 +172,7 @@ static int set_parameters (xine_post_t *this_gen, void *param_gen) { this->enabled = param->enabled; this->pulldown = param->pulldown; + this->tvtime->pulldown_error_wait = param->pulldown_error_wait; this->framerate_mode = param->framerate_mode; this->judder_correction = param->judder_correction; this->use_progressive_frame_flag = param->use_progressive_frame_flag; @@ -181,10 +189,11 @@ static int set_parameters (xine_post_t *this_gen, void *param_gen) { static int get_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)this_gen; deinterlace_parameters_t *param = (deinterlace_parameters_t *)param_gen; - + param->method = this->cur_method; param->enabled = this->enabled; param->pulldown = this->pulldown; + param->pulldown_error_wait = this->tvtime->pulldown_error_wait; param->framerate_mode = this->framerate_mode; param->judder_correction = this->judder_correction; param->use_progressive_frame_flag = this->use_progressive_frame_flag; @@ -193,7 +202,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } @@ -212,6 +221,9 @@ static char * get_static_help (void) { "\n" " Enabled: Enable/disable the plugin.\n" "\n" + " Pulldown_error_wait: Ensures that the telecine pattern has been " + "locked for this many frames before changing to filmmode.\n" + "\n" " Pulldown: Choose the 2-3 pulldown detection algorithm. 24 FPS films " "that have being converted to NTSC can be detected and intelligently " "reconstructed to their original (non-interlaced) frames.\n" @@ -291,13 +303,13 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) static void *deinterlace_init_plugin(xine_t *xine, void *data) { - post_class_deinterlace_t *class = (post_class_deinterlace_t *)xine_xmalloc(sizeof(post_class_deinterlace_t)); + post_class_deinterlace_t *class = calloc(1, sizeof(post_class_deinterlace_t)); uint32_t config_flags = xine_mm_accel(); int i; if (!class) return NULL; - + class->class.open_plugin = deinterlace_open_plugin; class->class.get_identifier = deinterlace_get_identifier; class->class.get_description = deinterlace_get_description; @@ -319,7 +331,7 @@ static void *deinterlace_init_plugin(xine_t *xine, void *data) filter_deinterlace_methods( config_flags, 5 /*fieldsavailable*/ ); if( !get_num_deinterlace_methods() ) { - xprintf(xine, XINE_VERBOSITY_LOG, + xprintf(xine, XINE_VERBOSITY_LOG, _("tvtime: No deinterlacing methods available, exiting.\n")); return NULL; } @@ -332,7 +344,7 @@ static void *deinterlace_init_plugin(xine_t *xine, void *data) deinterlace_method_t *method; method = get_deinterlace_method(i); - + enum_methods[i+1] = method->short_name; xine_buffer_strcat( help_string, "[" ); xine_buffer_strcat( help_string, method->short_name ); @@ -344,14 +356,15 @@ static void *deinterlace_init_plugin(xine_t *xine, void *data) xine_buffer_strcat( help_string, "\n---\n" ); } enum_methods[i+1] = NULL; - + /* Some default values */ class->init_param.method = 1; /* First (plugin) method available */ class->init_param.enabled = 1; class->init_param.pulldown = 1; /* vektor */ + class->init_param.pulldown_error_wait = 60; /* about one second */ class->init_param.framerate_mode = 0; /* full */ - class->init_param.judder_correction = 1; + class->init_param.judder_correction = 1; class->init_param.use_progressive_frame_flag = 1; class->init_param.chroma_filter = 0; class->init_param.cheap_mode = 0; @@ -364,18 +377,18 @@ static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int input xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)xine_xmalloc(sizeof(post_plugin_deinterlace_t)); + post_plugin_deinterlace_t *this = calloc(1, sizeof(post_plugin_deinterlace_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_class_deinterlace_t *class = (post_class_deinterlace_t *)class_gen; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, 1); this->tvtime = tvtime_new_context(); @@ -385,7 +398,7 @@ static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int input pthread_mutex_init (&this->lock, NULL); set_parameters ((xine_post_t *)&this->post, &class->init_param); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); /* replace with our own get_frame function */ port->new_port.open = deinterlace_open; @@ -395,7 +408,7 @@ static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int input port->new_port.flush = deinterlace_flush; port->intercept_frame = deinterlace_intercept_frame; port->new_frame->draw = deinterlace_draw; - + input_api = &this->parameter_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -404,11 +417,11 @@ static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int input input->xine_in.name = "video"; output->xine_out.name = "deinterlaced video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = deinterlace_dispose; - + return &this->post; } @@ -464,9 +477,9 @@ static int deinterlace_set_property(xine_video_port_t *port_gen, int property, i pthread_mutex_unlock (&this->lock); this->vo_deinterlace_enabled = this->enabled && (!this->cur_method); - - port->original_port->set_property(port->original_port, - XINE_PARAM_VO_DEINTERLACE, + + port->original_port->set_property(port->original_port, + XINE_PARAM_VO_DEINTERLACE, this->vo_deinterlace_enabled); return this->enabled; @@ -487,14 +500,14 @@ static void deinterlace_open(xine_video_port_t *port_gen, xine_stream_t *stream) { post_video_port_t *port = (post_video_port_t *)port_gen; post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post; - + _x_post_rewire(&this->post); _x_post_inc_usage(port); port->stream = stream; (port->original_port->open) (port->original_port, stream); this->vo_deinterlace_enabled = !this->cur_method; - port->original_port->set_property(port->original_port, - XINE_PARAM_VO_DEINTERLACE, + port->original_port->set_property(port->original_port, + XINE_PARAM_VO_DEINTERLACE, this->vo_deinterlace_enabled); } @@ -505,8 +518,8 @@ static void deinterlace_close(xine_video_port_t *port_gen, xine_stream_t *stream port->stream = NULL; _flush_frames(this); - port->original_port->set_property(port->original_port, - XINE_PARAM_VO_DEINTERLACE, + port->original_port->set_property(port->original_port, + XINE_PARAM_VO_DEINTERLACE, 0); port->original_port->close(port->original_port, stream); _x_post_dec_usage(port); @@ -517,21 +530,21 @@ static int deinterlace_intercept_frame(post_video_port_t *port, vo_frame_t *fram { post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post; int vo_deinterlace_enabled = 0; - + vo_deinterlace_enabled = ( frame->format != XINE_IMGFMT_YV12 && frame->format != XINE_IMGFMT_YUY2 && this->enabled ); - + if( this->cur_method && this->vo_deinterlace_enabled != vo_deinterlace_enabled ) { this->vo_deinterlace_enabled = vo_deinterlace_enabled; - port->original_port->set_property(port->original_port, - XINE_PARAM_VO_DEINTERLACE, + port->original_port->set_property(port->original_port, + XINE_PARAM_VO_DEINTERLACE, this->vo_deinterlace_enabled); } - + return (this->enabled && this->cur_method && - (frame->flags & VO_INTERLACED_FLAG) && + (frame->flags & VO_INTERLACED_FLAG) && (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2) ); } @@ -546,7 +559,7 @@ static void apply_chroma_filter( uint8_t *data, int stride, int width, int heigh */ for( i = 0; i < height; i++, data += stride ) { vfilter_chroma_332_packed422_scanline( data, width, - data, + data, (i) ? (data - stride) : data, (i < height-1) ? (data + stride) : data ); } @@ -554,7 +567,7 @@ static void apply_chroma_filter( uint8_t *data, int stride, int width, int heigh /* Build the output frame from the specified field. */ static int deinterlace_build_output_field( - post_plugin_deinterlace_t *this, post_video_port_t *port, + post_plugin_deinterlace_t *this, post_video_port_t *port, xine_stream_t *stream, vo_frame_t *frame, vo_frame_t *yuy2_frame, int bottom_field, int second_field, @@ -563,14 +576,14 @@ static int deinterlace_build_output_field( vo_frame_t *deinterlaced_frame; int scaler = 1; int force24fps; - + force24fps = this->judder_correction && !this->cheap_mode && ( this->pulldown == PULLDOWN_VEKTOR && this->tvtime->filmmode ); - + if( this->tvtime->curmethod->doscalerbob ) { scaler = 2; } - + pthread_mutex_unlock (&this->lock); deinterlaced_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height / scaler, frame->ratio, yuy2_frame->format, @@ -583,7 +596,7 @@ static int deinterlace_build_output_field( deinterlaced_frame->crop_bottom = frame->crop_bottom; _x_extra_info_merge(deinterlaced_frame->extra_info, frame->extra_info); - + if( skip > 0 && !this->pulldown ) { deinterlaced_frame->bad_frame = 1; } else { @@ -592,60 +605,60 @@ static int deinterlace_build_output_field( deinterlaced_frame->bad_frame = !tvtime_build_copied_field(this->tvtime, deinterlaced_frame->base[0], yuy2_frame->base[0], bottom_field, - frame->width, frame->height, + frame->width, frame->height, yuy2_frame->pitches[0], deinterlaced_frame->pitches[0] ); } else { deinterlaced_frame->bad_frame = !tvtime_build_copied_field(this->tvtime, deinterlaced_frame->base[0], yuy2_frame->base[0], bottom_field, - frame->width/2, frame->height, + frame->width/2, frame->height, yuy2_frame->pitches[0], deinterlaced_frame->pitches[0] ); deinterlaced_frame->bad_frame += !tvtime_build_copied_field(this->tvtime, deinterlaced_frame->base[1], yuy2_frame->base[1], bottom_field, - frame->width/4, frame->height/2, + frame->width/4, frame->height/2, yuy2_frame->pitches[1], deinterlaced_frame->pitches[1] ); deinterlaced_frame->bad_frame += !tvtime_build_copied_field(this->tvtime, deinterlaced_frame->base[2], yuy2_frame->base[2], bottom_field, - frame->width/4, frame->height/2, + frame->width/4, frame->height/2, yuy2_frame->pitches[2], deinterlaced_frame->pitches[2] ); } } else { if( yuy2_frame->format == XINE_IMGFMT_YUY2 ) { deinterlaced_frame->bad_frame = !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[0], - yuy2_frame->base[0], - (this->recent_frame[0])?this->recent_frame[0]->base[0]:yuy2_frame->base[0], + yuy2_frame->base[0], + (this->recent_frame[0])?this->recent_frame[0]->base[0]:yuy2_frame->base[0], (this->recent_frame[1])?this->recent_frame[1]->base[0]:yuy2_frame->base[0], - bottom_field, second_field, frame->width, frame->height, + bottom_field, second_field, frame->width, frame->height, yuy2_frame->pitches[0], deinterlaced_frame->pitches[0]); } else { deinterlaced_frame->bad_frame = !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[0], - yuy2_frame->base[0], - (this->recent_frame[0])?this->recent_frame[0]->base[0]:yuy2_frame->base[0], + yuy2_frame->base[0], + (this->recent_frame[0])?this->recent_frame[0]->base[0]:yuy2_frame->base[0], (this->recent_frame[1])?this->recent_frame[1]->base[0]:yuy2_frame->base[0], - bottom_field, second_field, frame->width/2, frame->height, + bottom_field, second_field, frame->width/2, frame->height, yuy2_frame->pitches[0], deinterlaced_frame->pitches[0]); deinterlaced_frame->bad_frame += !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[1], - yuy2_frame->base[1], - (this->recent_frame[0])?this->recent_frame[0]->base[1]:yuy2_frame->base[1], + yuy2_frame->base[1], + (this->recent_frame[0])?this->recent_frame[0]->base[1]:yuy2_frame->base[1], (this->recent_frame[1])?this->recent_frame[1]->base[1]:yuy2_frame->base[1], bottom_field, second_field, frame->width/4, frame->height/2, yuy2_frame->pitches[1], deinterlaced_frame->pitches[1]); deinterlaced_frame->bad_frame += !tvtime_build_deinterlaced_frame(this->tvtime, deinterlaced_frame->base[2], - yuy2_frame->base[2], - (this->recent_frame[0])?this->recent_frame[0]->base[2]:yuy2_frame->base[2], + yuy2_frame->base[2], + (this->recent_frame[0])?this->recent_frame[0]->base[2]:yuy2_frame->base[2], (this->recent_frame[1])?this->recent_frame[1]->base[2]:yuy2_frame->base[2], - bottom_field, second_field, frame->width/4, frame->height/2, + bottom_field, second_field, frame->width/4, frame->height/2, yuy2_frame->pitches[2], deinterlaced_frame->pitches[2]); } } } - + pthread_mutex_unlock (&this->lock); if( force24fps ) { if( !deinterlaced_frame->bad_frame ) { @@ -657,7 +670,7 @@ static int deinterlace_build_output_field( deinterlaced_frame->pts = 0; deinterlaced_frame->duration = FPS_24_DURATION; if( this->chroma_filter && !this->cheap_mode ) - apply_chroma_filter( deinterlaced_frame->base[0], deinterlaced_frame->pitches[0], + apply_chroma_filter( deinterlaced_frame->base[0], deinterlaced_frame->pitches[0], frame->width, frame->height / scaler ); skip = deinterlaced_frame->draw(deinterlaced_frame, stream); } else { @@ -667,15 +680,15 @@ static int deinterlace_build_output_field( deinterlaced_frame->pts = pts; deinterlaced_frame->duration = duration; if( this->chroma_filter && !this->cheap_mode && !deinterlaced_frame->bad_frame ) - apply_chroma_filter( deinterlaced_frame->base[0], deinterlaced_frame->pitches[0], + apply_chroma_filter( deinterlaced_frame->base[0], deinterlaced_frame->pitches[0], frame->width, frame->height / scaler ); skip = deinterlaced_frame->draw(deinterlaced_frame, stream); } - + /* _x_post_frame_copy_up(frame, deinterlaced_frame); */ deinterlaced_frame->free(deinterlaced_frame); pthread_mutex_lock (&this->lock); - + return skip; } @@ -692,7 +705,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) orig_frame = frame; _x_post_frame_copy_down(frame, frame->next); frame = frame->next; - + /* update tvtime context and method */ pthread_mutex_lock (&this->lock); if( this->tvtime_changed ) { @@ -703,8 +716,8 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) else this->tvtime->curmethod = NULL; - port->original_port->set_property(port->original_port, - XINE_PARAM_VO_DEINTERLACE, + port->original_port->set_property(port->original_port, + XINE_PARAM_VO_DEINTERLACE, !this->cur_method); this->tvtime_changed = 0; @@ -723,11 +736,11 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) lprintf("frame flags pf: %d rff: %d tff: %d duration: %d\n", frame->progressive_frame, frame->repeat_first_field, frame->top_field_first, frame->duration); - + /* detect special rff patterns */ this->rff_pattern = this->rff_pattern << 1; this->rff_pattern |= !!frame->repeat_first_field; - + if( ((this->rff_pattern & 0xff) == 0xaa || (this->rff_pattern & 0xff) == 0x55) ) { /* @@ -739,7 +752,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) /* using frame->progressive_frame may help displaying still menus. * however, it is known that some rare material set it wrong. - * + * * we also assume that repeat_first_field is progressive (it doesn't * make much sense to display interlaced fields out of order) */ @@ -747,8 +760,8 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) (frame->repeat_first_field || frame->progressive_frame) ) { progressive = 1; } - - if( !frame->bad_frame && + + if( !frame->bad_frame && (frame->flags & VO_INTERLACED_FLAG) && this->tvtime->curmethod ) { @@ -760,17 +773,17 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) yuy2_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YUY2, frame->flags | VO_BOTH_FIELDS); _x_post_frame_copy_down(frame, yuy2_frame); - + /* the logic for deciding upsampling to use comes from: * http://www.hometheaterhifi.com/volume_8_2/dvd-benchmark-special-report-chroma-bug-4-2001.html */ - yv12_to_yuy2(frame->base[0], frame->pitches[0], - frame->base[1], frame->pitches[1], - frame->base[2], frame->pitches[2], + yv12_to_yuy2(frame->base[0], frame->pitches[0], + frame->base[1], frame->pitches[1], + frame->base[2], frame->pitches[2], yuy2_frame->base[0], yuy2_frame->pitches[0], - frame->width, frame->height, + frame->width, frame->height, frame->progressive_frame || progressive ); - + } else { yuy2_frame = frame; yuy2_frame->lock(yuy2_frame); @@ -780,10 +793,10 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) pthread_mutex_lock (&this->lock); /* check if frame format changed */ for(i = 0; i < NUM_RECENT_FRAMES; i++ ) { - if( this->recent_frame[i] && - (this->recent_frame[i]->width != frame->width || - this->recent_frame[i]->height != frame->height || - this->recent_frame[i]->format != yuy2_frame->format ) ) { + if( this->recent_frame[i] && + (this->recent_frame[i]->width != frame->width || + this->recent_frame[i]->height != frame->height || + this->recent_frame[i]->format != yuy2_frame->format ) ) { this->recent_frame[i]->free(this->recent_frame[i]); this->recent_frame[i] = NULL; } @@ -796,10 +809,10 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) framerate_mode = FRAMERATE_HALF_TFF; this->tvtime->pulldown_alg = PULLDOWN_NONE; } - + if( framerate_mode == FRAMERATE_FULL ) { int top_field_first = frame->top_field_first; - + /* if i understood mpeg2 specs correctly, top_field_first * shall be zero for field pictures and the output order * is the same that the fields are decoded. @@ -811,7 +824,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) if ( (frame->flags & VO_BOTH_FIELDS) != VO_BOTH_FIELDS ) { top_field_first = (frame->flags & VO_TOP_FIELD) ? 1 : 0; } - + if ( top_field_first ) { fields[0] = 0; fields[1] = 1; @@ -824,8 +837,8 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) } else if ( framerate_mode == FRAMERATE_HALF_BFF ) { fields[0] = 1; } - - + + if( progressive ) { /* If the previous field was interlaced and this one is progressive @@ -837,10 +850,10 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) * duration is used in the calculation because the generated frame * represents the second half of the previous frame. */ - if (this->recent_frame[0] && !this->recent_frame[0]->progressive_frame && + if (this->recent_frame[0] && !this->recent_frame[0]->progressive_frame && this->tvtime->curmethod->delaysfield) { - skip = deinterlace_build_output_field( + skip = deinterlace_build_output_field( this, port, stream, frame, yuy2_frame, fields[0], 0, @@ -866,19 +879,19 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) /* Build the output from the first field. */ if ( !(this->recent_frame[0] && this->recent_frame[0]->progressive_frame && this->tvtime->curmethod->delaysfield) ) { - skip = deinterlace_build_output_field( + skip = deinterlace_build_output_field( this, port, stream, frame, yuy2_frame, fields[0], 0, frame->pts, (framerate_mode == FRAMERATE_FULL) ? frame->duration/2 : frame->duration, 0); - } + } if( framerate_mode == FRAMERATE_FULL ) { - + /* Build the output from the second field. */ - skip = deinterlace_build_output_field( + skip = deinterlace_build_output_field( this, port, stream, frame, yuy2_frame, fields[1], 1, @@ -888,7 +901,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) } } - /* don't drop frames when pulldown mode is enabled. otherwise + /* don't drop frames when pulldown mode is enabled. otherwise * pulldown detection fails (yo-yo effect has also been seen) */ if( this->pulldown ) @@ -896,7 +909,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) /* store back progressive flag for frame history */ yuy2_frame->progressive_frame = progressive; - + /* keep track of recent frames */ i = NUM_RECENT_FRAMES-1; if( this->recent_frame[i] ) @@ -917,8 +930,8 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream) } else { skip = frame->draw(frame, stream); } - + _x_post_frame_copy_up(orig_frame, frame); - + return skip; } diff --git a/src/post/goom/Makefile.am b/src/post/goom/Makefile.am index c01482917..cd022c9b0 100644 --- a/src/post/goom/Makefile.am +++ b/src/post/goom/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = mmx.c xmmx.c ppc_drawings.s ppc_zoom_ultimate.s diff_against_release.patch \ diff --git a/src/post/goom/convolve_fx.c b/src/post/goom/convolve_fx.c index e86bb3723..ee36dfd0b 100644 --- a/src/post/goom/convolve_fx.c +++ b/src/post/goom/convolve_fx.c @@ -20,7 +20,7 @@ typedef char Motif[CONV_MOTIF_W][CONV_MOTIF_W]; #define NB_THETA 512 -#define MAX 2.0f +//#define MAX 2.0f typedef struct _CONV_DATA{ PluginParam light; @@ -73,7 +73,7 @@ static void set_motif(ConvData *data, Motif motif) static void convolve_init(VisualFX *_this, PluginInfo *info) { ConvData *data; - data = (ConvData*)malloc(sizeof(ConvData)); + data = (ConvData*)calloc(1, sizeof(ConvData)); _this->fx_data = (void*)data; data->light = secure_f_param("Screen Brightness"); diff --git a/src/post/goom/diff_against_release.patch b/src/post/goom/diff_against_release.patch index bde85c285..a5e84b8d1 100644 --- a/src/post/goom/diff_against_release.patch +++ b/src/post/goom/diff_against_release.patch @@ -653,3 +653,40 @@ diff -u -p -r1.2 -r1.3 #endif +diff -r 96c7f8460d61 src/post/goom/convolve_fx.c +--- convolve_fx.c Mon Nov 10 16:33:51 2008 +0100 ++++ convolve_fx.c Sun Nov 16 21:14:29 2008 +0100 +@@ -73,7 +73,7 @@ static void set_motif(ConvData *data, Mo + + static void convolve_init(VisualFX *_this, PluginInfo *info) { + ConvData *data; +- data = (ConvData*)malloc(sizeof(ConvData)); ++ data = (ConvData*)calloc(1, sizeof(ConvData)); + _this->fx_data = (void*)data; + + data->light = secure_f_param("Screen Brightness"); +diff -r 96c7f8460d61 src/post/goom/goom_core.c +--- goom_core.c Mon Nov 10 16:33:51 2008 +0100 ++++ goom_core.c Sun Nov 16 21:14:29 2008 +0100 +@@ -76,6 +76,10 @@ PluginInfo *goom_init (guint32 resx, gui + goomInfo->tentacles_fx = tentacle_fx_create(); + goomInfo->tentacles_fx.init(&goomInfo->tentacles_fx, goomInfo); + ++ goomInfo->screen.width = resx; ++ goomInfo->screen.height = resy; ++ goomInfo->screen.size = resx * resy; ++ + goomInfo->convolve_fx = convolve_create(); + goomInfo->convolve_fx.init(&goomInfo->convolve_fx, goomInfo); + +@@ -83,10 +87,6 @@ PluginInfo *goom_init (guint32 resx, gui + plugin_info_add_visual (goomInfo, 1, &goomInfo->tentacles_fx); + plugin_info_add_visual (goomInfo, 2, &goomInfo->star_fx); + plugin_info_add_visual (goomInfo, 3, &goomInfo->convolve_fx); +- +- goomInfo->screen.width = resx; +- goomInfo->screen.height = resy; +- goomInfo->screen.size = resx * resy; + + init_buffers(goomInfo, goomInfo->screen.size); + goomInfo->gRandom = goom_random_init((uintptr_t)goomInfo->pixel); diff --git a/src/post/goom/goom_core.c b/src/post/goom/goom_core.c index b24f2f496..62d9a27b6 100644 --- a/src/post/goom/goom_core.c +++ b/src/post/goom/goom_core.c @@ -76,6 +76,10 @@ PluginInfo *goom_init (guint32 resx, guint32 resy) goomInfo->tentacles_fx = tentacle_fx_create(); goomInfo->tentacles_fx.init(&goomInfo->tentacles_fx, goomInfo); + goomInfo->screen.width = resx; + goomInfo->screen.height = resy; + goomInfo->screen.size = resx * resy; + goomInfo->convolve_fx = convolve_create(); goomInfo->convolve_fx.init(&goomInfo->convolve_fx, goomInfo); @@ -84,10 +88,6 @@ PluginInfo *goom_init (guint32 resx, guint32 resy) plugin_info_add_visual (goomInfo, 2, &goomInfo->star_fx); plugin_info_add_visual (goomInfo, 3, &goomInfo->convolve_fx); - goomInfo->screen.width = resx; - goomInfo->screen.height = resy; - goomInfo->screen.size = resx * resy; - init_buffers(goomInfo, goomInfo->screen.size); goomInfo->gRandom = goom_random_init((uintptr_t)goomInfo->pixel); @@ -841,7 +841,7 @@ void update_message (PluginInfo *goomInfo, char *message) { if (message) { int i=1,j=0; - sprintf (goomInfo->update_message.message, "%s", message); + strcpy(goomInfo->update_message.message, message); for (j=0;goomInfo->update_message.message[j];j++) if (goomInfo->update_message.message[j]=='\n') i++; @@ -855,8 +855,8 @@ void update_message (PluginInfo *goomInfo, char *message) { char *ptr = msg; int pos; float ecart; + strncpy(msg, goomInfo->update_message.message, goomInfo->update_message.longueur); message = msg; - sprintf (msg, "%s", goomInfo->update_message.message); while (!fin) { while (1) { diff --git a/src/post/goom/ppc_zoom_ultimate.h b/src/post/goom/ppc_zoom_ultimate.h index d6932e7e6..d070071c9 100644 --- a/src/post/goom/ppc_zoom_ultimate.h +++ b/src/post/goom/ppc_zoom_ultimate.h @@ -11,4 +11,4 @@ void ppc_zoom_generic (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]); /* G4 Specific PowerPC Code (Possible use of Altivec and Data Streams) */ -void ppc_zoom_G4 (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]);
\ No newline at end of file +void ppc_zoom_G4 (int sizeX, int sizeY, Pixel *src, Pixel *dest, int *brutS, int *brutD, int buffratio, int precalCoef[16][16]); diff --git a/src/post/goom/xine_goom.c b/src/post/goom/xine_goom.c index 8cd06dbd6..72692ffe1 100644 --- a/src/post/goom/xine_goom.c +++ b/src/post/goom/xine_goom.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -48,7 +48,7 @@ #define GOOM_HEIGHT 240 /* colorspace conversion methods */ -static const char const * goom_csc_methods[]={ +static const char* goom_csc_methods[]={ "Fast but not photorealistic", "Slow but looks better", NULL @@ -71,19 +71,19 @@ struct post_plugin_goom_s { /* private data */ xine_video_port_t *vo_port; post_out_t video_output; - + post_class_goom_t *class; - + /* private metronom for syncing the video */ metronom_t *metronom; - + /* goom context */ PluginInfo *goom; - - int data_idx; + + int data_idx; gint16 data [2][NUMSAMPLES]; audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */ - + int channels; int sample_rate; int samples_per_frame; @@ -99,7 +99,7 @@ struct post_plugin_goom_s { yuv_planes_t yuv; - + /* frame skipping */ int skip_frame; }; @@ -110,12 +110,12 @@ static void *goom_init_plugin(xine_t *xine, void *); /* plugin catalog information */ -static const post_info_t goom_special_info = { +static const post_info_t goom_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 9, "goom", XINE_VERSION_CODE, &goom_special_info, &goom_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; @@ -144,7 +144,7 @@ static void goom_port_put_buffer (xine_audio_port_t *this, audio_buffer_t *buf, static void fps_changed_cb(void *data, xine_cfg_entry_t *cfg) { post_class_goom_t *class = (post_class_goom_t*) data; - + if(class->ip) { post_plugin_goom_t *this = class->ip; @@ -160,7 +160,7 @@ static void fps_changed_cb(void *data, xine_cfg_entry_t *cfg) { static void width_changed_cb(void *data, xine_cfg_entry_t *cfg) { post_class_goom_t *class = (post_class_goom_t*) data; - + if(class->ip) { post_plugin_goom_t *this = class->ip; this->width = cfg->num_value; @@ -169,7 +169,7 @@ static void width_changed_cb(void *data, xine_cfg_entry_t *cfg) { static void height_changed_cb(void *data, xine_cfg_entry_t *cfg) { post_class_goom_t *class = (post_class_goom_t*) data; - + if(class->ip) { post_plugin_goom_t *this = class->ip; this->height = cfg->num_value; @@ -178,7 +178,7 @@ static void height_changed_cb(void *data, xine_cfg_entry_t *cfg) { static void csc_method_changed_cb(void *data, xine_cfg_entry_t *cfg) { post_class_goom_t *class = (post_class_goom_t*) data; - + if(class->ip) { post_plugin_goom_t *this = class->ip; this->csc_method = cfg->num_value; @@ -187,19 +187,19 @@ static void csc_method_changed_cb(void *data, xine_cfg_entry_t *cfg) { static void *goom_init_plugin(xine_t *xine, void *data) { - post_class_goom_t *this = (post_class_goom_t *)xine_xmalloc(sizeof(post_class_goom_t)); + post_class_goom_t *this = calloc(1, sizeof(post_class_goom_t)); config_values_t *cfg; if (!this) return NULL; - + this->class.open_plugin = goom_open_plugin; this->class.get_identifier = goom_get_identifier; this->class.get_description = goom_get_description; this->class.dispose = goom_class_dispose; this->ip = NULL; this->xine = xine; - + cfg = xine->config; cfg->register_num (cfg, "effects.goom.fps", FPS, @@ -212,12 +212,12 @@ static void *goom_init_plugin(xine_t *xine, void *data) _("goom image width"), _("The width in pixels of the image to be generated."), 10, width_changed_cb, this); - + cfg->register_num (cfg, "effects.goom.height", GOOM_HEIGHT, _("goom image height"), _("The height in pixels of the image to be generated."), 10, height_changed_cb, this); - + cfg->register_enum (cfg, "effects.goom.csc_method", 0, goom_csc_methods, @@ -234,7 +234,7 @@ static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_goom_t *this = (post_plugin_goom_t *)xine_xmalloc(sizeof(post_plugin_goom_t)); + post_plugin_goom_t *this = calloc(1, sizeof(post_plugin_goom_t)); post_class_goom_t *class = (post_class_goom_t*) class_gen; post_in_t *input; post_out_t *output; @@ -246,34 +246,34 @@ static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs, free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); - + /* * Lookup config entries. */ this->class = class; class->ip = this; this->vo_port = video_target[0]; - + this->metronom = _x_metronom_init(1, 0, class->xine); lprintf("goom_open_plugin\n"); if(xine_config_lookup_entry(class->xine, "effects.goom.fps", - &fps_entry)) + &fps_entry)) fps_changed_cb(class, &fps_entry); if(xine_config_lookup_entry(class->xine, "effects.goom.width", - &width_entry)) + &width_entry)) width_changed_cb(class, &width_entry); if(xine_config_lookup_entry(class->xine, "effects.goom.height", - &height_entry)) + &height_entry)) height_changed_cb(class, &height_entry); if(xine_config_lookup_entry(class->xine, "effects.goom.csc_method", - &csc_method_entry)) + &csc_method_entry)) csc_method_changed_cb(class, &csc_method_entry); this->width_back = this->width; @@ -285,13 +285,13 @@ static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs, this->ratio = (double)this->width_back/(double)this->height_back; this->buf.mem = NULL; - this->buf.mem_size = 0; + this->buf.mem_size = 0; port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output); port->new_port.open = goom_port_open; port->new_port.close = goom_port_close; port->new_port.put_buffer = goom_port_put_buffer; - + outputv = &this->video_output; outputv->xine_out.name = "generated video"; outputv->xine_out.type = XINE_POST_DATA_VIDEO; @@ -299,7 +299,7 @@ static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs, outputv->xine_out.rewire = goom_rewire_video; outputv->post = &this->post; xine_list_push_back(this->post.output, outputv); - + this->post.xine_post.audio_input[0] = &port->new_port; this->post.dispose = goom_dispose; @@ -322,13 +322,13 @@ static void goom_class_dispose(post_class_t *class_gen) post_class_goom_t *this = (post_class_goom_t*) class_gen; this->xine->config->unregister_callback(this->xine->config, - "effects.goom.fps"); + "effects.goom.fps"); this->xine->config->unregister_callback(this->xine->config, - "effects.goom.width"); + "effects.goom.width"); this->xine->config->unregister_callback(this->xine->config, - "effects.goom.height"); + "effects.goom.height"); this->xine->config->unregister_callback(this->xine->config, - "effects.goom.csc_method"); + "effects.goom.csc_method"); free(class_gen); } @@ -358,7 +358,7 @@ static int goom_rewire_video(xine_post_out_t *output_gen, void *data) xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data; xine_video_port_t *new_port = (xine_video_port_t *)data; post_plugin_goom_t *this = (post_plugin_goom_t *)output->post; - + if (!data) return 0; /* register our stream at the new output port */ @@ -377,12 +377,12 @@ static int goom_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - + this->channels = _x_ao_mode2channels(mode); this->sample_rate = rate; this->samples_per_frame = rate / this->fps; @@ -392,7 +392,7 @@ static int goom_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, this->do_samples_skip = 0; this->left_to_read = NUMSAMPLES; - + (this->vo_port->open) (this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, stream->metronom); @@ -407,18 +407,18 @@ static void goom_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream ) free_yuv_planes(&this->yuv); port->stream = NULL; - + this->vo_port->close(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, NULL); - + port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } -static void goom_port_put_buffer (xine_audio_port_t *port_gen, +static void goom_port_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_goom_t *this = (post_plugin_goom_t *)port->post; vo_frame_t *frame; @@ -431,28 +431,28 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, int width, height; int current_sample = 0; - + /* make a copy of buf data for private use */ if( this->buf.mem_size < buf->mem_size ) { this->buf.mem = realloc(this->buf.mem, buf->mem_size); this->buf.mem_size = buf->mem_size; } - memcpy(this->buf.mem, buf->mem, + memcpy(this->buf.mem, buf->mem, buf->num_frames*this->channels*((port->bits == 8)?1:2)); this->buf.num_frames = buf->num_frames; - + /* pass data to original port */ - port->original_port->put_buffer(port->original_port, buf, stream); - + port->original_port->put_buffer(port->original_port, buf, stream); + /* we must not use original data anymore, it should have already being moved * to the fifo of free audio buffers. just use our private copy instead. */ - buf = &this->buf; + buf = &this->buf; j = (this->channels >= 2) ? 1 : 0; while (current_sample < buf->num_frames) { - + if (this->do_samples_skip) { if (current_sample + this->left_to_read > buf->num_frames) { this->left_to_read -= (buf->num_frames-current_sample); @@ -461,14 +461,14 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, current_sample+=this->left_to_read; this->left_to_read = NUMSAMPLES; this->do_samples_skip = 0; - + } } else { if( port->bits == 8 ) { data8 = (int8_t *)buf->mem; data8 += current_sample * this->channels; - + /* scale 8 bit data to 16 bits and convert to signed as well */ for ( i=current_sample ; this->data_idx < NUMSAMPLES && i < buf->num_frames; i++, this->data_idx++,data8 += this->channels) { @@ -507,13 +507,13 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, frame = this->vo_port->get_frame (this->vo_port, this->width_back, this->height_back, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); - + frame->extra_info->invalid = 1; - + frame->duration = 90000 * this->samples_per_frame / this->sample_rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); - + if (!this->skip_frame) { /* Try to be fast */ goom_frame = (uint8_t *)goom_update (this->goom, this->data, 0, 0, NULL, NULL); @@ -521,13 +521,13 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, dest_ptr = frame -> base[0]; goom_frame_end = goom_frame + 4 * (this->width_back * this->height_back); - if ((this->csc_method == 1) && + if ((this->csc_method == 1) && (xine_mm_accel() & MM_ACCEL_X86_MMX)) { int plane_ptr = 0; while (goom_frame < goom_frame_end) { uint8_t r, g, b; - + /* don't take endianness into account since MMX is only available * on Intel processors */ b = *goom_frame; goom_frame++; @@ -563,7 +563,7 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, g2 = *goom_frame; goom_frame++; r2 = *goom_frame; goom_frame += 2; #endif - + *dest_ptr = COMPUTE_Y(r1, g1, b1); dest_ptr++; *dest_ptr = COMPUTE_U(r1, g1, b1); @@ -585,7 +585,7 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen, } frame->free(frame); - + width = this->width; height = this->height; if ((width != this->width_back) || (height != this->height_back)) { diff --git a/src/post/mosaico/Makefile.am b/src/post/mosaico/Makefile.am index af027b6e6..56426c711 100644 --- a/src/post/mosaico/Makefile.am +++ b/src/post/mosaico/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common xinepost_LTLIBRARIES = xineplug_post_mosaico.la xineplug_post_switch.la diff --git a/src/post/mosaico/mosaico.c b/src/post/mosaico/mosaico.c index 50b1cfcdf..ec46e1ca0 100644 --- a/src/post/mosaico/mosaico.c +++ b/src/post/mosaico/mosaico.c @@ -1,27 +1,31 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + /* * simple video mosaico plugin */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #define LOG_MODULE "mosaico" #define LOG_VERBOSE /* @@ -40,7 +44,7 @@ static void *mosaico_init_plugin(xine_t *xine, void *); static const post_info_t mosaico_special_info = { XINE_POST_TYPE_VIDEO_COMPOSE }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST, 9, "mosaico", XINE_VERSION_CODE, &mosaico_special_info, &mosaico_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; @@ -80,9 +84,9 @@ struct mosaico_pip_s { }; struct post_mosaico_s { - post_plugin_t post; + post_plugin_t post; xine_post_in_t parameter_input; - + mosaico_pip_t *pip; int64_t vpts_limit; pthread_cond_t vpts_limit_changed; @@ -122,11 +126,11 @@ static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream); static void *mosaico_init_plugin(xine_t *xine, void *data) { - post_class_mosaico_t *this = (post_class_mosaico_t *)xine_xmalloc(sizeof(post_class_mosaico_t)); + post_class_mosaico_t *this = calloc(1, sizeof(post_class_mosaico_t)); if (!this) return NULL; - + this->class.open_plugin = mosaico_open_plugin; this->class.get_identifier = mosaico_get_identifier; this->class.get_description = mosaico_get_description; @@ -140,30 +144,30 @@ static post_plugin_t *mosaico_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_mosaico_t *this = (post_mosaico_t *)xine_xmalloc(sizeof(post_mosaico_t)); + post_mosaico_t *this = calloc(1, sizeof(post_mosaico_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; - static xine_post_api_t post_api = + static xine_post_api_t post_api = { mosaico_set_parameters, mosaico_get_parameters, mosaico_get_param_descr, mosaico_get_help }; int i; - + lprintf("mosaico open\n"); if (inputs < 2 || !this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, inputs); - this->pip = (mosaico_pip_t *)xine_xmalloc(sizeof(mosaico_pip_t) * (inputs - 1)); + this->pip = (mosaico_pip_t *)calloc((inputs - 1), sizeof(mosaico_pip_t)); this->pip_count = inputs - 1; pthread_cond_init(&this->vpts_limit_changed, NULL); pthread_mutex_init(&this->mutex, NULL); - + /* the port for the background video */ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->intercept_frame = mosaico_intercept_frame; @@ -178,9 +182,8 @@ static post_plugin_t *mosaico_open_plugin(post_class_t *class_gen, int inputs, this->pip[i].y = 50; this->pip[i].w = 150; this->pip[i].h = 150; - this->pip[i].input_name = (char *)xine_xmalloc(sizeof("video in ") + 10); - snprintf(this->pip[i].input_name, sizeof("video in ") + 10, "video in %d", i+1); - + asprintf(&(this->pip[i].input_name), "video in %d", i+1); + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, NULL); port->new_port.close = mosaico_close; port->intercept_frame = mosaico_intercept_frame; @@ -221,7 +224,7 @@ static void mosaico_class_dispose(post_class_t *class_gen) static void mosaico_dispose(post_plugin_t *this_gen) { post_mosaico_t *this = (post_mosaico_t *)this_gen; - + if (_x_post_dispose(this_gen)) { int i; for (i = 0; i < this->pip_count; i++) @@ -243,7 +246,7 @@ static int mosaico_set_parameters(xine_post_t *this_gen, void *param_gen) { post_mosaico_t *this = (post_mosaico_t *)this_gen; mosaico_parameters_t *param = (mosaico_parameters_t *)param_gen; - + if (param->pip_num > this->pip_count) return 0; this->pip[param->pip_num - 1].x = param->x; this->pip[param->pip_num - 1].y = param->y; @@ -256,7 +259,7 @@ static int mosaico_get_parameters(xine_post_t *this_gen, void *param_gen) { post_mosaico_t *this = (post_mosaico_t *)this_gen; mosaico_parameters_t *param = (mosaico_parameters_t *)param_gen; - + if (param->pip_num > this->pip_count || param->pip_num < 1) param->pip_num = 1; param->x = this->pip[param->pip_num - 1].x; @@ -288,7 +291,7 @@ static void mosaico_close(xine_video_port_t *port_gen, xine_stream_t *stream) for (pip_num = 0; pip_num < this->pip_count; pip_num++) if (this->post.xine_post.video_input[pip_num+1] == port_gen) break; - + pthread_mutex_lock(&this->mutex); free_frame = this->pip[pip_num].frame; this->pip[pip_num].frame = NULL; @@ -317,11 +320,11 @@ static void frame_copy_content(vo_frame_t *to, vo_frame_t *from) case XINE_IMGFMT_YUY2: /* TODO: implement conversion to YV12 or implement support to paste * frames of different types together */ - break; - + break; + case XINE_IMGFMT_YV12: /* Y */ - size = to->pitches[0] * to->height; + size = to->pitches[0] * to->height; xine_fast_memcpy(to->base[0], from->base[0], size); /* U */ @@ -346,7 +349,7 @@ static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_nu unsigned long i, j; if (!this->pip[pip_num].frame) return; - + target_width = this->pip[pip_num].w; target_height = this->pip[pip_num].h; background_width = background->width; @@ -361,8 +364,8 @@ static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_nu switch (this->pip[pip_num].frame->format) { case XINE_IMGFMT_YUY2: /* TODO: implement YUY2 */ - break; - + break; + case XINE_IMGFMT_YV12: /* Y */ target_offset = 0; @@ -379,7 +382,7 @@ static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_nu pos = pos_y * background_width + pos_x; target_width = (target_width + 1) / 2; target_height = (target_height + 1) / 2; - + /* U */ target_offset = 0; for (j = 0; j < target_height; j++, target_offset += (background_width - target_width)) @@ -387,7 +390,7 @@ static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_nu source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width); background->base[1][pos + target_offset] = this->pip[pip_num].frame->base[1][source_offset]; } - + /* V */ target_offset = 0; for (j = 0; j < target_height; j++, target_offset += (background_width - target_width)) @@ -395,7 +398,7 @@ static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_nu source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width); background->base[2][pos + target_offset] = this->pip[pip_num].frame->base[2][source_offset]; } - + break; } } @@ -408,47 +411,47 @@ static int mosaico_draw_background(vo_frame_t *frame, xine_stream_t *stream) int pip_num, skip; pthread_mutex_lock(&this->mutex); - + if (frame->bad_frame) { _x_post_frame_copy_down(frame, frame->next); skip = frame->next->draw(frame->next, stream); _x_post_frame_copy_up(frame, frame->next); - + this->vpts_limit = frame->vpts + frame->duration; if (skip) { this->skip = skip; this->skip_vpts = frame->vpts; } else this->skip = 0; - + pthread_mutex_unlock(&this->mutex); pthread_cond_broadcast(&this->vpts_limit_changed); - + return skip; } - + background = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS); _x_post_frame_copy_down(frame, background); frame_copy_content(background, frame); - + for (pip_num = 0; pip_num < this->pip_count; pip_num++) frame_paste(this, background, pip_num); - + skip = background->draw(background, stream); _x_post_frame_copy_up(frame, background); this->vpts_limit = background->vpts + background->duration; background->free(background); - + if (skip) { this->skip = skip; this->skip_vpts = frame->vpts; } else this->skip = 0; - + pthread_mutex_unlock(&this->mutex); pthread_cond_broadcast(&this->vpts_limit_changed); - + return skip; } @@ -462,11 +465,11 @@ static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream) for (pip_num = 0; pip_num < this->pip_count; pip_num++) if (this->post.xine_post.video_input[pip_num+1] == frame->port) break; _x_assert(pip_num < this->pip_count); - + frame->lock(frame); - + pthread_mutex_lock(&this->mutex); - + /* the original output will never see this frame again */ _x_post_frame_u_turn(frame, stream); while (frame->vpts > this->vpts_limit || !this->vpts_limit) @@ -475,12 +478,12 @@ static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream) free_frame = this->pip[pip_num].frame; if (port->stream) this->pip[pip_num].frame = frame; - + if (this->skip && frame->vpts <= this->skip_vpts) skip = this->skip; else skip = 0; - + pthread_mutex_unlock(&this->mutex); if (free_frame) @@ -489,6 +492,6 @@ static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream) /* do not keep this frame when no stream is connected to us, * otherwise, this frame might never get freed */ frame->free(frame); - + return skip; } diff --git a/src/post/mosaico/switch.c b/src/post/mosaico/switch.c index 8fec5ee77..7cba7c998 100644 --- a/src/post/mosaico/switch.c +++ b/src/post/mosaico/switch.c @@ -1,23 +1,23 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + /* * simple switch video post plugin */ @@ -40,7 +40,7 @@ static void *switch_init_plugin(xine_t *xine, void *); static const post_info_t switch_special_info = { XINE_POST_TYPE_VIDEO_COMPOSE }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST, 9, "switch", XINE_VERSION_CODE, &switch_special_info, &switch_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; @@ -67,7 +67,7 @@ struct post_class_switch_s { struct post_switch_s { post_plugin_t post; xine_post_in_t parameter_input; - + int64_t vpts_limit; pthread_cond_t display_condition_changed; int64_t skip_vpts; @@ -101,11 +101,11 @@ static int switch_draw(vo_frame_t *frame, xine_stream_t *stream); static void *switch_init_plugin(xine_t *xine, void *data) { - post_class_switch_t *this = (post_class_switch_t *)xine_xmalloc(sizeof(post_class_switch_t)); + post_class_switch_t *this = calloc(1, sizeof(post_class_switch_t)); if (!this) return NULL; - + this->class.open_plugin = switch_open_plugin; this->class.get_identifier = switch_get_identifier; this->class.get_description = switch_get_description; @@ -119,7 +119,7 @@ static post_plugin_t *switch_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_switch_t *this = (post_switch_t *)xine_xmalloc(sizeof(post_switch_t)); + post_switch_t *this = calloc(1, sizeof(post_switch_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; @@ -127,28 +127,28 @@ static post_plugin_t *switch_open_plugin(post_class_t *class_gen, int inputs, static xine_post_api_t post_api = { switch_set_parameters, switch_get_parameters, switch_get_param_descr, switch_get_help }; int i; - + lprintf("switch open\n"); if (inputs < 2 || !this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, inputs); this->source_count = inputs; this->selected_source = 1; - + pthread_cond_init(&this->display_condition_changed, NULL); pthread_mutex_init(&this->mutex, NULL); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->new_frame->draw = switch_draw; port->port_lock = &this->mutex; port->frame_lock = &this->mutex; this->post.xine_post.video_input[0] = &port->new_port; - + for (i = 1; i < inputs; i++) { port = _x_post_intercept_video_port(&this->post, video_target[0], &input, NULL); port->new_frame->draw = switch_draw; @@ -156,7 +156,7 @@ static post_plugin_t *switch_open_plugin(post_class_t *class_gen, int inputs, port->frame_lock = &this->mutex; this->post.xine_post.video_input[i] = &port->new_port; } - + input_api = &this->parameter_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -187,7 +187,7 @@ static void switch_class_dispose(post_class_t *class_gen) static void switch_dispose(post_plugin_t *this_gen) { post_switch_t *this = (post_switch_t *)this_gen; - + if (_x_post_dispose(this_gen)) { pthread_cond_destroy(&this->display_condition_changed); pthread_mutex_destroy(&this->mutex); @@ -205,7 +205,7 @@ static int switch_set_parameters(xine_post_t *this_gen, void *param_gen) { post_switch_t *this = (post_switch_t *)this_gen; switch_parameter_t *param = (switch_parameter_t *)param_gen; - + if (param->select > this->source_count) return 0; pthread_mutex_lock(&this->mutex); this->selected_source = param->select; @@ -218,7 +218,7 @@ static int switch_get_parameters(xine_post_t *this_gen, void *param_gen) { post_switch_t *this = (post_switch_t *)this_gen; switch_parameter_t *param = (switch_parameter_t *)param_gen; - + param->select = this->selected_source; return 1; } @@ -241,7 +241,7 @@ static int switch_draw(vo_frame_t *frame, xine_stream_t *stream) for (source_num = 1; source_num <= this->source_count; source_num++) if (this->post.xine_post.video_input[source_num-1] == frame->port) break; _x_assert(source_num <= this->source_count); - + pthread_mutex_lock(&this->mutex); /* the original output will probably never see this frame again */ _x_post_frame_u_turn(frame, stream); @@ -268,6 +268,6 @@ static int switch_draw(vo_frame_t *frame, xine_stream_t *stream) skip = 0; pthread_mutex_unlock(&this->mutex); } - + return skip; } diff --git a/src/post/planar/Makefile.am b/src/post/planar/Makefile.am index 4ba6bfa41..751ea390a 100644 --- a/src/post/planar/Makefile.am +++ b/src/post/planar/Makefile.am @@ -1,12 +1,13 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common POSTPROC_INT_LIB = $(top_builddir)/src/libffmpeg/libavcodec/libpostproc/libpostprocess.la if HAVE_FFMPEG postproc_lib = $(FFMPEG_POSTPROC_LIBS) -ff_cflags = $(FFMPEG_POSTPROC_CFLAGS) +ff_cflags = $(FFMPEG_CFLAGS) $(FFMPEG_POSTPROC_CFLAGS) else -ff_cflags = -I$(top_srcdir)/src/libffmpeg/libavcodec/libpostproc +ff_cflags = -I$(top_srcdir)/src/libffmpeg/libavcodec postproc_lib = $(POSTPROC_INT_LIB) postproc_dep = $(postproc_lib) endif diff --git a/src/post/planar/boxblur.c b/src/post/planar/boxblur.c index b7a6f524f..ceeba3b40 100644 --- a/src/post/planar/boxblur.c +++ b/src/post/planar/boxblur.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" @@ -32,7 +36,7 @@ void *boxblur_init_plugin(xine_t *xine, void *); typedef struct post_plugin_boxblur_s post_plugin_boxblur_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct boxblur_parameters_s { @@ -47,13 +51,13 @@ typedef struct boxblur_parameters_s { * description of params struct */ START_PARAM_DESCR( boxblur_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_INT, luma_radius, NULL, 0, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, luma_radius, NULL, 0, 10, 0, "radius of luma blur" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, luma_power, NULL, 0, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, luma_power, NULL, 0, 10, 0, "power of luma blur" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_radius, NULL, -1, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_radius, NULL, -1, 10, 0, "radius of chroma blur (-1 = same as luma)" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_power, NULL, -1, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_power, NULL, -1, 10, 0, "power of chroma blur (-1 = same as luma)" ) END_PARAM_DESCR( param_descr ) @@ -92,7 +96,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } @@ -140,7 +144,7 @@ void *boxblur_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = boxblur_open_plugin; class->get_identifier = boxblur_get_identifier; class->get_description = boxblur_get_description; @@ -154,19 +158,19 @@ static post_plugin_t *boxblur_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)xine_xmalloc(sizeof(post_plugin_boxblur_t)); + post_plugin_boxblur_t *this = calloc(1, sizeof(post_plugin_boxblur_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, 1); - + this->params.luma_radius = 2; this->params.luma_power = 1; this->params.chroma_radius = -1; @@ -177,7 +181,7 @@ static post_plugin_t *boxblur_open_plugin(post_class_t *class_gen, int inputs, port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->intercept_frame = boxblur_intercept_frame; port->new_frame->draw = boxblur_draw; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -186,11 +190,11 @@ static post_plugin_t *boxblur_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "boxblured video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = boxblur_dispose; - + return &this->post; } @@ -213,7 +217,7 @@ static void boxblur_class_dispose(post_class_t *class_gen) static void boxblur_dispose(post_plugin_t *this_gen) { post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)this_gen; - + if (_x_post_dispose(this_gen)) { pthread_mutex_destroy(&this->lock); free(this); @@ -258,7 +262,7 @@ static inline void blur(uint8_t *dst, uint8_t *src, int w, int radius, int dstSt static inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int power, int dstStep, int srcStep){ uint8_t temp[2][4096]; uint8_t *a= temp[0], *b=temp[1]; - + if(radius){ blur(a, src, w, radius, 1, srcStep); for(; power>2; power--){ @@ -282,9 +286,9 @@ static inline void blur2(uint8_t *dst, uint8_t *src, int w, int radius, int powe static void hBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){ int y; - + if(radius==0 && dst==src) return; - + for(y=0; y<h; y++){ blur2(dst + y*dstStride, src + y*srcStride, w, radius, power, 1, 1); } @@ -292,7 +296,7 @@ static void hBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int s static void vBlur(uint8_t *dst, uint8_t *src, int w, int h, int dstStride, int srcStride, int radius, int power){ int x; - + if(radius==0 && dst==src) return; for(x=0; x<w; x++){ @@ -341,25 +345,25 @@ static int boxblur_draw(vo_frame_t *frame, xine_stream_t *stream) pthread_mutex_lock (&this->lock); - chroma_radius = (this->params.chroma_radius != -1) ? this->params.chroma_radius : + chroma_radius = (this->params.chroma_radius != -1) ? this->params.chroma_radius : this->params.luma_radius; - chroma_power = (this->params.chroma_power != -1) ? this->params.chroma_power : + chroma_power = (this->params.chroma_power != -1) ? this->params.chroma_power : this->params.luma_power; cw = yv12_frame->width/2; ch = yv12_frame->height/2; - hBlur(out_frame->base[0], yv12_frame->base[0], yv12_frame->width, yv12_frame->height, + hBlur(out_frame->base[0], yv12_frame->base[0], yv12_frame->width, yv12_frame->height, out_frame->pitches[0], yv12_frame->pitches[0], this->params.luma_radius, this->params.luma_power); - hBlur(out_frame->base[1], yv12_frame->base[1], cw,ch, + hBlur(out_frame->base[1], yv12_frame->base[1], cw,ch, out_frame->pitches[1], yv12_frame->pitches[1], chroma_radius, chroma_power); - hBlur(out_frame->base[2], yv12_frame->base[2], cw,ch, + hBlur(out_frame->base[2], yv12_frame->base[2], cw,ch, out_frame->pitches[2], yv12_frame->pitches[2], chroma_radius, chroma_power); - vBlur(out_frame->base[0], out_frame->base[0], yv12_frame->width, yv12_frame->height, + vBlur(out_frame->base[0], out_frame->base[0], yv12_frame->width, yv12_frame->height, out_frame->pitches[0], out_frame->pitches[0], this->params.luma_radius, this->params.luma_power); - vBlur(out_frame->base[1], out_frame->base[1], cw,ch, + vBlur(out_frame->base[1], out_frame->base[1], cw,ch, out_frame->pitches[1], out_frame->pitches[1], chroma_radius, chroma_power); - vBlur(out_frame->base[2], out_frame->base[2], cw,ch, + vBlur(out_frame->base[2], out_frame->base[2], cw,ch, out_frame->pitches[2], out_frame->pitches[2], chroma_radius, chroma_power); pthread_mutex_unlock (&this->lock); diff --git a/src/post/planar/denoise3d.c b/src/post/planar/denoise3d.c index fb3c1102b..2073151b4 100644 --- a/src/post/planar/denoise3d.c +++ b/src/post/planar/denoise3d.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" @@ -40,7 +44,7 @@ typedef struct post_plugin_denoise3d_s post_plugin_denoise3d_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct denoise3d_parameters_s { @@ -54,11 +58,11 @@ typedef struct denoise3d_parameters_s { * description of params struct */ START_PARAM_DESCR( denoise3d_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, luma, NULL, 0, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, luma, NULL, 0, 10, 0, "spatial luma strength" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, chroma, NULL, 0, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, chroma, NULL, 0, 10, 0, "spatial chroma strength" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, time, NULL, 0, 10, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, time, NULL, 0, 10, 0, "temporal strength" ) END_PARAM_DESCR( param_descr ) @@ -125,7 +129,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } @@ -180,7 +184,7 @@ void *denoise3d_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = denoise3d_open_plugin; class->get_identifier = denoise3d_get_identifier; class->get_description = denoise3d_get_description; @@ -194,19 +198,19 @@ static post_plugin_t *denoise3d_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_denoise3d_t *this = (post_plugin_denoise3d_t *)xine_xmalloc(sizeof(post_plugin_denoise3d_t)); + post_plugin_denoise3d_t *this = calloc(1, sizeof(post_plugin_denoise3d_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } _x_post_init(&this->post, 0, 1); - + this->params.luma = PARAM1_DEFAULT; this->params.chroma = PARAM2_DEFAULT; this->params.time = PARAM3_DEFAULT; @@ -218,7 +222,7 @@ static post_plugin_t *denoise3d_open_plugin(post_class_t *class_gen, int inputs, port->new_port.close = denoise3d_close; port->intercept_frame = denoise3d_intercept_frame; port->new_frame->draw = denoise3d_draw; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -227,13 +231,13 @@ static post_plugin_t *denoise3d_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "denoise3d video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = denoise3d_dispose; set_parameters ((xine_post_t *)this, &this->params); - + return &this->post; } @@ -256,7 +260,7 @@ static void denoise3d_class_dispose(post_class_t *class_gen) static void denoise3d_dispose(post_plugin_t *this_gen) { post_plugin_denoise3d_t *this = (post_plugin_denoise3d_t *)this_gen; - + if (_x_post_dispose(this_gen)) { pthread_mutex_destroy(&this->lock); free(this); @@ -288,10 +292,10 @@ static int denoise3d_intercept_frame(post_video_port_t *port, vo_frame_t *frame) #define LowPass(Prev, Curr, Coef) (((Prev)*Coef[Prev - Curr] + (Curr)*(65536-(Coef[Prev - Curr]))) / 65536) -static void deNoise(unsigned char *Frame, - unsigned char *FramePrev, - unsigned char *FrameDest, - unsigned char *LineAnt, +static void deNoise(unsigned char *Frame, + unsigned char *FramePrev, + unsigned char *FrameDest, + unsigned char *LineAnt, int W, int H, int sStride, int pStride, int dStride, int *Horizontal, int *Vertical, int *Temporal) { @@ -349,15 +353,15 @@ static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream) yv12_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS); - + _x_post_frame_copy_down(frame, yv12_frame); - + yuy2_to_yv12(frame->base[0], frame->pitches[0], yv12_frame->base[0], yv12_frame->pitches[0], yv12_frame->base[1], yv12_frame->pitches[1], yv12_frame->base[2], yv12_frame->pitches[2], frame->width, frame->height); - + } else { yv12_frame = frame; yv12_frame->lock(yv12_frame); @@ -397,7 +401,7 @@ static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream) pthread_mutex_unlock (&this->lock); skip = out_frame->draw(out_frame, stream); - + _x_post_frame_copy_up(frame, out_frame); out_frame->free(out_frame); diff --git a/src/post/planar/eq.c b/src/post/planar/eq.c index b2cf6e50f..73607b8a1 100644 --- a/src/post/planar/eq.c +++ b/src/post/planar/eq.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * Copyright (C) Richard Felker */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" @@ -43,7 +47,7 @@ static void process_MMX(unsigned char *dest, int dstride, unsigned char *src, in brvec[0] = brvec[1] = brvec[2] = brvec[3] = brightness; contvec[0] = contvec[1] = contvec[2] = contvec[3] = contrast; - + while (h--) { asm volatile ( "movq (%5), %%mm3 \n\t" @@ -121,7 +125,7 @@ void *eq_init_plugin(xine_t *xine, void *); typedef struct post_plugin_eq_s post_plugin_eq_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct eq_parameters_s { @@ -134,9 +138,9 @@ typedef struct eq_parameters_s { * description of params struct */ START_PARAM_DESCR( eq_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_INT, brightness, NULL, -100, 100, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, brightness, NULL, -100, 100, 0, "brightness" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, contrast, NULL, -100, 100, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, contrast, NULL, -100, 100, 0, "contrast" ) END_PARAM_DESCR( param_descr ) @@ -175,7 +179,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } @@ -232,7 +236,7 @@ void *eq_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = eq_open_plugin; class->get_identifier = eq_get_identifier; class->get_description = eq_get_description; @@ -246,12 +250,12 @@ static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_eq_t *this = (post_plugin_eq_t *)xine_xmalloc(sizeof(post_plugin_eq_t)); + post_plugin_eq_t *this = calloc(1, sizeof(post_plugin_eq_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; @@ -259,7 +263,7 @@ static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs, process = process_C; #if defined(ARCH_X86) || defined(ARCH_X86_64) - if( xine_mm_accel() & MM_ACCEL_X86_MMX ) + if( xine_mm_accel() & MM_ACCEL_X86_MMX ) process = process_MMX; #endif @@ -269,14 +273,14 @@ static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs, this->params.contrast = 0; pthread_mutex_init (&this->lock, NULL); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->new_port.get_property = eq_get_property; port->new_port.set_property = eq_set_property; port->intercept_frame = eq_intercept_frame; port->new_frame->draw = eq_draw; - input_api = &this->params_input; + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; input_api->data = &post_api; @@ -284,11 +288,11 @@ static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "eqd video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = eq_dispose; - + return &this->post; } @@ -370,15 +374,15 @@ static int eq_draw(vo_frame_t *frame, xine_stream_t *stream) yv12_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS); - + _x_post_frame_copy_down(frame, yv12_frame); - + yuy2_to_yv12(frame->base[0], frame->pitches[0], yv12_frame->base[0], yv12_frame->pitches[0], yv12_frame->base[1], yv12_frame->pitches[1], yv12_frame->base[2], yv12_frame->pitches[2], frame->width, frame->height); - + } else { yv12_frame = frame; yv12_frame->lock(yv12_frame); @@ -404,7 +408,7 @@ static int eq_draw(vo_frame_t *frame, xine_stream_t *stream) pthread_mutex_unlock (&this->lock); skip = out_frame->draw(out_frame, stream); - + _x_post_frame_copy_up(frame, out_frame); out_frame->free(out_frame); diff --git a/src/post/planar/eq2.c b/src/post/planar/eq2.c index 6b277c347..542ea7bad 100644 --- a/src/post/planar/eq2.c +++ b/src/post/planar/eq2.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2006 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -25,6 +25,10 @@ * Richard Felker (original MMX contrast/brightness code (vf_eq.c)) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" @@ -110,7 +114,7 @@ void affine_1d_MMX (eq2_param_t *par, unsigned char *dst, unsigned char *src, int pel; short brvec[4]; short contvec[4]; - + contrast = (int) (par->c * 256 * 16); brightness = ((int) (100.0 * par->b + 100.0) * 511) / 200 - 128 - contrast / 32; @@ -265,7 +269,7 @@ void *eq2_init_plugin(xine_t *xine, void *); typedef struct post_plugin_eq2_s post_plugin_eq2_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct eq2_parameters_s { @@ -284,19 +288,19 @@ typedef struct eq2_parameters_s { * description of params struct */ START_PARAM_DESCR( eq2_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, gamma, NULL, 0, 5, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, gamma, NULL, 0, 5, 0, "gamma" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, brightness, NULL, -1, 1, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, brightness, NULL, -1, 1, 0, "brightness" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, contrast, NULL, 0, 2, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, contrast, NULL, 0, 2, 0, "contrast" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, saturation, NULL, 0, 2, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, saturation, NULL, 0, 2, 0, "saturation" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, rgamma, NULL, 0, 5, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, rgamma, NULL, 0, 5, 0, "rgamma" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, ggamma, NULL, 0, 5, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, ggamma, NULL, 0, 5, 0, "ggamma" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, bgamma, NULL, 0, 5, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, bgamma, NULL, 0, 5, 0, "bgamma" ) END_PARAM_DESCR( param_descr ) @@ -308,7 +312,7 @@ struct post_plugin_eq2_s { /* private data */ eq2_parameters_t params; xine_post_in_t params_input; - + vf_eq2_t eq2; pthread_mutex_t lock; @@ -348,7 +352,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } @@ -413,7 +417,7 @@ void *eq2_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = eq2_open_plugin; class->get_identifier = eq2_get_identifier; class->get_description = eq2_get_description; @@ -427,50 +431,37 @@ static post_plugin_t *eq2_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_eq2_t *this = (post_plugin_eq2_t *)xine_xmalloc(sizeof(post_plugin_eq2_t)); + post_plugin_eq2_t *this = calloc(1, sizeof(post_plugin_eq2_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; - vf_eq2_t *eq2; - int i; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, 1); - eq2 = &this->eq2; - for (i = 0; i < 3; i++) { - eq2->buf[i] = NULL; - eq2->buf_w[i] = 0; - eq2->buf_h[i] = 0; - - eq2->param[i].adjust = NULL; - eq2->param[i].c = 1.0; - eq2->param[i].b = 0.0; - eq2->param[i].g = 1.0; - eq2->param[i].lut_clean = 0; - } + memset(&this->eq2, 0, sizeof(this->eq2)); - eq2->gamma = this->params.gamma = 1.0; - eq2->contrast = this->params.contrast = 1.0; - eq2->brightness = this->params.brightness = 0.0; - eq2->saturation = this->params.saturation = 1.0; - eq2->rgamma = this->params.rgamma = 1.0; - eq2->ggamma = this->params.ggamma = 1.0; - eq2->bgamma = this->params.bgamma = 1.0; + this->eq2.gamma = this->params.gamma = 1.0; + this->eq2.contrast = this->params.contrast = 1.0; + this->eq2.brightness = this->params.brightness = 0.0; + this->eq2.saturation = this->params.saturation = 1.0; + this->eq2.rgamma = this->params.rgamma = 1.0; + this->eq2.ggamma = this->params.ggamma = 1.0; + this->eq2.bgamma = this->params.bgamma = 1.0; pthread_mutex_init(&this->lock, NULL); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->new_port.get_property = eq2_get_property; port->new_port.set_property = eq2_set_property; port->intercept_frame = eq2_intercept_frame; port->new_frame->draw = eq2_draw; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -479,13 +470,13 @@ static post_plugin_t *eq2_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "eqd video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = eq2_dispose; set_parameters ((xine_post_t *)this, &this->params); - + return &this->post; } @@ -575,15 +566,15 @@ static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream) yv12_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS); - + _x_post_frame_copy_down(frame, yv12_frame); - + yuy2_to_yv12(frame->base[0], frame->pitches[0], yv12_frame->base[0], yv12_frame->pitches[0], yv12_frame->base[1], yv12_frame->pitches[1], yv12_frame->base[2], yv12_frame->pitches[2], frame->width, frame->height); - + } else { yv12_frame = frame; yv12_frame->lock(yv12_frame); @@ -613,7 +604,7 @@ static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream) pthread_mutex_unlock (&this->lock); skip = out_frame->draw(out_frame, stream); - + _x_post_frame_copy_up(frame, out_frame); out_frame->free(out_frame); diff --git a/src/post/planar/expand.c b/src/post/planar/expand.c index 67d449153..cc189118f 100644 --- a/src/post/planar/expand.c +++ b/src/post/planar/expand.c @@ -1,23 +1,23 @@ /* * Copyright (C) 2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * $Id: + * $Id: * * expand video filter by James Stembridge 24/05/2003 * improved by Michael Roitzsch @@ -58,7 +58,7 @@ * bars to the left and right of the image and will then set up cropping * to efficiently remove the black border around the 4:3 image, which the * plugin would produce otherwise for this case. - */ + */ /* plugin class initialization function */ @@ -85,9 +85,9 @@ END_PARAM_DESCR(expand_param_descr) typedef struct post_expand_s { post_plugin_t post; - + xine_post_in_t parameter_input; - + int enable_automatic_shift; int overlay_y_offset; double aspect; @@ -114,8 +114,8 @@ static int expand_get_parameters(xine_post_t *this_gen, void *param_g static char *expand_get_help (void); /* replaced video port functions */ -static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width, - uint32_t height, double ratio, +static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width, + uint32_t height, double ratio, int format, int flags); /* replaced vo_frame functions */ @@ -131,15 +131,15 @@ static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen void *expand_init_plugin(xine_t *xine, void *data) { post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t)); - + if (!class) return NULL; - + class->open_plugin = expand_open_plugin; class->get_identifier = expand_get_identifier; class->get_description = expand_get_description; class->dispose = expand_class_dispose; - + return class; } @@ -148,46 +148,46 @@ static post_plugin_t *expand_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_expand_t *this = (post_expand_t *)xine_xmalloc(sizeof(post_expand_t)); + post_expand_t *this = calloc(1, sizeof(post_expand_t)); post_in_t *input; xine_post_in_t *input_param; post_out_t *output; post_video_port_t *port; static xine_post_api_t post_api = { expand_set_parameters, expand_get_parameters, expand_get_param_descr, expand_get_help }; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, 1); - + this->enable_automatic_shift = 0; this->overlay_y_offset = 0; this->aspect = 4.0 / 3.0; this->centre_cut_out_mode = 0; this->cropping_active = 0; - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->new_port.get_frame = expand_get_frame; port->new_frame->draw = expand_draw; port->intercept_ovl = expand_intercept_ovl; port->new_manager->add_event = expand_overlay_add_event; - + input_param = &this->parameter_input; input_param->name = "parameters"; input_param->type = XINE_POST_DATA_PARAMETERS; input_param->data = &post_api; xine_list_push_back(this->post.input, input_param); - + input->xine_in.name = "video"; output->xine_out.name = "expanded video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = expand_dispose; - + return &this->post; } @@ -210,7 +210,7 @@ static void expand_class_dispose(post_class_t *class_gen) static void expand_dispose(post_plugin_t *this_gen) { post_expand_t *this = (post_expand_t *)this_gen; - + if (_x_post_dispose(this_gen)) free(this); } @@ -238,12 +238,12 @@ static int expand_get_parameters(xine_post_t *this_gen, void *param_gen) { post_expand_t *this = (post_expand_t *)this_gen; expand_parameters_t *param = (expand_parameters_t *)param_gen; - + param->enable_automatic_shift = this->enable_automatic_shift; param->overlay_y_offset = this->overlay_y_offset; param->aspect = this->aspect; param->centre_cut_out_mode = this->centre_cut_out_mode; - + return 1; } @@ -271,7 +271,7 @@ static int is_pixel_black(vo_frame_t *frame, int x, int y) if (x >= frame->width) x = frame->width - 1; if (y < 0) y = 0; if (y >= frame->height) y = frame->height - 1; - + switch (frame->format) { case XINE_IMGFMT_YV12: @@ -279,7 +279,7 @@ static int is_pixel_black(vo_frame_t *frame, int x, int y) Cr = *(frame->base[ 1 ] + frame->pitches[ 1 ] * y / 2 + x / 2); Cb = *(frame->base[ 2 ] + frame->pitches[ 2 ] * y / 2 + x / 2); break; - + case XINE_IMGFMT_YUY2: Y = *(frame->base[ 0 ] + frame->pitches[ 0 ] * y + x * 2 + 0); x &= ~1; @@ -340,8 +340,8 @@ static int expand_draw(vo_frame_t *frame, xine_stream_t *stream) } -static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width, - uint32_t height, double ratio, +static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width, + uint32_t height, double ratio, int format, int flags) { post_video_port_t *port = (post_video_port_t *)port_gen; @@ -349,27 +349,27 @@ static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width, vo_frame_t *frame; uint32_t new_height, top_bar_height; int i, end; - + _x_post_rewire(&this->post); - + if (ratio <= 0.0) ratio = (double)width / (double)height; - + /* Calculate height of expanded frame */ new_height = (double)height * ratio / this->aspect; new_height = (new_height + 1) & ~1; top_bar_height = (new_height - height) / 2; top_bar_height = (top_bar_height + 1) & ~1; - + this->top_bar_height = top_bar_height; if (new_height > height && (format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2)) { frame = port->original_port->get_frame(port->original_port, width, new_height, this->aspect, format, flags); - + _x_post_inc_usage(port); frame = _x_post_intercept_video_frame(frame, port); - + /* paint black bars in the top and bottom of the frame and hide these * from the decoders by modifying the pointers to and * the size of the drawing area */ @@ -414,7 +414,7 @@ static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width, width, height, ratio, format, flags); /* no need to intercept this one, we are not going to do anything with it */ } - + return frame; } @@ -424,7 +424,7 @@ static int expand_intercept_ovl(post_video_port_t *port) post_expand_t *this = (post_expand_t *)port->post; if (this->centre_cut_out_mode && this->cropping_active) return 0; - + /* we always intercept overlay manager */ return 1; } @@ -435,7 +435,7 @@ static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen, void video_overlay_event_t *event = (video_overlay_event_t *)event_gen; post_video_port_t *port = _x_post_ovl_manager_to_port(this_gen); post_expand_t *this = (post_expand_t *)port->post; - + if (event->event_type == OVERLAY_EVENT_SHOW) { switch (event->object.object_type) { case 0: @@ -450,6 +450,6 @@ static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen, void event->object.overlay->y += this->top_bar_height; } } - + return port->original_manager->add_event(port->original_manager, event_gen); } diff --git a/src/post/planar/fill.c b/src/post/planar/fill.c index 32a9d5dfb..dd8b83c82 100644 --- a/src/post/planar/fill.c +++ b/src/post/planar/fill.c @@ -12,7 +12,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -49,15 +49,15 @@ static int fill_draw(vo_frame_t *frame, xine_stream_t *stream); void *fill_init_plugin(xine_t *xine, void *data) { post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t)); - + if (!class) return NULL; - + class->open_plugin = fill_open_plugin; class->get_identifier = fill_get_identifier; class->get_description = fill_get_description; class->dispose = fill_class_dispose; - + return class; } @@ -66,29 +66,29 @@ static post_plugin_t *fill_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_t *this = (post_plugin_t *)xine_xmalloc(sizeof(post_plugin_t)); + post_plugin_t *this = calloc(1, sizeof(post_plugin_t)); post_in_t *input; post_out_t *output; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(this, 0, 1); - + port = _x_post_intercept_video_port(this, video_target[0], &input, &output); port->new_port.get_frame = fill_get_frame; port->new_frame->draw = fill_draw; - + input->xine_in.name = "video"; output->xine_out.name = "cropped video"; - + this->xine_post.video_input[0] = &port->new_port; - + this->dispose = fill_dispose; - + return this; } @@ -114,33 +114,33 @@ static void fill_dispose(post_plugin_t *this) } -static vo_frame_t *fill_get_frame(xine_video_port_t *port_gen, uint32_t width, - uint32_t height, double ratio, +static vo_frame_t *fill_get_frame(xine_video_port_t *port_gen, uint32_t width, + uint32_t height, double ratio, int format, int flags) { post_video_port_t *port = (post_video_port_t *)port_gen; post_plugin_t *this = port->post; vo_frame_t *frame; - + _x_post_rewire(this); - + if (ratio <= 0.0) ratio = (double)width / (double)height; - + if ((ratio > 4.0/3.0) && (format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2)) { frame = port->original_port->get_frame(port->original_port, width, height, 4.0/3.0, format, flags); - + _x_post_inc_usage(port); frame = _x_post_intercept_video_frame(frame, port); - + frame->ratio = ratio; } else { frame = port->original_port->get_frame(port->original_port, width, height, ratio, format, flags); /* no need to intercept this one, we are not going to do anything with it */ } - + return frame; } @@ -148,13 +148,13 @@ static vo_frame_t *fill_get_frame(xine_video_port_t *port_gen, uint32_t width, static int fill_draw(vo_frame_t *frame, xine_stream_t *stream) { int skip, new_width; - + new_width = (4.0*frame->width) / (3.0*frame->ratio); - + frame->crop_left += (frame->width - new_width) / 2; frame->crop_right += (frame->width + 1 - new_width) / 2; frame->ratio = 4.0/3.0; - + _x_post_frame_copy_down(frame, frame->next); skip = frame->next->draw(frame->next, stream); _x_post_frame_copy_up(frame, frame->next); diff --git a/src/post/planar/invert.c b/src/post/planar/invert.c index 1aa5c2a2e..820221cf5 100644 --- a/src/post/planar/invert.c +++ b/src/post/planar/invert.c @@ -1,23 +1,23 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + /* * simple video inverter plugin */ @@ -50,15 +50,15 @@ static int invert_draw(vo_frame_t *frame, xine_stream_t *stream); void *invert_init_plugin(xine_t *xine, void *data) { post_class_t *class = (post_class_t *)malloc(sizeof(post_class_t)); - + if (!class) return NULL; - + class->open_plugin = invert_open_plugin; class->get_identifier = invert_get_identifier; class->get_description = invert_get_description; class->dispose = invert_class_dispose; - + return class; } @@ -67,27 +67,27 @@ static post_plugin_t *invert_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_t *this = (post_plugin_t *)xine_xmalloc(sizeof(post_plugin_t)); + post_plugin_t *this = calloc(1, sizeof(post_plugin_t)); post_in_t *input; post_out_t *output; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(this, 0, 1); - + port = _x_post_intercept_video_port(this, video_target[0], &input, &output); port->intercept_frame = invert_intercept_frame; port->new_frame->draw = invert_draw; input->xine_in.name = "video"; output->xine_out.name = "inverted video"; this->xine_post.video_input[0] = &port->new_port; - + this->dispose = invert_dispose; - + return this; } @@ -125,18 +125,18 @@ static int invert_draw(vo_frame_t *frame, xine_stream_t *stream) post_video_port_t *port = (post_video_port_t *)frame->port; vo_frame_t *inverted_frame; int size, i, skip; - + if (frame->bad_frame) { _x_post_frame_copy_down(frame, frame->next); skip = frame->next->draw(frame->next, stream); _x_post_frame_copy_up(frame, frame->next); return skip; } - + inverted_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS); _x_post_frame_copy_down(frame, inverted_frame); - + switch (inverted_frame->format) { case XINE_IMGFMT_YUY2: size = inverted_frame->pitches[0] * inverted_frame->height; @@ -157,10 +157,10 @@ static int invert_draw(vo_frame_t *frame, xine_stream_t *stream) for (i = 0; i < size; i++) inverted_frame->base[2][i] = 0xff - frame->base[2][i]; break; - } + } skip = inverted_frame->draw(inverted_frame, stream); _x_post_frame_copy_up(frame, inverted_frame); inverted_frame->free(inverted_frame); - + return skip; } diff --git a/src/post/planar/noise.c b/src/post/planar/noise.c index 8c04f2e72..0f1fe98f7 100644 --- a/src/post/planar/noise.c +++ b/src/post/planar/noise.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * is copyright 2002 Michael Niedermayer <michaelni@gmx.at> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" @@ -311,7 +315,7 @@ void *noise_init_plugin(xine_t *xine, void *); typedef struct post_plugin_noise_s post_plugin_noise_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct noise_parameters_s { int luma_strength, chroma_strength, @@ -325,15 +329,15 @@ static char *enum_quality[] = {"fixed", "temporal", "averaged temporal", NULL}; * description of params struct */ START_PARAM_DESCR( noise_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_INT, luma_strength, NULL, 0, 100, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, luma_strength, NULL, 0, 100, 0, "Amount of noise to add to luma channel" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_strength, NULL, 0, 100, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_strength, NULL, 0, 100, 0, "Amount of noise to add to chroma channel" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, quality, enum_quality, 0, 0, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, quality, enum_quality, 0, 0, 0, "Quality level of noise" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, type, enum_types, 0, 0, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, type, enum_types, 0, 0, 0, "Type of noise" ) -PARAM_ITEM( POST_PARAM_TYPE_BOOL, pattern, NULL, 0, 1, 0, +PARAM_ITEM( POST_PARAM_TYPE_BOOL, pattern, NULL, 0, 1, 0, "Mix random noise with a (semi)regular pattern" ) END_PARAM_DESCR( param_descr ) @@ -350,7 +354,7 @@ struct post_plugin_noise_s { }; -static int set_parameters (xine_post_t *this_gen, void *param_gen) +static int set_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_noise_t *this = (post_plugin_noise_t *)this_gen; noise_parameters_t *param = (noise_parameters_t *)param_gen; @@ -372,7 +376,7 @@ static int set_parameters (xine_post_t *this_gen, void *param_gen) return 1; } -static int get_parameters (xine_post_t *this_gen, void *param_gen) +static int get_parameters (xine_post_t *this_gen, void *param_gen) { post_plugin_noise_t *this = (post_plugin_noise_t *)this_gen; noise_parameters_t *param = (noise_parameters_t *)param_gen; @@ -391,7 +395,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) pthread_mutex_unlock (&this->lock); return 1; } - + static xine_post_api_descr_t *get_param_descr (void) { return ¶m_descr; } @@ -449,7 +453,7 @@ void *noise_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = noise_open_plugin; class->get_identifier = noise_get_identifier; class->get_description = noise_get_description; @@ -471,18 +475,18 @@ static post_plugin_t *noise_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_noise_t *this = (post_plugin_noise_t *)xine_xmalloc(sizeof(post_plugin_noise_t)); + post_plugin_noise_t *this = calloc(1, sizeof(post_plugin_noise_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; noise_parameters_t params; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } - + _x_post_init(&this->post, 0, 1); memset(¶ms, 0, sizeof(noise_parameters_t)); @@ -492,11 +496,11 @@ static post_plugin_t *noise_open_plugin(post_class_t *class_gen, int inputs, params.quality = 2; pthread_mutex_init(&this->lock, NULL); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->intercept_frame = noise_intercept_frame; port->new_frame->draw = noise_draw; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -505,13 +509,13 @@ static post_plugin_t *noise_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "filtered video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = noise_dispose; set_parameters ((xine_post_t *)this, ¶ms); - + return &this->post; } @@ -555,7 +559,7 @@ static int noise_draw(vo_frame_t *frame, xine_stream_t *stream) vo_frame_t *out_frame; int skip; - if (frame->bad_frame || + if (frame->bad_frame || (this->params[0].strength == 0 && this->params[1].strength == 0)) { _x_post_frame_copy_down(frame, frame->next); skip = frame->next->draw(frame->next, stream); @@ -565,26 +569,26 @@ static int noise_draw(vo_frame_t *frame, xine_stream_t *stream) frame->lock(frame); out_frame = port->original_port->get_frame(port->original_port, - frame->width, frame->height, frame->ratio, frame->format, + frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS); _x_post_frame_copy_down(frame, out_frame); pthread_mutex_lock (&this->lock); if (frame->format == XINE_IMGFMT_YV12) { - noise(out_frame->base[0], frame->base[0], - out_frame->pitches[0], frame->pitches[0], + noise(out_frame->base[0], frame->base[0], + out_frame->pitches[0], frame->pitches[0], frame->width, frame->height, &this->params[0]); - noise(out_frame->base[1], frame->base[1], - out_frame->pitches[1], frame->pitches[1], + noise(out_frame->base[1], frame->base[1], + out_frame->pitches[1], frame->pitches[1], frame->width/2, frame->height/2, &this->params[1]); - noise(out_frame->base[2], frame->base[2], - out_frame->pitches[2], frame->pitches[2], + noise(out_frame->base[2], frame->base[2], + out_frame->pitches[2], frame->pitches[2], frame->width/2, frame->height/2, &this->params[1]); } else { // Chroma strength is ignored for YUY2. - noise(out_frame->base[0], frame->base[0], - out_frame->pitches[0], frame->pitches[0], + noise(out_frame->base[0], frame->base[0], + out_frame->pitches[0], frame->pitches[0], frame->width * 2, frame->height, &this->params[0]); } diff --git a/src/post/planar/planar.c b/src/post/planar/planar.c index 5907d58e5..112ebdf0d 100644 --- a/src/post/planar/planar.c +++ b/src/post/planar/planar.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,6 +20,10 @@ * catalog for planar post plugins */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" @@ -55,7 +59,7 @@ extern void *noise_init_plugin(xine_t *xine, void *); static const post_info_t noise_special_info = { XINE_POST_TYPE_VIDEO_FILTER }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST, 9, "expand", XINE_VERSION_CODE, &expand_special_info, &expand_init_plugin }, { PLUGIN_POST, 9, "fill", XINE_VERSION_CODE, &fill_special_info, &fill_init_plugin }, { PLUGIN_POST, 9, "invert", XINE_VERSION_CODE, &invert_special_info, &invert_init_plugin }, diff --git a/src/post/planar/pp.c b/src/post/planar/pp.c index e13119311..c9db99f2c 100644 --- a/src/post/planar/pp.c +++ b/src/post/planar/pp.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,12 +20,21 @@ * plugin for ffmpeg libpostprocess */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" -#include "postprocess.h" #include <pthread.h> +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <postprocess.h> +#else +# include <libpostproc/postprocess.h> +#endif + #define PP_STRING_SIZE 256 /* size of pp mode string (including all options) */ /* plugin class initialization function */ @@ -34,7 +43,7 @@ void *pp_init_plugin(xine_t *xine, void *); typedef struct post_plugin_pp_s post_plugin_pp_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct pp_parameters_s { @@ -47,9 +56,9 @@ typedef struct pp_parameters_s { * description of params struct */ START_PARAM_DESCR( pp_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_INT, quality, NULL, 0, PP_QUALITY_MAX, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, quality, NULL, 0, PP_QUALITY_MAX, 0, "postprocessing quality" ) -PARAM_ITEM( POST_PARAM_TYPE_CHAR, mode, NULL, 0, 0, 0, +PARAM_ITEM( POST_PARAM_TYPE_CHAR, mode, NULL, 0, 0, 0, "mode string (overwrites all other options except quality)" ) END_PARAM_DESCR( param_descr ) @@ -96,30 +105,27 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } static char * get_help (void) { - char *help1 = + char *help1 = _("FFmpeg libpostprocess plugin.\n" "\n" "Parameters\n" "\n"); - + char *help2 = _("\n" "* libpostprocess (C) Michael Niedermayer\n" ); static char *help = NULL; - if( !help ) { - help = malloc( strlen(help1) + strlen(help2) + strlen(pp_help) + 1); - strcpy(help, help1); - strcat(help, pp_help); - strcat(help, help2); - } + if( !help ) + asprintf(&help, "%s%s%s", help1, help2, pp_help); + return help; } @@ -155,7 +161,7 @@ void *pp_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = pp_open_plugin; class->get_identifier = pp_get_identifier; class->get_description = pp_get_description; @@ -169,20 +175,20 @@ static post_plugin_t *pp_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_pp_t *this = (post_plugin_pp_t *)xine_xmalloc(sizeof(post_plugin_pp_t)); + post_plugin_pp_t *this = calloc(1, sizeof(post_plugin_pp_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; uint32_t cpu_caps; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } _x_post_init(&this->post, 0, 1); - + this->params.quality = 3; strcpy(this->params.mode, "de"); @@ -193,18 +199,18 @@ static post_plugin_t *pp_open_plugin(post_class_t *class_gen, int inputs, this->pp_flags |= PP_CPU_CAPS_MMX; if(cpu_caps & MM_ACCEL_X86_MMXEXT) this->pp_flags |= PP_CPU_CAPS_MMX2; - if(cpu_caps & MM_ACCEL_X86_3DNOW) + if(cpu_caps & MM_ACCEL_X86_3DNOW) this->pp_flags |= PP_CPU_CAPS_3DNOW; this->pp_mode = NULL; this->pp_context = NULL; pthread_mutex_init (&this->lock, NULL); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->intercept_frame = pp_intercept_frame; port->new_frame->draw = pp_draw; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -213,11 +219,11 @@ static post_plugin_t *pp_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "pped video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + this->post.dispose = pp_dispose; - + return &this->post; } @@ -277,9 +283,9 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream) yv12_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS); - + _x_post_frame_copy_down(frame, yv12_frame); - + yuy2_to_yv12(frame->base[0], frame->pitches[0], yv12_frame->base[0], yv12_frame->pitches[0], yv12_frame->base[1], yv12_frame->pitches[1], @@ -293,12 +299,12 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream) out_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS); - + _x_post_frame_copy_down(frame, out_frame); pthread_mutex_lock (&this->lock); - if( !this->pp_context || + if( !this->pp_context || this->frame_width != yv12_frame->width || this->frame_height != yv12_frame->height ) { @@ -318,15 +324,15 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream) } if(!this->pp_mode) - this->pp_mode = pp_get_mode_by_name_and_quality(this->params.mode, + this->pp_mode = pp_get_mode_by_name_and_quality(this->params.mode, this->params.quality); if(this->pp_mode) - pp_postprocess(yv12_frame->base, yv12_frame->pitches, - out_frame->base, out_frame->pitches, + pp_postprocess(yv12_frame->base, yv12_frame->pitches, + out_frame->base, out_frame->pitches, (frame->width+7)&(~7), frame->height, NULL, 0, - this->pp_mode, this->pp_context, + this->pp_mode, this->pp_context, 0 /*this->av_frame->pict_type*/); pthread_mutex_unlock (&this->lock); diff --git a/src/post/planar/unsharp.c b/src/post/planar/unsharp.c index b9b791a8e..dbf723577 100644 --- a/src/post/planar/unsharp.c +++ b/src/post/planar/unsharp.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,18 +21,15 @@ * Copyright (C) 2002 Rémi Guyomarch <rguyom@pobox.com> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "xine_internal.h" #include "post.h" #include "xineutils.h" #include <pthread.h> -#ifndef MIN -#define MIN(a,b) (((a)<(b))?(a):(b)) -#endif -#ifndef MAX -#define MAX(a,b) (((a)>(b))?(a):(b)) -#endif - /*===========================================================================*/ #define MIN_MATRIX_SIZE 3 @@ -67,7 +64,7 @@ static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, i uint32_t **SC = fp->SC; uint32_t SR[MAX_MATRIX_SIZE-1], Tmp1, Tmp2; - uint8_t* src2 = src; + uint8_t* src2 = src; int32_t res; int x, y, z; @@ -80,7 +77,7 @@ static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, i if( !fp->amount ) { if( src == dst ) return; - if( dstStride == srcStride ) + if( dstStride == srcStride ) xine_fast_memcpy( dst, src, srcStride*height ); else for( y=0; y<height; y++, dst+=dstStride, src+=srcStride ) @@ -107,7 +104,7 @@ static void unsharp( uint8_t *dst, uint8_t *src, int dstStride, int srcStride, i if( x>=stepsX && y>=stepsY ) { uint8_t* srx = src - stepsY*srcStride + x - stepsX; uint8_t* dsx = dst - stepsY*dstStride + x - stepsX; - + res = (int32_t)*srx + ( ( ( (int32_t)*srx - (int32_t)((Tmp1+halfscale) >> scalebits) ) * amount ) >> 16 ); *dsx = res>255 ? 255 : res<0 ? 0 : (uint8_t)res; } @@ -126,7 +123,7 @@ void *unsharp_init_plugin(xine_t *xine, void *); typedef struct post_plugin_unsharp_s post_plugin_unsharp_t; /* - * this is the struct used by "parameters api" + * this is the struct used by "parameters api" */ typedef struct unsharp_parameters_s { @@ -144,17 +141,17 @@ typedef struct unsharp_parameters_s { * description of params struct */ START_PARAM_DESCR( unsharp_parameters_t ) -PARAM_ITEM( POST_PARAM_TYPE_INT, luma_matrix_width, NULL, 3, 11, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, luma_matrix_width, NULL, 3, 11, 0, "width of the matrix (must be odd)" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, luma_matrix_height, NULL, 3, 11, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, luma_matrix_height, NULL, 3, 11, 0, "height of the matrix (must be odd)" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, luma_amount, NULL, -2, 2, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, luma_amount, NULL, -2, 2, 0, "relative amount of sharpness/blur (=0 disable, <0 blur, >0 sharpen)" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_matrix_width, NULL, 3, 11, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_matrix_width, NULL, 3, 11, 0, "width of the matrix (must be odd)" ) -PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_matrix_height, NULL, 3, 11, 0, +PARAM_ITEM( POST_PARAM_TYPE_INT, chroma_matrix_height, NULL, 3, 11, 0, "height of the matrix (must be odd)" ) -PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, chroma_amount, NULL, -2, 2, 0, +PARAM_ITEM( POST_PARAM_TYPE_DOUBLE, chroma_amount, NULL, -2, 2, 0, "relative amount of sharpness/blur (=0 disable, <0 blur, >0 sharpen)" ) END_PARAM_DESCR( param_descr ) @@ -208,7 +205,7 @@ static int get_parameters (xine_post_t *this_gen, void *param_gen) { return 1; } - + static xine_post_api_descr_t * get_param_descr (void) { return ¶m_descr; } @@ -273,7 +270,7 @@ void *unsharp_init_plugin(xine_t *xine, void *data) if (!class) return NULL; - + class->open_plugin = unsharp_open_plugin; class->get_identifier = unsharp_get_identifier; class->get_description = unsharp_get_description; @@ -287,19 +284,19 @@ static post_plugin_t *unsharp_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_unsharp_t *this = (post_plugin_unsharp_t *)xine_xmalloc(sizeof(post_plugin_unsharp_t)); + post_plugin_unsharp_t *this = calloc(1, sizeof(post_plugin_unsharp_t)); post_in_t *input; xine_post_in_t *input_api; post_out_t *output; post_video_port_t *port; - + if (!this || !video_target || !video_target[0]) { free(this); return NULL; } _x_post_init(&this->post, 0, 1); - + this->params.luma_matrix_width = 5; this->params.luma_matrix_height = 5; this->params.luma_amount = 0.0; @@ -309,11 +306,11 @@ static post_plugin_t *unsharp_open_plugin(post_class_t *class_gen, int inputs, this->params.chroma_amount = 0.0; pthread_mutex_init (&this->lock, NULL); - + port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output); port->intercept_frame = unsharp_intercept_frame; port->new_frame->draw = unsharp_draw; - + input_api = &this->params_input; input_api->name = "parameters"; input_api->type = XINE_POST_DATA_PARAMETERS; @@ -322,13 +319,13 @@ static post_plugin_t *unsharp_open_plugin(post_class_t *class_gen, int inputs, input->xine_in.name = "video"; output->xine_out.name = "unsharped video"; - + this->post.xine_post.video_input[0] = &port->new_port; - + set_parameters ((xine_post_t *)this, &this->params); - + this->post.dispose = unsharp_dispose; - + return &this->post; } @@ -402,15 +399,15 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream) yv12_frame = port->original_port->get_frame(port->original_port, frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS); - + _x_post_frame_copy_down(frame, yv12_frame); - + yuy2_to_yv12(frame->base[0], frame->pitches[0], yv12_frame->base[0], yv12_frame->pitches[0], yv12_frame->base[1], yv12_frame->pitches[1], yv12_frame->base[2], yv12_frame->pitches[2], frame->width, frame->height); - + } else { yv12_frame = frame; yv12_frame->lock(yv12_frame); @@ -438,7 +435,7 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream) stepsY = fp->msizeY/2; for( z=0; z<2*stepsY; z++ ) fp->SC[z] = malloc( sizeof(*(fp->SC[z])) * (frame->width+2*stepsX) ); - + fp = &this->priv.chromaParam; stepsX = fp->msizeX/2; stepsY = fp->msizeY/2; @@ -453,7 +450,7 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream) pthread_mutex_unlock (&this->lock); skip = out_frame->draw(out_frame, stream); - + _x_post_frame_copy_up(frame, out_frame); out_frame->free(out_frame); diff --git a/src/post/visualizations/Makefile.am b/src/post/visualizations/Makefile.am index f42598d9c..a766bc10a 100644 --- a/src/post/visualizations/Makefile.am +++ b/src/post/visualizations/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common EXTRA_DIST = fooviz.c diff --git a/src/post/visualizations/fft.c b/src/post/visualizations/fft.c index e9a99911a..7e32dbbf6 100644 --- a/src/post/visualizations/fft.c +++ b/src/post/visualizations/fft.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/post/visualizations/fft.h b/src/post/visualizations/fft.h index dff3cd7e8..651c7f15d 100644 --- a/src/post/visualizations/fft.h +++ b/src/post/visualizations/fft.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/post/visualizations/fftgraph.c b/src/post/visualizations/fftgraph.c index 5068bd37a..c3f8ff9f9 100644 --- a/src/post/visualizations/fftgraph.c +++ b/src/post/visualizations/fftgraph.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * by Thibaut Mattern (tmattern@noos.fr) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <math.h> @@ -62,7 +66,7 @@ struct post_plugin_fftgraph_s { /* private metronom for syncing the video */ metronom_t *metronom; - + double ratio; int data_idx; @@ -88,21 +92,21 @@ static void fade(int r1, int g1, int b1, int r2, int g2, int b2, uint32_t *yuy2_colors, int steps) { int i, r, g, b, y, u, v; - + for (i = 0; i < steps; i++) { r = r1 + (r2 - r1) * i / steps; g = g1 + (g2 - g1) * i / steps; b = b1 + (b2 - b1) * i / steps; - + y = COMPUTE_Y(r, g, b); u = COMPUTE_U(r, g, b); v = COMPUTE_V(r, g, b); - + *(yuy2_colors + i) = be2me_32((y << 24) | (u << 16) | (y << 8) | v); - + } } @@ -208,19 +212,19 @@ static int fftgraph_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream int i,j; uint32_t *color_ptr; uint32_t last_color, yuy2_black; - + /* printf("fftgraph_port_open, port_gen=%p, stream=%p, this=%p\n", port_gen, stream, this); */ _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - + this->ratio = (double)FFTGRAPH_WIDTH / (double)FFTGRAPH_HEIGHT; - + this->channels = _x_ao_mode2channels(mode); if( this->channels > MAXCHANNELS ) this->channels = MAXCHANNELS; @@ -235,7 +239,7 @@ static int fftgraph_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream this->fft = fft_new(FFT_BITS); this->cur_line = 0; - + /* compute colors */ color_ptr = this->yuy2_colors; /* black -> red */ @@ -249,7 +253,7 @@ static int fftgraph_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream 40, 0, 160, color_ptr, 256); color_ptr += 256; - + /* blue -> green */ fade(40, 0, 160, 40, 160, 70, @@ -290,15 +294,15 @@ static void fftgraph_port_close(xine_audio_port_t *port_gen, xine_stream_t *stre post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)port->post; port->stream = NULL; - + fft_dispose(this->fft); this->fft = NULL; this->vo_port->close(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, NULL); - + port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } @@ -325,7 +329,7 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen, /* pass data to original port */ port->original_port->put_buffer(port->original_port, buf, stream ); - + /* we must not use original data anymore, it should have already being moved * to the fifo of free audio buffers. just use our private copy instead. */ @@ -368,8 +372,8 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - - /* frame is marked as bad if we don't have enough samples for + + /* 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 ) { @@ -381,10 +385,10 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen, frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); - + this->sample_counter -= this->samples_per_frame; - if( this->fft ) + if( this->fft ) draw_fftgraph(this, frame); else frame->bad_frame = 1; @@ -415,7 +419,7 @@ static post_plugin_t *fftgraph_open_plugin(post_class_t *class_gen, int inputs, xine_video_port_t **video_target) { post_class_fftgraph_t *class = (post_class_fftgraph_t *)class_gen; - post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)xine_xmalloc(sizeof(post_plugin_fftgraph_t)); + post_plugin_fftgraph_t *this = calloc(1, sizeof(post_plugin_fftgraph_t)); post_in_t *input; post_out_t *output; post_out_t *outputv; @@ -427,7 +431,7 @@ static post_plugin_t *fftgraph_open_plugin(post_class_t *class_gen, int inputs, } _x_post_init(&this->post, 1, 0); - + this->metronom = _x_metronom_init(1, 0, class->xine); this->vo_port = video_target[0]; @@ -471,16 +475,16 @@ static void fftgraph_class_dispose(post_class_t *class_gen) void *fftgraph_init_plugin(xine_t *xine, void *data) { post_class_fftgraph_t *class = (post_class_fftgraph_t *)malloc(sizeof(post_class_fftgraph_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = fftgraph_open_plugin; class->post_class.get_identifier = fftgraph_get_identifier; class->post_class.get_description = fftgraph_get_description; class->post_class.dispose = fftgraph_class_dispose; - + class->xine = xine; - + return class; } diff --git a/src/post/visualizations/fftscope.c b/src/post/visualizations/fftscope.c index ba34437f5..286c4ac38 100644 --- a/src/post/visualizations/fftscope.c +++ b/src/post/visualizations/fftscope.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -23,6 +23,10 @@ * FFT code by Steve Haehnichen, originally licensed under GPL v1 */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <math.h> @@ -49,7 +53,7 @@ typedef struct post_class_fftscope_s post_class_fftscope_t; struct post_class_fftscope_s { post_class_t post_class; - + xine_t *xine; }; @@ -59,10 +63,10 @@ struct post_plugin_fftscope_s { /* private data */ xine_video_port_t *vo_port; post_out_t video_output; - + /* private metronom for syncing the video */ metronom_t *metronom; - + double ratio; int data_idx; @@ -273,12 +277,12 @@ static int fftscope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - + this->ratio = (double)FFT_WIDTH/(double)FFT_HEIGHT; this->channels = _x_ao_mode2channels(mode); @@ -311,15 +315,15 @@ static void fftscope_port_close(xine_audio_port_t *port_gen, xine_stream_t *stre post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)port->post; port->stream = NULL; - + fft_dispose(this->fft); this->fft = NULL; this->vo_port->close(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, NULL); - + port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } @@ -389,8 +393,8 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen, this->ratio, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); frame->extra_info->invalid = 1; - - /* frame is marked as bad if we don't have enough samples for + + /* 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 ) { @@ -402,10 +406,10 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen, frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); - + this->sample_counter -= this->samples_per_frame; - if( this->fft ) + if( this->fft ) draw_fftscope(this, frame); else frame->bad_frame = 1; @@ -419,7 +423,7 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen, static void fftscope_dispose(post_plugin_t *this_gen) { post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)this_gen; - + if (_x_post_dispose(this_gen)) { this->metronom->exit(this->metronom); @@ -435,7 +439,7 @@ static post_plugin_t *fftscope_open_plugin(post_class_t *class_gen, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target) { - post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)xine_xmalloc(sizeof(post_plugin_fftscope_t)); + post_plugin_fftscope_t *this = calloc(1, sizeof(post_plugin_fftscope_t)); post_class_fftscope_t *class = (post_class_fftscope_t *)class_gen; post_in_t *input; post_out_t *output; @@ -446,7 +450,7 @@ static post_plugin_t *fftscope_open_plugin(post_class_t *class_gen, int inputs, free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); this->metronom = _x_metronom_init(1, 0, class->xine); @@ -492,16 +496,16 @@ static void fftscope_class_dispose(post_class_t *class_gen) void *fftscope_init_plugin(xine_t *xine, void *data) { post_class_fftscope_t *class = (post_class_fftscope_t *)malloc(sizeof(post_class_fftscope_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = fftscope_open_plugin; class->post_class.get_identifier = fftscope_get_identifier; class->post_class.get_description = fftscope_get_description; class->post_class.dispose = fftscope_class_dispose; - + class->xine = xine; - + return &class->post_class; } diff --git a/src/post/visualizations/fooviz.c b/src/post/visualizations/fooviz.c index 21854afc6..ac85da304 100644 --- a/src/post/visualizations/fooviz.c +++ b/src/post/visualizations/fooviz.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -24,6 +24,10 @@ * colors on each iteration. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" @@ -56,7 +60,7 @@ struct post_plugin_fooviz_s { /* private metronom for syncing the video */ metronom_t *metronom; - + double ratio; int data_idx; @@ -86,7 +90,7 @@ static int fooviz_rewire_video(xine_post_out_t *output_gen, void *data) xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data; xine_video_port_t *new_port = (xine_video_port_t *)data; post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)output->post; - + if (!data) return 0; /* register our stream at the new output port */ @@ -105,12 +109,12 @@ static int fooviz_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - + this->ratio = (double)FOO_WIDTH/(double)FOO_HEIGHT; this->channels = _x_ao_mode2channels(mode); this->samples_per_frame = rate / FPS; @@ -129,18 +133,18 @@ static void fooviz_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)port->post; port->stream = NULL; - + this->vo_port->close(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, NULL); - + port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } -static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, +static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)port->post; vo_frame_t *frame; @@ -149,34 +153,34 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, int samples_used = 0; int64_t pts = buf->vpts; int i, j; - + /* make a copy of buf data for private use */ if( this->buf.mem_size < buf->mem_size ) { this->buf.mem = realloc(this->buf.mem, buf->mem_size); this->buf.mem_size = buf->mem_size; } - memcpy(this->buf.mem, buf->mem, + memcpy(this->buf.mem, buf->mem, buf->num_frames*this->channels*((port->bits == 8)?1:2)); this->buf.num_frames = buf->num_frames; - + /* pass data to original port */ - port->original_port->put_buffer(port->original_port, buf, stream ); - + port->original_port->put_buffer(port->original_port, buf, stream ); + /* we must not use original data anymore, it should have already being moved * to the fifo of free audio buffers. just use our private copy instead. */ - buf = &this->buf; + buf = &this->buf; this->sample_counter += buf->num_frames; - + j = (this->channels >= 2) ? 1 : 0; do { - + if( port->bits == 8 ) { data8 = (int8_t *)buf->mem; data8 += samples_used * this->channels; - + /* scale 8 bit data to 16 bits and convert to signed as well */ for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) { @@ -186,24 +190,24 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, } else { data = buf->mem; data += samples_used * this->channels; - + 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 ) { - + 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 is marked as bad if we don't have enough samples for + + /* 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 ) { @@ -215,7 +219,7 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen, frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); - + this->sample_counter -= this->samples_per_frame; memset(frame->base[0], this->current_yuv_byte, FOO_WIDTH * FOO_HEIGHT * 2); @@ -247,19 +251,19 @@ static post_plugin_t *fooviz_open_plugin(post_class_t *class_gen, int inputs, xine_video_port_t **video_target) { post_class_fooviz_t *class = (post_class_fooviz_t *)class_gen; - post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)xine_xmalloc(sizeof(post_plugin_fooviz_t)); + post_plugin_fooviz_t *this = calloc(1, sizeof(post_plugin_fooviz_t)); post_in_t *input; post_out_t *output; post_out_t *outputv; post_audio_port_t *port; - + if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0] ) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); - + this->metronom = _x_metronom_init(1, 0, class->xine); this->vo_port = video_target[0]; @@ -268,7 +272,7 @@ static post_plugin_t *fooviz_open_plugin(post_class_t *class_gen, int inputs, port->new_port.open = fooviz_port_open; port->new_port.close = fooviz_port_close; port->new_port.put_buffer = fooviz_port_put_buffer; - + outputv = &this->video_output; outputv->xine_out.name = "generated video"; outputv->xine_out.type = XINE_POST_DATA_VIDEO; @@ -276,9 +280,9 @@ static post_plugin_t *fooviz_open_plugin(post_class_t *class_gen, int inputs, outputv->xine_out.rewire = fooviz_rewire_video; outputv->post = &this->post; xine_list_push_back(this->post.output, outputv); - + this->post.xine_post.audio_input[0] = &port->new_port; - + this->post.dispose = fooviz_dispose; return &this->post; @@ -303,17 +307,17 @@ static void fooviz_class_dispose(post_class_t *class_gen) static void *fooviz_init_plugin(xine_t *xine, void *data) { post_class_fooviz_t *class = (post_class_fooviz_t *)malloc(sizeof(post_class_fooviz_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = fooviz_open_plugin; class->post_class.get_identifier = fooviz_get_identifier; class->post_class.get_description = fooviz_get_description; class->post_class.dispose = fooviz_class_dispose; - + class->xine = xine; - + return class; } @@ -321,7 +325,7 @@ static void *fooviz_init_plugin(xine_t *xine, void *data) static const post_info_t fooviz_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_POST, 9, "fooviz", XINE_VERSION_CODE, &fooviz_special_info, &fooviz_init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/post/visualizations/oscope.c b/src/post/visualizations/oscope.c index a435604d4..28d1b4cbc 100644 --- a/src/post/visualizations/oscope.c +++ b/src/post/visualizations/oscope.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * by Mike Melanson (melanson@pcisys.net) */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include "xine_internal.h" @@ -55,13 +59,13 @@ struct post_plugin_oscope_s { /* private metronom for syncing the video */ metronom_t *metronom; - + double ratio; int data_idx; short data [MAXCHANNELS][NUMSAMPLES]; audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */ - + int channels; int sample_counter; int samples_per_frame; @@ -126,7 +130,7 @@ static void draw_oscope_dots(post_plugin_oscope_t *this) { /* draw channel scope */ for (i = 0; i < NUMSAMPLES; i++) { - pixel_ptr = + pixel_ptr = ((OSCOPE_HEIGHT * (c * 2 + 1) / (2*this->channels) ) + (this->data[c][i] >> 9)) * OSCOPE_WIDTH + i; this->yuv.y[pixel_ptr] = 0xFF; this->yuv.u[pixel_ptr] = this->u_current; @@ -157,7 +161,7 @@ static int oscope_rewire_video(xine_post_out_t *output_gen, void *data) xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data; xine_video_port_t *new_port = (xine_video_port_t *)data; post_plugin_oscope_t *this = (post_plugin_oscope_t *)output->post; - + if (!data) return 0; old_port->close(old_port, XINE_ANON_STREAM); @@ -175,12 +179,12 @@ static int oscope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream, _x_post_rewire(&this->post); _x_post_inc_usage(port); - + port->stream = stream; port->bits = bits; port->rate = rate; port->mode = mode; - + this->ratio = (double)OSCOPE_WIDTH/(double)OSCOPE_HEIGHT; this->channels = _x_ao_mode2channels(mode); @@ -206,15 +210,15 @@ static void oscope_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream this->vo_port->close(this->vo_port, XINE_ANON_STREAM); this->metronom->set_master(this->metronom, NULL); - + port->original_port->close(port->original_port, stream ); - + _x_post_dec_usage(port); } -static void oscope_port_put_buffer (xine_audio_port_t *port_gen, +static void oscope_port_put_buffer (xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { - + post_audio_port_t *port = (post_audio_port_t *)port_gen; post_plugin_oscope_t *this = (post_plugin_oscope_t *)port->post; vo_frame_t *frame; @@ -223,32 +227,32 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen, int samples_used = 0; int64_t pts = buf->vpts; int i, c; - + /* make a copy of buf data for private use */ if( this->buf.mem_size < buf->mem_size ) { this->buf.mem = realloc(this->buf.mem, buf->mem_size); this->buf.mem_size = buf->mem_size; } - memcpy(this->buf.mem, buf->mem, + memcpy(this->buf.mem, buf->mem, buf->num_frames*this->channels*((port->bits == 8)?1:2)); this->buf.num_frames = buf->num_frames; - + /* pass data to original port */ - port->original_port->put_buffer(port->original_port, buf, stream ); - + port->original_port->put_buffer(port->original_port, buf, stream ); + /* we must not use original data anymore, it should have already being moved * to the fifo of free audio buffers. just use our private copy instead. */ - buf = &this->buf; - + buf = &this->buf; + this->sample_counter += buf->num_frames; - + do { - + if( port->bits == 8 ) { data8 = (int8_t *)buf->mem; data8 += samples_used * this->channels; - + /* scale 8 bit data to 16 bits and convert to signed as well */ for( i = samples_used; i < buf->num_frames && this->data_idx < NUMSAMPLES; i++, this->data_idx++, data8 += this->channels ) @@ -257,23 +261,23 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen, } else { data = buf->mem; data += samples_used * this->channels; - + 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 ) { - + 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 is marked as bad if we don't have enough samples for + + /* 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 ) { @@ -285,12 +289,12 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen, frame->duration = 90000 * this->samples_per_frame / port->rate; frame->pts = pts; this->metronom->got_video_frame(this->metronom, frame); - + this->sample_counter -= this->samples_per_frame; - + draw_oscope_dots(this); yuv444_to_yuy2(&this->yuv, frame->base[0], frame->pitches[0]); - + frame->draw(frame, XINE_ANON_STREAM); frame->free(frame); @@ -303,7 +307,7 @@ static void oscope_dispose(post_plugin_t *this_gen) post_plugin_oscope_t *this = (post_plugin_oscope_t *)this_gen; if (_x_post_dispose(this_gen)) { - + this->metronom->exit(this->metronom); if(this->buf.mem) @@ -318,19 +322,19 @@ static post_plugin_t *oscope_open_plugin(post_class_t *class_gen, int inputs, xine_video_port_t **video_target) { post_class_oscope_t *class = (post_class_oscope_t *)class_gen; - post_plugin_oscope_t *this = (post_plugin_oscope_t *)xine_xmalloc(sizeof(post_plugin_oscope_t)); + post_plugin_oscope_t *this = calloc(1, sizeof(post_plugin_oscope_t)); post_in_t *input; post_out_t *output; post_out_t *outputv; post_audio_port_t *port; - + if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0] ) { free(this); return NULL; } - + _x_post_init(&this->post, 1, 0); - + this->metronom = _x_metronom_init(1, 0, class->xine); this->vo_port = video_target[0]; @@ -339,7 +343,7 @@ static post_plugin_t *oscope_open_plugin(post_class_t *class_gen, int inputs, port->new_port.open = oscope_port_open; port->new_port.close = oscope_port_close; port->new_port.put_buffer = oscope_port_put_buffer; - + outputv = &this->video_output; outputv->xine_out.name = "generated video"; outputv->xine_out.type = XINE_POST_DATA_VIDEO; @@ -347,9 +351,9 @@ static post_plugin_t *oscope_open_plugin(post_class_t *class_gen, int inputs, outputv->xine_out.rewire = oscope_rewire_video; outputv->post = &this->post; xine_list_push_back(this->post.output, outputv); - + this->post.xine_post.audio_input[0] = &port->new_port; - + this->post.dispose = oscope_dispose; return &this->post; @@ -374,16 +378,16 @@ static void oscope_class_dispose(post_class_t *class_gen) void *oscope_init_plugin(xine_t *xine, void *data) { post_class_oscope_t *class = (post_class_oscope_t *)malloc(sizeof(post_class_oscope_t)); - + if (!class) return NULL; - + class->post_class.open_plugin = oscope_open_plugin; class->post_class.get_identifier = oscope_get_identifier; class->post_class.get_description = oscope_get_description; class->post_class.dispose = oscope_class_dispose; - + class->xine = xine; - + return &class->post_class; } diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index c40535d9e..3e182fc14 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -1,3 +1,4 @@ +include $(top_builddir)/misc/Makefile.plugins include $(top_srcdir)/misc/Makefile.common AM_CPPFLAGS = -DXINE_COMPILE @@ -100,6 +101,7 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \ $(xxmc_module) \ $(xcbshm_module) \ $(xcbxv_module) \ + xineplug_vo_out_raw.la \ xineplug_vo_out_none.la xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD) @@ -130,13 +132,13 @@ xineplug_vo_out_xxmc_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(XV_CFLAGS) -fn xineplug_vo_out_opengl_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ video_out_opengl.c myglext.h $(X11OSD) -xineplug_vo_out_opengl_la_LIBADD = $(MLIB_LIBS) $(OPENGL_LIBS) $(GLUT_LIBS) \ - $(GLU_LIBS) $(X_LIBS) $(XINE_LIB) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) +xineplug_vo_out_opengl_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(OPENGL_LIBS) \ + $(GLUT_LIBS) $(GLU_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) xineplug_vo_out_opengl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(MLIB_CFLAGS) -fno-strict-aliasing -xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c +xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c xineplug_vo_out_syncfb_la_LIBADD = $(XINE_LIB) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) -xineplug_vo_out_syncfb_la_CFLAGS = $(VISIBILITY_FLAG) +xineplug_vo_out_syncfb_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) xineplug_vo_out_pgx64_la_SOURCES = video_out_pgx64.c xineplug_vo_out_pgx64_la_LIBADD = $(XINE_LIB) $(X_LIBS) $(SUNDGA_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) @@ -177,28 +179,32 @@ xineplug_vo_out_sdl_la_SOURCES = video_out_sdl.c xineplug_vo_out_sdl_la_LIBADD = $(XINE_LIB) $(SDL_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_sdl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(SDL_CFLAGS) -xineplug_vo_out_stk_la_SOURCES = video_out_stk.c +xineplug_vo_out_stk_la_SOURCES = video_out_stk.c xineplug_vo_out_stk_la_LIBADD = $(XINE_LIB) $(LIBSTK_LIBS) $(PTHREAD_LIBS) xineplug_vo_out_stk_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBSTK_CFLAGS) -xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c +xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c xineplug_vo_out_directx_la_CPPFLAGS = $(AM_CPPFLAGS) $(DIRECTX_CPPFLAGS) -xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) +xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) xineplug_vo_out_none_la_SOURCES = video_out_none.c xineplug_vo_out_none_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_none_la_CFLAGS = $(VISIBILITY_FLAG) +xineplug_vo_out_raw_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_raw.c +xineplug_vo_out_raw_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_raw_la_CFLAGS = $(VISIBILITY_FLAG) + xineplug_vo_out_macosx_la_SOURCES = video_out_macosx.m xineplug_vo_out_macosx_la_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(MLIB_CFLAGS) xineplug_vo_out_macosx_la_OBJCFLAGS = $(VISIBILITY_FLAG) -xineplug_vo_out_macosx_la_LIBADD = $(MLIB_LIBS) $(OPENGL_LIBS) $(GLUT_LIBS) \ - $(GLU_LIBS) $(X_LIBS) $(XINE_LIB) $(PTHREAD_LIBS) +xineplug_vo_out_macosx_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(OPENGL_LIBS) \ + $(GLUT_LIBS) $(GLU_LIBS) $(X_LIBS) $(PTHREAD_LIBS) # The "-Wl,-framework -Wl,Cocoa" is needed for libtool versions before # 1.5.x (1.257): the default version that ships with Mac OS X is 1.5 (1.1220) xineplug_vo_out_macosx_la_LDFLAGS = $(AM_LDFLAGS) \ -Wl,-framework -Wl,Cocoa -framework Cocoa -framework OpenGL noinst_HEADERS = deinterlace.h video_out_syncfb.h \ - yuv2rgb.h x11osd.h xcbosd.h + yuv2rgb.h x11osd.h xcbosd.h xv_common.h diff --git a/src/video_out/deinterlace.c b/src/video_out/deinterlace.c index 8ba161ebb..6d90caca0 100644 --- a/src/video_out/deinterlace.c +++ b/src/video_out/deinterlace.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -30,6 +30,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include "xine_internal.h" @@ -37,6 +41,18 @@ #include "xineutils.h" +const char *deinterlace_methods[] = { + "none", + "bob", + "weave", + "greedy", + "onefield", + "onefield_xv", + "linearblend", + NULL +}; + + /* DeinterlaceFieldBob algorithm Based on Virtual Dub plugin by Gunnar Thalin @@ -185,7 +201,7 @@ static void deinterlace_bob_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], /* Deinterlace the latest field, with a tendency to weave rather than bob. Good for high detail on low-movement scenes. Seems to produce bad output in general case, need to check if this - is normal or if the code is broken. + is normal or if the code is broken. */ static int deinterlace_weave_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], int width, int height ) @@ -640,7 +656,7 @@ static void deinterlace_linearblend_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], uint64_t *YVal3; uint64_t *Dest; int LineLength = width; - + int n; /* Copy first line */ @@ -660,7 +676,7 @@ static void deinterlace_linearblend_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], movq_m2r (*YVal1++, mm0); movq_m2r (*YVal2++, mm1); movq_m2r (*YVal3++, mm2); - + /* expand bytes to words */ punpckhbw_r2r (mm0, mm3); punpckhbw_r2r (mm1, mm4); @@ -668,8 +684,8 @@ static void deinterlace_linearblend_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], punpcklbw_r2r (mm0, mm0); punpcklbw_r2r (mm1, mm1); punpcklbw_r2r (mm2, mm2); - - /* + + /* * deinterlacing: * deint_line = (line0 + 2*line1 + line2) / 4 */ @@ -688,15 +704,15 @@ static void deinterlace_linearblend_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], /* pack 8 words to 8 bytes in mm0 */ packuswb_r2r (mm3, mm0); - + movq_r2m ( mm0, *Dest++ ); } } /* Copy last line */ - xine_fast_memcpy(pdst + Line * LineLength, + xine_fast_memcpy(pdst + Line * LineLength, psrc[0] + Line * LineLength, LineLength); - + /* clear out the MMX registers ready for doing floating point * again */ @@ -718,7 +734,7 @@ static void deinterlace_linearblend_yuv_mmx( uint8_t *pdst, uint8_t *psrc[], * each line on pdst doesn't depend on previous lines; * due to the way the algorithm is defined, the first & last lines of the screen aren't deinterlaced. - + */ static void deinterlace_linearblend_yuv( uint8_t *pdst, uint8_t *psrc[], int width, int height ) @@ -735,7 +751,7 @@ static void deinterlace_linearblend_yuv( uint8_t *pdst, uint8_t *psrc[], xine_fast_memcpy(l0, l1, width); l0 += width; - for (y = 1; y < height-1; ++y) { + for (y = 1; y < height-1; ++y) { /* computes avg of: l1 + 2*l2 + l3 */ for (x = 0; x < width; ++x) { diff --git a/src/video_out/deinterlace.h b/src/video_out/deinterlace.h index 2ebbf53d9..d7712f581 100644 --- a/src/video_out/deinterlace.h +++ b/src/video_out/deinterlace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001 the xine project + * Copyright (C) 2001-2008 the xine project * * This file is part of xine, a free video player. * @@ -41,15 +41,6 @@ void deinterlace_yuv( uint8_t *pdst, uint8_t *psrc[], #define DEINTERLACE_ONEFIELDXV 5 #define DEINTERLACE_LINEARBLEND 6 -static const char *deinterlace_methods[] = { - "none", - "bob", - "weave", - "greedy", - "onefield", - "onefield_xv", - "linearblend", - NULL -}; +extern const char *deinterlace_methods[]; #endif diff --git a/src/video_out/libdha/Makefile.am b/src/video_out/libdha/Makefile.am index 8d94347d1..9412bcd50 100644 --- a/src/video_out/libdha/Makefile.am +++ b/src/video_out/libdha/Makefile.am @@ -16,7 +16,7 @@ CLEANFILES = $(awk_generated) noinst_LTLIBRARIES = $(dha_lib) libdha_la_SOURCES = libdha.c mtrr.c pci.c mmi.c ports.c irq.c cpu_flush.c -nodist_libdha_la_SOURCES = pci_names.c +nodist_libdha_la_SOURCES = pci_names.c EXTRA_PROGRAMS = test diff --git a/src/video_out/libdha/sysdep/Makefile.am b/src/video_out/libdha/sysdep/Makefile.am index 807572c39..0896a8ded 100644 --- a/src/video_out/libdha/sysdep/Makefile.am +++ b/src/video_out/libdha/sysdep/Makefile.am @@ -24,7 +24,7 @@ EXTRA_DIST = \ pci_svr4.c \ pci_win32.c \ pci_x86.c - + noinst_HEADERS = \ AsmMacros_alpha.h \ AsmMacros_arm32.h \ diff --git a/src/video_out/macosx/XineOpenGLView.m b/src/video_out/macosx/XineOpenGLView.m index a9ffee00f..1f947ca16 100644 --- a/src/video_out/macosx/XineOpenGLView.m +++ b/src/video_out/macosx/XineOpenGLView.m @@ -340,7 +340,7 @@ NSColorToYUV(NSColor *color) // http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, videoSize.width, videoSize.height, GL_YCBCR_422_APPLE, -#if WORDS_BIG_ENDIAN +#if WORDS_BIGENDIAN GL_UNSIGNED_SHORT_8_8_APPLE, #else GL_UNSIGNED_SHORT_8_8_REV_APPLE, diff --git a/src/video_out/macosx/video_window.h b/src/video_out/macosx/video_window.h index b46ac43fe..0a3655c0c 100644 --- a/src/video_out/macosx/video_window.h +++ b/src/video_out/macosx/video_window.h @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * Written by Daniel Mack <xine@zonque.org> - * + * * Most parts of this code were taken from VLC, http://www.videolan.org * Thanks for the good research! */ diff --git a/src/video_out/myglext.h b/src/video_out/myglext.h index 1a55a4f87..643b31c3d 100644 --- a/src/video_out/myglext.h +++ b/src/video_out/myglext.h @@ -13,21 +13,21 @@ extern "C" { ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: -** +** ** http://oss.sgi.com/projects/FreeB -** +** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. -** +** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2004 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. -** +** ** Additional Notice Provisions: This software was created using the ** OpenGL(R) version 1.2.1 Sample Implementation published by SGI, but has ** not been independently verified as being compliant with the OpenGL(R) diff --git a/src/video_out/video_out_aa.c b/src/video_out/video_out_aa.c index 012db9665..2f20bd7c0 100644 --- a/src/video_out/video_out_aa.c +++ b/src/video_out/video_out_aa.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -86,7 +86,7 @@ static uint32_t aa_get_capabilities (vo_driver_t *this) { static void aa_dispose_frame (vo_frame_t *vo_img) { aa_frame_t *frame = (aa_frame_t *)vo_img; - + if (frame->mem[0]) free (frame->mem[0]); if (frame->mem[1]) @@ -106,7 +106,7 @@ static vo_frame_t *aa_alloc_frame(vo_driver_t *this_gen) { /* aa_driver_t *this = (aa_driver_t*) this_gen; */ aa_frame_t *frame; - frame = (aa_frame_t *) xine_xmalloc (sizeof (aa_frame_t)); + frame = calloc(1, sizeof (aa_frame_t)); if (!frame) return NULL; @@ -117,19 +117,19 @@ static vo_frame_t *aa_alloc_frame(vo_driver_t *this_gen) { frame->vo_frame.field = aa_frame_field; frame->vo_frame.dispose = aa_dispose_frame; frame->vo_frame.driver = this_gen; - + return (vo_frame_t*) frame; } static void aa_update_frame_format (vo_driver_t *this_gen, vo_frame_t *img, - uint32_t width, uint32_t height, + uint32_t width, uint32_t height, double ratio, int format, int flags) { aa_driver_t *this = (aa_driver_t*) this_gen; aa_frame_t *frame = (aa_frame_t *) img; /* printf ("aa_update_format...\n"); */ - if ((frame->width != width) || (frame->height != height) + if ((frame->width != width) || (frame->height != height) || (frame->format != format)) { if (frame->mem[0]) { @@ -140,7 +140,7 @@ static void aa_update_frame_format (vo_driver_t *this_gen, vo_frame_t *img, free (frame->mem[1]); frame->mem[1] = NULL; } - + if (frame->mem[2]) { free (frame->mem[2]); frame->mem[2] = NULL; @@ -202,27 +202,27 @@ static void aa_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { if (frame->format == XINE_IMGFMT_YV12) { for (y = 0; y<aa_imgheight (this->context); y++) { for (x = 0; x<aa_imgwidth (this->context); x++) { - + *img++ = src_image[((int)((double) x * x_fact) + frame->width * (int)((double) y * y_fact))]; - + } } } else { for (y = 0; y<aa_imgheight (this->context); y++) { for (x = 0; x<aa_imgwidth (this->context); x++) { - + *img++ = src_image[((int)((double) x * x_fact) * 2 + frame->width * 2 * (int)((double) y * y_fact))]; - + } } } frame->vo_frame.free (&frame->vo_frame); - aa_fastrender(this->context, 0, 0, - aa_imgwidth (this->context), + aa_fastrender(this->context, 0, 0, + aa_imgwidth (this->context), aa_imgheight (this->context)); aa_flush (this->context); @@ -231,7 +231,7 @@ static void aa_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { static int aa_get_property (vo_driver_t *this_gen, int property) { aa_driver_t *this = (aa_driver_t*) this_gen; - + if ( property == VO_PROP_ASPECT_RATIO) { return this->user_ratio ; } else { @@ -242,7 +242,7 @@ static int aa_get_property (vo_driver_t *this_gen, int property) { return 0; } -static int aa_set_property (vo_driver_t *this_gen, +static int aa_set_property (vo_driver_t *this_gen, int property, int value) { aa_driver_t *this = (aa_driver_t*) this_gen; @@ -259,7 +259,7 @@ static int aa_set_property (vo_driver_t *this_gen, return value; } -static void aa_get_property_min_max (vo_driver_t *this_gen, +static void aa_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) { *min = 0; *max = 0; @@ -276,10 +276,10 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi aa_class_t *class = (aa_class_t *) class_gen; aa_driver_t *this; - this = (aa_driver_t*) xine_xmalloc (sizeof (aa_driver_t)); - + this = (aa_driver_t*) calloc(1, sizeof(aa_driver_t)); + this->context = (aa_context*) visual_gen; - + this->config = class->config; this->xine = class->xine; @@ -298,7 +298,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->vo_driver.dispose = aa_dispose; return &this->vo_driver; -} +} static char* get_identifier (video_driver_class_t *this_gen) { return "AA"; @@ -315,14 +315,14 @@ static void dispose_class (video_driver_class_t *this_gen) { static void *init_class (xine_t *xine, void *visual_gen) { /* aa_context *context = (aa_context*) visual_gen; */ aa_class_t *this; - - this = (aa_class_t *) xine_xmalloc(sizeof(aa_class_t)); - + + this = calloc(1, sizeof(aa_class_t)); + this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; this->driver_class.get_description = get_description; this->driver_class.dispose = dispose_class; - + this->config = xine->config; this->xine = xine; @@ -335,7 +335,7 @@ static const vo_info_t vo_info_aa = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "aa", XINE_VERSION_CODE, &vo_info_aa, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/video_out/video_out_caca.c b/src/video_out/video_out_caca.c index 866eabcd8..5a060151e 100644 --- a/src/video_out/video_out_caca.c +++ b/src/video_out/video_out_caca.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2003, 2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -93,7 +93,7 @@ static uint32_t caca_get_capabilities (vo_driver_t *this) { static void caca_dispose_frame (vo_frame_t *vo_img) { caca_frame_t *frame = (caca_frame_t *)vo_img; - + if (frame->mem[0]) free (frame->mem[0]); if (frame->mem[1]) @@ -120,7 +120,7 @@ static vo_frame_t *caca_alloc_frame(vo_driver_t *this_gen) { caca_driver_t *this = (caca_driver_t*) this_gen; caca_frame_t *frame; - frame = (caca_frame_t *) xine_xmalloc (sizeof (caca_frame_t)); + frame = calloc(1, sizeof (caca_frame_t)); if (!frame) return NULL; @@ -135,17 +135,17 @@ static vo_frame_t *caca_alloc_frame(vo_driver_t *this_gen) { /* colorspace converter for this frame */ frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); - + return (vo_frame_t*) frame; } static void caca_update_frame_format (vo_driver_t *this_gen, vo_frame_t *img, - uint32_t width, uint32_t height, + uint32_t width, uint32_t height, double ratio, int format, int flags) { caca_driver_t *this = (caca_driver_t*) this_gen; caca_frame_t *frame = (caca_frame_t *) img; - if ((frame->width != width) || (frame->height != height) + if ((frame->width != width) || (frame->height != height) || (frame->format != format)) { if (frame->mem[0]) { @@ -228,7 +228,7 @@ static void caca_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { static int caca_get_property (vo_driver_t *this_gen, int property) { caca_driver_t *this = (caca_driver_t*) this_gen; - + if ( property == VO_PROP_ASPECT_RATIO) { return this->user_ratio; } else { @@ -239,7 +239,7 @@ static int caca_get_property (vo_driver_t *this_gen, int property) { return 0; } -static int caca_set_property (vo_driver_t *this_gen, +static int caca_set_property (vo_driver_t *this_gen, int property, int value) { caca_driver_t *this = (caca_driver_t*) this_gen; @@ -256,7 +256,7 @@ static int caca_set_property (vo_driver_t *this_gen, return value; } -static void caca_get_property_min_max (vo_driver_t *this_gen, +static void caca_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) { *min = 0; *max = 0; @@ -276,10 +276,11 @@ static int caca_redraw_needed (vo_driver_t *this_gen) { static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { caca_class_t *class = (caca_class_t *) class_gen; + caca_display_t *dp = (caca_display_t *)visual_gen; caca_driver_t *this; - this = (caca_driver_t*) xine_xmalloc (sizeof (caca_driver_t)); - + this = calloc(1, sizeof (caca_driver_t)); + this->config = class->config; this->xine = class->xine; @@ -300,12 +301,17 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->yuv2rgb_factory = yuv2rgb_factory_init(MODE_32_RGB, 0, NULL); this->yuv2rgb_factory->set_csc_levels(this->yuv2rgb_factory, 0, 128, 128); - this->cv = cucul_create_canvas(0, 0); - this->dp = caca_create_display(this->cv); + if (dp) { + this->cv = caca_get_canvas(dp); + this->dp = dp; + } else { + this->cv = cucul_create_canvas(0, 0); + this->dp = caca_create_display(this->cv); + } caca_refresh_display(this->dp); return &this->vo_driver; -} +} static char* get_identifier (video_driver_class_t *this_gen) { return "CACA"; @@ -321,14 +327,14 @@ static void dispose_class (video_driver_class_t *this_gen) { } static void *init_class (xine_t *xine, void *visual_gen) { caca_class_t *this; - - this = (caca_class_t *) xine_xmalloc(sizeof(caca_class_t)); - + + this = calloc(1, sizeof(caca_class_t)); + this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; this->driver_class.get_description = get_description; this->driver_class.dispose = dispose_class; - + this->config = xine->config; this->xine = xine; @@ -341,7 +347,7 @@ static const vo_info_t vo_info_caca = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "caca", XINE_VERSION_CODE, &vo_info_caca, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/video_out/video_out_directfb.c b/src/video_out/video_out_directfb.c index e6e333a0c..77f20a367 100644 --- a/src/video_out/video_out_directfb.c +++ b/src/video_out/video_out_directfb.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2006 the xine project and Claudio Ciccani - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -19,7 +19,7 @@ * * * DirectFB based output plugin by Claudio Ciccani <klan@directfb.org> - * + * * Based on video_out_xv.c and video_out_vidix.c. */ @@ -71,18 +71,18 @@ typedef struct directfb_frame_s { typedef struct directfb_driver_s { vo_driver_t vo_driver; - + int visual_type; uint32_t capabilities; xine_t *xine; - + directfb_frame_t *cur_frame; /* DirectFB related stuff */ IDirectFB *dfb; IDirectFBDisplayLayer *underlay; - + /* Video Layer */ IDirectFBDisplayLayer *layer; IDirectFBSurface *surface; @@ -93,23 +93,23 @@ typedef struct directfb_driver_s { DFBColorAdjustment default_cadj; int default_level; int visible; - + /* Subpicture layer */ IDirectFBDisplayLayer *spic_layer; IDirectFBSurface *spic_surface; - + /* for hardware scaling */ IDirectFBSurface *temp; int temp_frame_width; int temp_frame_height; DFBSurfacePixelFormat temp_frame_format; - + /* wheter card supports stretchblit with deinterlacing */ int hw_deinterlace; - + /* wheter to enable deinterlacing */ int deinterlace; - + /* configurable options */ int buffermode; int vsync; @@ -117,7 +117,7 @@ typedef struct directfb_driver_s { uint32_t colorkey; int flicker_filtering; int field_parity; - + #ifdef DIRECTFB_X11 /* X11 related stuff */ Display *display; @@ -126,18 +126,18 @@ typedef struct directfb_driver_s { GC gc; int depth; x11osd *xoverlay; - + void *user_data; void (*lock_display) (void *user_data); void (*unlock_display) (void *user_data); #endif int ovl_changed; - + /* screen size */ int screen_width; int screen_height; - + /* size / aspect ratio calculations */ vo_scale_t sc; @@ -162,16 +162,12 @@ typedef struct { "no-deinit-check,"\ "disable-module=linux_input,"\ "disable-module=keyboard" - + #define XDIRECTFB_OPTIONS "no-banner,"\ "no-sighandler,"\ "no-deinit-check" -#ifndef MAX -# define MAX( a, b ) (((a) > (b)) ? (a) : (b)) -#endif - #define YCBCR_TO_RGB( y, cb, cr, r, g, b ) \ do { \ int _y, _cb, _cr, _r, _g, _b; \ @@ -193,7 +189,7 @@ typedef struct { else \ XLockDisplay (this->display); \ } while (0) - + #define UNLOCK_DISPLAY() \ do { \ if (this->unlock_display) \ @@ -201,7 +197,7 @@ typedef struct { else \ XUnlockDisplay (this->display); \ } while (0) - + /*** driver functions ***/ @@ -219,11 +215,11 @@ static void directfb_frame_dispose (vo_frame_t *vo_img) { if (frame) { if (frame->surface) { - if (frame->locked) + if (frame->locked) frame->surface->Unlock (frame->surface); frame->surface->Release (frame->surface); } - + free (frame); } } @@ -232,21 +228,21 @@ static vo_frame_t *directfb_alloc_frame (vo_driver_t *this_gen) { directfb_driver_t *this = (directfb_driver_t *) this_gen; directfb_frame_t *frame; - frame = (directfb_frame_t *) xine_xmalloc (sizeof (directfb_frame_t)); + frame = (directfb_frame_t *) calloc(1, sizeof(directfb_frame_t)); if (!frame) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_directfb: directfb_alloc_frame: out of memory\n"); return NULL; } pthread_mutex_init (&frame->vo_frame.mutex, NULL); - - frame->vo_frame.proc_slice = NULL; + + frame->vo_frame.proc_slice = NULL; frame->vo_frame.proc_frame = NULL; - frame->vo_frame.field = directfb_frame_field; + frame->vo_frame.field = directfb_frame_field; frame->vo_frame.dispose = directfb_frame_dispose; frame->vo_frame.driver = this_gen; - + return &frame->vo_frame; } @@ -257,18 +253,18 @@ static void directfb_update_frame_format (vo_driver_t *this_gen, directfb_driver_t *this = (directfb_driver_t *) this_gen; directfb_frame_t *frame = (directfb_frame_t *) frame_gen; DFBSurfacePixelFormat format = (fmt == XINE_IMGFMT_YUY2) ? DSPF_YUY2 : DSPF_YV12; - + if (frame->surface == NULL || frame->width != width || frame->height != height || - frame->format != format) + frame->format != format) { DFBSurfaceDescription dsc; DFBResult ret; - + lprintf ("frame %p: format changed to %dx%d %s.\n", frame, width, height, (format == DSPF_YUY2) ? "YUY2" : "YV12"); - + if (frame->surface) { if (frame->locked) frame->surface->Unlock (frame->surface); @@ -276,26 +272,26 @@ static void directfb_update_frame_format (vo_driver_t *this_gen, frame->surface = NULL; frame->locked = 0; } - + dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; dsc.caps = DSCAPS_SYSTEMONLY | DSCAPS_INTERLACED; dsc.width = (width + 7) & ~7; dsc.height = (height + 1) & ~1; dsc.pixelformat = format; - + ret = this->dfb->CreateSurface (this->dfb, &dsc, &frame->surface); if (ret != DFB_OK) { DirectFBError ("IDirectFB::CreateSurface()", ret); return; } - + frame->width = width; frame->height = height; frame->format = format; - - ret = frame->surface->Lock (frame->surface, - DSLF_READ | DSLF_WRITE, + + ret = frame->surface->Lock (frame->surface, + DSLF_READ | DSLF_WRITE, (void**)&frame->vo_frame.base[0], (int *)&frame->vo_frame.pitches[0]); if (ret != DFB_OK) { @@ -303,17 +299,17 @@ static void directfb_update_frame_format (vo_driver_t *this_gen, return; } frame->locked = 1; - + if (frame->format == DSPF_YV12) { frame->vo_frame.pitches[1] = frame->vo_frame.pitches[0]/2; frame->vo_frame.pitches[2] = frame->vo_frame.pitches[0]/2; - frame->vo_frame.base[2] = frame->vo_frame.base[0] + + frame->vo_frame.base[2] = frame->vo_frame.base[0] + dsc.height * frame->vo_frame.pitches[0]; frame->vo_frame.base[1] = frame->vo_frame.base[2] + dsc.height/2 * frame->vo_frame.pitches[2]; } } - + frame->ratio = ratio; } @@ -335,7 +331,7 @@ static uint32_t directfb_colorkey_to_pixel (directfb_driver_t *this) { default: break; } - + return this->colorkey; } #endif @@ -346,11 +342,11 @@ static void directfb_clean_output_area (directfb_driver_t *this) { #ifdef DIRECTFB_X11 if (this->config.options & DLOP_DST_COLORKEY) { int i; - + LOCK_DISPLAY(); - + XSetForeground (this->display, this->gc, BlackPixel(this->display, this->screen)); - + for (i = 0; i < 4; i++) { if (this->sc.border[i].w && this->sc.border[i].h) { XFillRectangle (this->display, this->drawable, this->gc, @@ -358,18 +354,18 @@ static void directfb_clean_output_area (directfb_driver_t *this) { this->sc.border[i].w, this->sc.border[i].h); } } - + XSetForeground (this->display, this->gc, directfb_colorkey_to_pixel(this)); - XFillRectangle (this->display, this->drawable, this->gc, + XFillRectangle (this->display, this->drawable, this->gc, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height); - - + + if (this->xoverlay) { x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + XFlush (this->display); UNLOCK_DISPLAY(); @@ -388,7 +384,7 @@ static void directfb_clean_output_area (directfb_driver_t *this) { rect[i].w = MAX(this->sc.border[i].w, 0); rect[i].h = MAX(this->sc.border[i].h, 0); } - + this->surface->GetCapabilities (this->surface, &caps); if (caps & DSCAPS_DOUBLE) bufs++; @@ -396,7 +392,7 @@ static void directfb_clean_output_area (directfb_driver_t *this) { bufs++; this->surface->SetColor (this->surface, 0x00, 0x00, 0x00, 0xff); - for (i = 0; i < bufs; i++) { + for (i = 0; i < bufs; i++) { this->surface->FillRectangles (this->surface, &rect[0], 4); this->surface->Flip (this->surface, NULL, 0); } @@ -413,7 +409,7 @@ static void directfb_overlay_begin (vo_driver_t *this_gen, #ifdef DIRECTFB_X11 if (this->xoverlay) { LOCK_DISPLAY(); - x11osd_clear (this->xoverlay); + x11osd_clear (this->xoverlay); UNLOCK_DISPLAY(); } #endif @@ -423,7 +419,7 @@ static void directfb_overlay_begin (vo_driver_t *this_gen, this->spic_surface->Clear (this->spic_surface, 0, 0, 0, 0); } } - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -439,28 +435,28 @@ static void directfb_subpicture_paint (directfb_driver_t *this, int xoffset; int yoffset; int x, y, i; - + memset (colors, 0, sizeof(colors)); - + xoffset = this->sc.gui_win_x+overlay->x; yoffset = this->sc.gui_win_y+overlay->y; - + clip.x1 = xoffset; clip.y1 = yoffset; clip.x2 = xoffset + overlay->width - 1; clip.y2 = yoffset + overlay->height - 1; this->spic_surface->SetClip (this->spic_surface, &clip); - + for (x = 0, y= 0, i = 0; i < overlay->num_rle; i++) { int idx = overlay->rle[i].color; int len = overlay->rle[i].len; - + while (len > 0) { clut_t color = ((clut_t *)overlay->color)[idx]; uint8_t alpha = overlay->trans[idx]; int index = idx; int width; - + if ((len+x) > overlay->width) { width = overlay->width - x; len -= width; @@ -469,7 +465,7 @@ static void directfb_subpicture_paint (directfb_driver_t *this, width = len; len = 0; } - + if ((y >= overlay->hili_top) && (y <= overlay->hili_bottom) && (x <= overlay->hili_right)) @@ -482,28 +478,28 @@ static void directfb_subpicture_paint (directfb_driver_t *this, color = ((clut_t *)overlay->hili_color)[idx]; alpha = overlay->hili_trans[idx]; index += OVL_PALETTE_SIZE; - + if (x+width-1 > overlay->hili_right) { width -= overlay->hili_right - x; len += overlay->hili_right - x; } } } - + if (alpha) { if (n_rects == MAX_RECTS || (p_index != -1 && p_index != index)) { lprintf ("flushing %d rect(s).\n", n_rects); this->spic_surface->FillRectangles (this->spic_surface, rects, n_rects); n_rects = 0; } - + if (p_index != index) { if (!colors[index].a) { YCBCR_TO_RGB (color.y, color.cb, color.cr, colors[index].r, colors[index].g, colors[index].b); colors[index].a = alpha | (alpha << 4); } - + lprintf ("color change to %02x%02x%02x%02x.\n", colors[index].a, colors[index].r, colors[index].g, colors[index].b); @@ -512,7 +508,7 @@ static void directfb_subpicture_paint (directfb_driver_t *this, colors[index].b, colors[index].a); p_index = index; } - + rects[n_rects].x = x + xoffset; rects[n_rects].y = y + yoffset; rects[n_rects].w = width; @@ -524,10 +520,10 @@ static void directfb_subpicture_paint (directfb_driver_t *this, n_rects--; rects[n_rects].h++; } - } + } n_rects++; } - + x += width; if (x == overlay->width) { if (++y == overlay->height) @@ -536,7 +532,7 @@ static void directfb_subpicture_paint (directfb_driver_t *this, } } } - + if (n_rects) { lprintf ("flushing %d remaining rect(s).\n", n_rects); this->spic_surface->FillRectangles (this->spic_surface, rects, n_rects); @@ -547,17 +543,17 @@ static void directfb_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { directfb_driver_t *this = (directfb_driver_t *) this_gen; directfb_frame_t *frame = (directfb_frame_t *) frame_gen; - + if (!overlay->rle) return; - + if (overlay->unscaled) { if (!this->ovl_changed) return; #ifdef DIRECTFB_X11 if (this->xoverlay) { LOCK_DISPLAY(); - x11osd_blend (this->xoverlay, overlay); + x11osd_blend (this->xoverlay, overlay); UNLOCK_DISPLAY(); } #endif @@ -574,7 +570,7 @@ static void directfb_overlay_blend (vo_driver_t *this_gen, &this->alphablend_extra_data); } else { - _x_blend_yuv (frame->vo_frame.base, overlay, + _x_blend_yuv (frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); @@ -606,20 +602,20 @@ static void directfb_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) static int directfb_redraw_needed (vo_driver_t *this_gen) { directfb_driver_t *this = (directfb_driver_t *) this_gen; directfb_frame_t *frame = this->cur_frame; - + if (!frame) return 1; - - this->sc.delivered_width = frame->width; - this->sc.delivered_height = frame->height; - this->sc.delivered_ratio = frame->ratio; + + this->sc.delivered_width = frame->width; + this->sc.delivered_height = frame->height; + this->sc.delivered_ratio = frame->ratio; this->sc.crop_left = frame->vo_frame.crop_left; this->sc.crop_right = frame->vo_frame.crop_right; this->sc.crop_top = frame->vo_frame.crop_top; this->sc.crop_bottom = frame->vo_frame.crop_bottom; - + _x_vo_scale_compute_ideal_size (&this->sc); - + if (_x_vo_scale_redraw_needed (&this->sc)) { lprintf ("redraw needed.\n"); _x_vo_scale_compute_output_size (&this->sc); @@ -628,20 +624,20 @@ static int directfb_redraw_needed (vo_driver_t *this_gen) { this->layer->SetSourceRectangle (this->layer, this->sc.displayed_xoffset, this->sc.displayed_yoffset, - this->sc.displayed_width, + this->sc.displayed_width, this->sc.displayed_height ); this->layer->SetScreenRectangle (this->layer, - this->sc.gui_win_x+this->sc.output_xoffset, + this->sc.gui_win_x+this->sc.output_xoffset, this->sc.gui_win_y+this->sc.output_yoffset, this->sc.output_width, this->sc.output_height); } - + directfb_clean_output_area (this); - + return 1; } - + return 0; } @@ -649,30 +645,30 @@ static int directfb_redraw_needed (vo_driver_t *this_gen) { static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { directfb_driver_t *this = (directfb_driver_t *) this_gen; directfb_frame_t *frame = (directfb_frame_t *) frame_gen; - + if (this->cur_frame) this->cur_frame->vo_frame.free (&this->cur_frame->vo_frame); this->cur_frame = frame; - + this->config.flags = DLCONF_NONE; - + if (frame->width != this->config.width) { this->config.flags |= DLCONF_WIDTH; this->config.width = frame->width; } - + if (frame->height != this->config.height) { this->config.flags |= DLCONF_HEIGHT; this->config.height = frame->height; } - - if (this->type & DLTF_VIDEO) { + + if (this->type & DLTF_VIDEO) { if (frame->format != this->config.pixelformat) { this->config.flags |= DLCONF_PIXELFORMAT; this->config.pixelformat = frame->format; } } - + if (this->caps & DLCAPS_DEINTERLACING) { if (this->deinterlace && !(this->config.options & DLOP_DEINTERLACING)) { @@ -685,14 +681,14 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen this->config.options &= ~DLOP_DEINTERLACING; } } - + if (this->config.flags) { DFBDisplayLayerConfigFlags failed = 0; - + lprintf ("changing layer configuration to %dx%d %s.\n", this->config.width, this->config.height, (this->config.pixelformat == DSPF_YUY2) ? "YUY2" : "YV12"); - + this->layer->TestConfiguration (this->layer, &this->config, &failed); this->config.flags &= ~failed; if (this->config.flags) { @@ -704,7 +700,7 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen lprintf ("failed=0x%08x.\n", failed); } - + if (this->sc.delivered_width != frame->width || this->sc.delivered_height != frame->height || this->sc.delivered_ratio != frame->ratio) @@ -712,9 +708,9 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen lprintf ("forcing redraw.\n"); this->sc.force_redraw = 1; } - + directfb_redraw_needed (&this->vo_driver); - + if (!this->visible) { this->layer->SetOpacity (this->layer, 0xff); this->visible = 1; @@ -724,13 +720,13 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen frame->surface->Unlock (frame->surface); frame->locked = 0; } - + if (this->deinterlace) { if (!(this->config.options & DLOP_DEINTERLACING)) { - frame->surface->SetField (frame->surface, + frame->surface->SetField (frame->surface, frame->vo_frame.top_field_first ? 0 : 1); this->surface->SetBlittingFlags (this->surface, DSBLIT_DEINTERLACE); - } + } else { this->surface->SetField (this->surface, frame->vo_frame.top_field_first ? 0 : 1); @@ -738,13 +734,13 @@ static void directfb_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen } else { this->surface->SetBlittingFlags (this->surface, DSBLIT_NOFX); } - + this->surface->Blit (this->surface, frame->surface, NULL, 0, 0); this->surface->Flip (this->surface, NULL, (this->vsync) ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC); - - frame->surface->Lock (frame->surface, - DSLF_READ | DSLF_WRITE, + + frame->surface->Lock (frame->surface, + DSLF_READ | DSLF_WRITE, (void**)&frame->vo_frame.base[0], (int *)&frame->vo_frame.pitches[0]); frame->locked = 1; @@ -757,28 +753,28 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge DFBSurfaceBlittingFlags flags; DFBRectangle s, d; DFBResult ret; - + if (this->cur_frame) this->cur_frame->vo_frame.free (&this->cur_frame->vo_frame); this->cur_frame = frame; - + /* TODO: try to change video mode when frame size changes */ - + if (this->type & DLTF_VIDEO) { if (frame->format != this->config.pixelformat) { this->config.flags = DLCONF_PIXELFORMAT; this->config.pixelformat = frame->format; - + lprintf ("changing layer pixelformat to %s.\n", (this->config.pixelformat == DSPF_YUY2) ? "YUY2" : "YV12"); - + ret = this->layer->SetConfiguration (this->layer, &this->config); this->layer->GetConfiguration (this->layer, &this->config); lprintf ("%s.\n", ret ? "failed" : "ok"); } - } - + } + if (this->temp) { /* try to reduce video memory fragmentation */ if (this->temp_frame_width < frame->width || @@ -788,27 +784,27 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge DFBSurfaceDescription dsc; lprintf ("reallocating temporary surface.\n"); - + this->temp->Release (this->temp); this->temp = NULL; - + dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; dsc.caps = DSCAPS_INTERLACED; dsc.width = frame->width; dsc.height = frame->height; dsc.pixelformat = this->config.pixelformat; - + ret = this->dfb->CreateSurface (this->dfb, &dsc, &this->temp); if (ret != DFB_OK) DirectFBError ("IDirectFB::CreateSurface()", ret); - + this->temp_frame_width = frame->width; this->temp_frame_height = frame->height; this->temp_frame_format = this->config.pixelformat; } } - + if (this->sc.delivered_width != frame->width || this->sc.delivered_height != frame->height || this->sc.delivered_ratio != frame->ratio) @@ -816,7 +812,7 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge lprintf ("forcing redraw.\n"); this->sc.force_redraw = 1; } - + directfb_redraw_needed (&this->vo_driver); if (!this->visible) { @@ -828,24 +824,24 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge frame->surface->Unlock (frame->surface); frame->locked = 0; } - + /* source rectangle */ s.x = this->sc.displayed_xoffset; s.y = this->sc.displayed_yoffset; s.w = this->sc.displayed_width; s.h = this->sc.displayed_height; - + /* destination rectangle */ d.x = this->sc.gui_win_x+this->sc.output_xoffset; d.y = this->sc.gui_win_y+this->sc.output_yoffset; d.w = this->sc.output_width; d.h = this->sc.output_height; - + flags = (this->deinterlace) ? DSBLIT_DEINTERLACE : DSBLIT_NOFX; - + if (this->temp) { if (this->hw_deinterlace) { - this->temp->SetField (this->temp, + this->temp->SetField (this->temp, frame->vo_frame.top_field_first ? 0 : 1); this->surface->SetBlittingFlags (this->surface, flags); } @@ -854,23 +850,23 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge frame->vo_frame.top_field_first ? 0 : 1); this->temp->SetBlittingFlags (this->temp, flags); } - + this->temp->Blit (this->temp, frame->surface, &s, 0, 0); s.x = 0; s.y = 0; this->surface->StretchBlit (this->surface, this->temp, &s, &d); - } + } else { frame->surface->SetField (frame->surface, frame->vo_frame.top_field_first ? 0 : 1); this->surface->SetBlittingFlags (this->surface, flags); this->surface->StretchBlit (this->surface, frame->surface, &s, &d); } - + this->surface->Flip (this->surface, NULL, (this->vsync) ? DSFLIP_WAITFORSYNC : DSFLIP_ONSYNC); - - frame->surface->Lock (frame->surface, - DSLF_READ | DSLF_WRITE, + + frame->surface->Lock (frame->surface, + DSLF_READ | DSLF_WRITE, (void**)&frame->vo_frame.base[0], (int *)&frame->vo_frame.pitches[0]); frame->locked = 1; @@ -878,48 +874,48 @@ static void directfb_display_frame2 (vo_driver_t *this_gen, vo_frame_t *frame_ge static int directfb_get_property (vo_driver_t *this_gen, int property) { directfb_driver_t *this = (directfb_driver_t *) this_gen; - + switch (property) { case VO_PROP_INTERLACED: return this->deinterlace; - + case VO_PROP_ASPECT_RATIO: return this->sc.user_ratio; - + case VO_PROP_HUE: if (this->caps & DLCAPS_HUE) return this->cadj.hue; break; - + case VO_PROP_SATURATION: if (this->caps & DLCAPS_SATURATION) return this->cadj.saturation; break; - + case VO_PROP_CONTRAST: if (this->caps & DLCAPS_CONTRAST) return this->cadj.contrast; break; - + case VO_PROP_BRIGHTNESS: if (this->caps & DLCAPS_BRIGHTNESS) return this->cadj.brightness; break; - + case VO_PROP_COLORKEY: if (this->caps & DLCAPS_DST_COLORKEY) return this->colorkey; break; - + case VO_PROP_ZOOM_X: return this->sc.zoom_factor_x * XINE_VO_ZOOM_STEP; - + case VO_PROP_ZOOM_Y: return this->sc.zoom_factor_y * XINE_VO_ZOOM_STEP; - + case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; - + case VO_PROP_WINDOW_HEIGHT: return this->sc.gui_height; @@ -929,21 +925,21 @@ static int directfb_get_property (vo_driver_t *this_gen, int property) { default: break; } - + return 0; } -static int directfb_set_property (vo_driver_t *this_gen, +static int directfb_set_property (vo_driver_t *this_gen, int property, int value) { directfb_driver_t *this = (directfb_driver_t *) this_gen; - + switch (property) { case VO_PROP_INTERLACED: xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_directfb: deinterlacing set to %d.\n", value); this->deinterlace = value; break; - + case VO_PROP_ASPECT_RATIO: if (value >= XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_NUM_RATIOS-1; @@ -954,7 +950,7 @@ static int directfb_set_property (vo_driver_t *this_gen, _x_vo_scale_compute_ideal_size (&this->sc); this->sc.force_redraw = 1; break; - + case VO_PROP_HUE: if (this->caps & DLCAPS_HUE) { if (value > 0xffff) @@ -966,7 +962,7 @@ static int directfb_set_property (vo_driver_t *this_gen, this->layer->SetColorAdjustment (this->layer, &this->cadj); } break; - + case VO_PROP_SATURATION: if (this->caps & DLCAPS_SATURATION) { if (value > 0xffff) @@ -978,7 +974,7 @@ static int directfb_set_property (vo_driver_t *this_gen, this->layer->SetColorAdjustment (this->layer, &this->cadj); } break; - + case VO_PROP_CONTRAST: if (this->caps & DLCAPS_CONTRAST) { if (value > 0xffff) @@ -990,7 +986,7 @@ static int directfb_set_property (vo_driver_t *this_gen, this->layer->SetColorAdjustment (this->layer, &this->cadj); } break; - + case VO_PROP_BRIGHTNESS: if (this->caps & DLCAPS_BRIGHTNESS) { if (value > 0xffff) @@ -1002,7 +998,7 @@ static int directfb_set_property (vo_driver_t *this_gen, this->layer->SetColorAdjustment (this->layer, &this->cadj); } break; - + case VO_PROP_COLORKEY: if (this->caps & DLCAPS_DST_COLORKEY) { if (value > 0xffffff) @@ -1016,7 +1012,7 @@ static int directfb_set_property (vo_driver_t *this_gen, directfb_clean_output_area (this); } break; - + case VO_PROP_ZOOM_X: if (value >= XINE_VO_ZOOM_MIN && value <= XINE_VO_ZOOM_MAX) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, @@ -1026,7 +1022,7 @@ static int directfb_set_property (vo_driver_t *this_gen, this->sc.force_redraw = 1; } break; - + case VO_PROP_ZOOM_Y: if (value >= XINE_VO_ZOOM_MIN && value <= XINE_VO_ZOOM_MAX) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, @@ -1036,29 +1032,29 @@ static int directfb_set_property (vo_driver_t *this_gen, this->sc.force_redraw = 1; } break; - + default: break; - } - + } + return value; } static void directfb_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) { directfb_driver_t *this = (directfb_driver_t *) this_gen; - + switch (property) { case VO_PROP_INTERLACED: *min = 0; *max = 1; return; - + case VO_PROP_ASPECT_RATIO: - *min = 0; + *min = 0; *max = XINE_VO_ASPECT_NUM_RATIOS-1; return; - + case VO_PROP_HUE: if (this->caps & DLCAPS_HUE) { *min = 0x0000; @@ -1066,7 +1062,7 @@ static void directfb_get_property_min_max (vo_driver_t *this_gen, return; } break; - + case VO_PROP_SATURATION: if (this->caps & DLCAPS_SATURATION) { *min = 0x0000; @@ -1074,7 +1070,7 @@ static void directfb_get_property_min_max (vo_driver_t *this_gen, return; } break; - + case VO_PROP_CONTRAST: if (this->caps & DLCAPS_CONTRAST) { *min = 0x0000; @@ -1082,7 +1078,7 @@ static void directfb_get_property_min_max (vo_driver_t *this_gen, return; } break; - + case VO_PROP_BRIGHTNESS: if (this->caps & DLCAPS_BRIGHTNESS) { *min = 0x0000; @@ -1090,7 +1086,7 @@ static void directfb_get_property_min_max (vo_driver_t *this_gen, return; } break; - + case VO_PROP_COLORKEY: if (this->caps & DLCAPS_DST_COLORKEY) { *min = 0x000000; @@ -1098,25 +1094,25 @@ static void directfb_get_property_min_max (vo_driver_t *this_gen, return; } break; - + case VO_PROP_ZOOM_X: case VO_PROP_ZOOM_Y: *min = XINE_VO_ZOOM_MIN; *max = XINE_VO_ZOOM_MAX; return; - + default: break; } - + *min = 0; *max = 0; } -static int directfb_gui_data_exchange (vo_driver_t *this_gen, +static int directfb_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { directfb_driver_t *this = (directfb_driver_t *) this_gen; - + switch (data_type) { case XINE_GUI_SEND_DRAWABLE_CHANGED: lprintf ("drawable changed.\n"); @@ -1130,11 +1126,11 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen, if (this->xoverlay) { x11osd_drawable_changed (this->xoverlay, this->drawable); this->ovl_changed = 1; - } + } UNLOCK_DISPLAY(); this->sc.force_redraw = 1; } -#endif +#endif directfb_clean_output_area (this); break; @@ -1152,13 +1148,13 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen, #endif directfb_clean_output_area (this); break; - + case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: { int x1, y1, x2, y2; x11_rectangle_t *rect = data; - + _x_vo_scale_translate_gui2video (&this->sc, - rect->x, rect->y, + rect->x, rect->y, &x1, &y1); _x_vo_scale_translate_gui2video (&this->sc, rect->x + rect->w, rect->y + rect->h, @@ -1168,11 +1164,11 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen, rect->w = x2-x1; rect->h = y2-y1; } break; - + default: return -1; } - + return 0; } @@ -1181,7 +1177,7 @@ static void directfb_dispose (vo_driver_t *this_gen) { if (this->cur_frame) this->cur_frame->vo_frame.dispose (&this->cur_frame->vo_frame); - + #ifdef DIRECTFB_X11 if (this->visual_type == XINE_VISUAL_TYPE_X11 || this->visual_type == XINE_VISUAL_TYPE_X11_2) { @@ -1195,25 +1191,25 @@ static void directfb_dispose (vo_driver_t *this_gen) { if (this->temp) this->temp->Release (this->temp); - + if (this->spic_surface) this->spic_surface->Release (this->spic_surface); - + if (this->spic_layer) this->spic_layer->Release (this->spic_layer); - + if (this->surface) this->surface->Release (this->surface); - + if (this->layer) { this->layer->SetColorAdjustment (this->layer, &this->default_cadj); this->layer->SetLevel (this->layer, this->default_level); this->layer->Release (this->layer); } - + if (this->underlay) this->underlay->Release (this->underlay); - + if (this->dfb) this->dfb->Release (this->dfb); @@ -1226,12 +1222,12 @@ static void directfb_dispose (vo_driver_t *this_gen) { static void update_config_cb (void *data, xine_cfg_entry_t *entry) { directfb_driver_t *this = (directfb_driver_t *) data; - + lprintf ("update_config_cb(%s).\n", entry->key); - + if (strcmp (entry->key, "video.device.directfb_buffermode") == 0) { DFBDisplayLayerConfig config = { .flags = DLCONF_BUFFERMODE }; - + switch (entry->num_value) { case 0: config.buffermode = DLBM_FRONTONLY; @@ -1243,46 +1239,46 @@ static void update_config_cb (void *data, xine_cfg_entry_t *entry) { config.buffermode = DLBM_BACKVIDEO; break; } - + if (config.buffermode != this->config.buffermode) { if (this->layer->SetConfiguration (this->layer, &config ) != DFB_OK) { xprintf (this->xine, XINE_VERBOSITY_LOG, - "video_out_directfb: failed to set buffermode to %d!\n", + "video_out_directfb: failed to set buffermode to %d!\n", entry->num_value); return; } - + this->layer->GetConfiguration (this->layer, &this->config); } } else if (strcmp (entry->key, "video.device.directfb_colorkeying") == 0) { DFBDisplayLayerConfig config = { .flags = DLCONF_OPTIONS }; - + if (entry->num_value) config.options = this->config.options | DLOP_DST_COLORKEY; else config.options = this->config.options & ~DLOP_DST_COLORKEY; - + if (config.options != this->config.options) { if (this->layer->SetConfiguration (this->layer, &config) != DFB_OK) { xprintf (this->xine, XINE_VERBOSITY_LOG, - "video_out_directfb: failed to set colour keying to %d!\n", + "video_out_directfb: failed to set colour keying to %d!\n", entry->num_value); return; } - + this->layer->GetConfiguration (this->layer, &this->config); directfb_clean_output_area (this); } - } + } else if (strcmp (entry->key, "video.device.directfb_colorkey") == 0) { this->colorkey = entry->num_value; this->layer->SetDstColorKey (this->layer, (this->colorkey & 0xff0000) >> 16, (this->colorkey & 0x00ff00) >> 8, - (this->colorkey & 0x0000ff) >> 0); + (this->colorkey & 0x0000ff) >> 0); #ifdef DIRECTFB_X11 if (this->xoverlay) { - x11osd_colorkey (this->xoverlay, + x11osd_colorkey (this->xoverlay, directfb_colorkey_to_pixel(this), &this->sc); } #endif @@ -1290,52 +1286,52 @@ static void update_config_cb (void *data, xine_cfg_entry_t *entry) { } else if (strcmp (entry->key, "video.device.directfb_flicker_filtering") == 0) { DFBDisplayLayerConfig config = { .flags = DLCONF_OPTIONS }; - + if (entry->num_value) config.options = this->config.options | DLOP_FLICKER_FILTERING; else config.options = this->config.options & ~DLOP_FLICKER_FILTERING; - + if (config.options != this->config.options) { if (this->layer->SetConfiguration (this->layer, &config) != DFB_OK) { xprintf (this->xine, XINE_VERBOSITY_LOG, - "video_out_directfb: failed to set flicker_filtering to %d!\n", + "video_out_directfb: failed to set flicker_filtering to %d!\n", entry->num_value); return; } - + this->layer->GetConfiguration (this->layer, &this->config); } } else if (strcmp (entry->key, "video.device.directfb_field_parity") == 0) { DFBDisplayLayerConfig config = { .flags = DLCONF_OPTIONS }; - + if (entry->num_value) config.options = this->config.options | DLOP_FIELD_PARITY; else config.options = this->config.options & ~DLOP_FIELD_PARITY; - + if (config.options != this->config.options) { if (this->layer->SetConfiguration (this->layer, &config) != DFB_OK) { xprintf (this->xine, XINE_VERBOSITY_LOG, - "video_out_directfb: failed to set field_parity to %d!\n", + "video_out_directfb: failed to set field_parity to %d!\n", entry->num_value); return; } - + this->layer->GetConfiguration (this->layer, &this->config); - } + } } else if (strcmp (entry->key, "video.device.directfb_vsync") == 0) { this->vsync = entry->num_value; } } - + static void init_config (directfb_driver_t *this) { config_values_t *config = this->xine->config; static const char *buffermode_enum[] = {"single", "double", "triple", 0}; static const char *fieldparity_enum[] = {"none", "top", "bottom", 0}; - + this->buffermode = config->register_enum (config, "video.device.directfb_buffermode", this->buffermode, (char**)buffermode_enum, _("video layer buffering mode"), @@ -1343,14 +1339,14 @@ static void init_config (directfb_driver_t *this) { "Double or triple buffering give a smoother playback, " "but consume more video memory."), 10, update_config_cb, (void *)this); - + this->vsync = config->register_bool (config, "video.device.directfb_vsync", this->vsync, _("wait for vertical retrace"), _("Enable synchronizing the update of the video image to the " "repainting of the entire screen (\"vertical retrace\")."), 10, update_config_cb, (void *)this); - + if (this->caps & DLCAPS_DST_COLORKEY) { this->colorkeying = config->register_bool (config, "video.device.directfb_colorkeying", this->colorkeying, @@ -1358,7 +1354,7 @@ static void init_config (directfb_driver_t *this) { _("Enable using a colour key to tell the graphics card " "where to overlay the video image."), 20, update_config_cb, (void *)this); - + this->colorkey = config->register_range (config, "video.device.directfb_colorkey", this->colorkey, 0, 0xffffff, _("video colour key"), @@ -1367,7 +1363,7 @@ static void init_config (directfb_driver_t *this) { "if you experience windows becoming transparent."), 10, update_config_cb, (void *)this); } - + if (this->caps & DLCAPS_FLICKER_FILTERING) { this->flicker_filtering = config->register_bool( config, "video.device.directfb_flicker_filtering", this->flicker_filtering, @@ -1375,7 +1371,7 @@ static void init_config (directfb_driver_t *this) { _("Enable Flicker Filetring for a smooth output on an interlaced display."), 10, update_config_cb, (void *)this); } - + if (this->caps & DLCAPS_FIELD_PARITY) { this->field_parity = config->register_enum( config, "video.device.directfb_field_parity", this->field_parity, (char**)fieldparity_enum, @@ -1389,7 +1385,7 @@ static void init_config (directfb_driver_t *this) { static DFBEnumerationResult find_overlay (DFBDisplayLayerID id, DFBDisplayLayerDescription dsc, void *ctx) { DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx; - + if (dsc.type & DLTF_VIDEO && dsc.caps & DLCAPS_SURFACE && dsc.caps & DLCAPS_SCREEN_LOCATION) { @@ -1397,27 +1393,27 @@ static DFBEnumerationResult find_overlay (DFBDisplayLayerID id, *ret_id = id; return DFENUM_CANCEL; } - + return DFENUM_OK; } static DFBEnumerationResult find_underlay (DFBDisplayLayerID id, DFBDisplayLayerDescription dsc, void *ctx) { DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx; - + if (dsc.caps & DLCAPS_SURFACE) { lprintf ("underlay's id = %d.\n", id); *ret_id = id; return DFENUM_CANCEL; } - + return DFENUM_OK; } static DFBEnumerationResult find_subpicture (DFBDisplayLayerID id, DFBDisplayLayerDescription dsc, void *ctx) { DFBDisplayLayerID *ret_id = (DFBDisplayLayerID *) ctx; - + if (id != DLID_PRIMARY && dsc.caps & DLCAPS_SURFACE && dsc.caps & DLCAPS_ALPHACHANNEL) { @@ -1425,33 +1421,33 @@ static DFBEnumerationResult find_subpicture (DFBDisplayLayerID id, *ret_id = id; return DFENUM_CANCEL; } - + return DFENUM_OK; } static void init_subpicture (directfb_driver_t *this) { DFBResult ret; - + /* subpicture layer supported by Unichrome and Radeon */ if (this->caps & DLCAPS_LEVELS && this->underlay) { DFBDisplayLayerDescription dsc; - + this->underlay->GetDescription (this->underlay, &dsc); if (dsc.caps & DLCAPS_ALPHACHANNEL) { DFBDisplayLayerConfig config; - - /* enable alphachannel on the underlay */ + + /* enable alphachannel on the underlay */ config.flags = DLCONF_PIXELFORMAT | DLCONF_OPTIONS; config.pixelformat = DSPF_ARGB; config.options = DLOP_ALPHACHANNEL; - + ret = this->underlay->SetConfiguration (this->underlay, &config); if (ret) { /* try AiRGB if the previous failed */ - config.pixelformat = DSPF_AiRGB; + config.pixelformat = DSPF_AiRGB; ret = this->underlay->SetConfiguration (this->underlay, &config); } - + if (ret == DFB_OK) { this->underlay->AddRef (this->underlay); this->spic_layer = this->underlay; @@ -1460,33 +1456,33 @@ static void init_subpicture (directfb_driver_t *this) { } } } -#if 0 +#if 0 /* most common type of supicture layer */ if (!this->spic_layer) { IDirectFBScreen *screen; DFBDisplayLayerID video_id, id = -1; - + this->layer->GetID (this->layer, &video_id); - + if (this->layer->GetScreen (this->layer, &screen) == DFB_OK) { screen->EnumDisplayLayers (screen, find_subpicture, (void *)&id); screen->Release (screen); } - - if (id != -1 && id != video_id) { + + if (id != -1 && id != video_id) { ret = this->dfb->GetDisplayLayer (this->dfb, id, &this->spic_layer); if (ret == DFB_OK) { DFBDisplayLayerConfig config; - + this->spic_layer->GetConfiguration (this->spic_layer, &config); - + config.flags = DLCONF_OPTIONS; config.options = DLOP_ALPHACHANNEL; if (!DFB_PIXELFORMAT_HAS_ALPHA(config.pixelformat)) { config.flags |= DLCONF_PIXELFORMAT; config.pixelformat = DSPF_ALUT44; } - + ret = this->spic_layer->SetConfiguration (this->spic_layer, &config); if (ret) { lprintf ("failed to set subpicture layer configuration!\n"); @@ -1499,7 +1495,7 @@ static void init_subpicture (directfb_driver_t *this) { } } } -#endif +#endif if (this->spic_layer) { ret = this->spic_layer->GetSurface (this->spic_layer, &this->spic_surface); if (ret) { @@ -1508,10 +1504,10 @@ static void init_subpicture (directfb_driver_t *this) { this->spic_layer = NULL; return; } - + this->spic_surface->Clear (this->spic_surface, 0, 0, 0, 0); this->spic_surface->Flip (this->spic_surface, NULL, 0); - + xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: using hardware subpicture acceleration.\n")); } @@ -1524,18 +1520,18 @@ static DFBResult init_device (directfb_driver_t *this) { DFBResult ret; config.flags = DLCONF_NONE; - + if (this->type & DLTF_VIDEO) { xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: layer supports video output.\n")); config.flags |= DLCONF_PIXELFORMAT; - + /* test for YV12 support */ config.pixelformat = DSPF_YV12; ret = this->layer->TestConfiguration (this->layer, &config, NULL); if (ret) { - xprintf (this->xine, XINE_VERBOSITY_LOG, + xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: layer doesn't support YV12!\n")); /* test for YUY2 support */ @@ -1550,7 +1546,7 @@ static DFBResult init_device (directfb_driver_t *this) { } } } - + #if DIRECTFB_VERSION_CODE < VERSION_CODE(0,9,25) if (!(this->type & DLTF_VIDEO)) { xprintf (this->xine, XINE_VERBOSITY_LOG, @@ -1558,12 +1554,12 @@ static DFBResult init_device (directfb_driver_t *this) { "need at least DirectFB 0.9.25 to play on this layer!\n")); return DFB_UNSUPPORTED; } -#endif - +#endif + /* set layer configuration */ config.flags |= DLCONF_BUFFERMODE | DLCONF_OPTIONS; config.options = DLOP_NONE; - + switch (this->buffermode) { case 0: config.buffermode = DLBM_FRONTONLY; @@ -1575,22 +1571,22 @@ static DFBResult init_device (directfb_driver_t *this) { config.buffermode = DLBM_BACKVIDEO; break; } - + if (this->colorkeying) config.options |= DLOP_DST_COLORKEY; - + if (this->flicker_filtering) config.options |= DLOP_FLICKER_FILTERING; - + if (this->field_parity) config.options |= DLOP_FIELD_PARITY; - + /* test current configuration */ ret = this->layer->TestConfiguration (this->layer, &config, &failed); if (failed & DLCONF_BUFFERMODE) { xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: layer doesn't support buffermode %d!\n"), - this->buffermode); + this->buffermode); config.flags &= ~DLCONF_BUFFERMODE; } if (failed & DLCONF_OPTIONS) { @@ -1599,7 +1595,7 @@ static DFBResult init_device (directfb_driver_t *this) { config.options); config.flags &= ~DLCONF_OPTIONS; } - + ret = this->layer->SetConfiguration (this->layer, &config); /* this should never happen */ if (ret) { @@ -1607,31 +1603,31 @@ static DFBResult init_device (directfb_driver_t *this) { return ret; } - this->layer->GetConfiguration (this->layer, &this->config); - + this->layer->GetConfiguration (this->layer, &this->config); + if (this->caps & DLCAPS_DST_COLORKEY) { this->layer->SetDstColorKey (this->layer, (this->colorkey & 0xff0000) >> 16, (this->colorkey & 0x00ff00) >> 8, (this->colorkey & 0x0000ff) >> 0); } - + if (this->field_parity) this->layer->SetFieldParity (this->layer, this->field_parity-1); - + /* get current color cadjustment */ this->layer->GetColorAdjustment (this->layer, &this->default_cadj); this->cadj = this->default_cadj; - + /* get current level */ this->layer->GetLevel (this->layer, &this->default_level); - + /* retrieve layer's surface */ ret = this->layer->GetSurface (this->layer, &surface); if (ret != DFB_OK) { DirectFBError ("IDirectFBDisplayLayer::GetSurface()", ret); return ret; } - + /* clear surface buffers */ surface->Clear (surface, 0x00, 0x00, 0x00, 0xff); surface->Flip (surface, NULL, 0); @@ -1639,33 +1635,33 @@ static DFBResult init_device (directfb_driver_t *this) { surface->Flip (surface, NULL, 0); surface->Clear (surface, 0x00, 0x00, 0x00, 0xff); surface->Flip (surface, NULL, 0); - + this->surface = surface; - - if (this->caps & DLCAPS_SCREEN_LOCATION) { + + if (this->caps & DLCAPS_SCREEN_LOCATION) { IDirectFBScreen *screen = NULL; DFBDisplayLayerID id = -1; this->screen_width = 640; this->screen_height = 480; - + this->layer->GetScreen (this->layer, &screen); if (screen) { screen->EnumDisplayLayers (screen, find_underlay, (void *)&id); screen->Release (screen); } - + this->dfb->GetDisplayLayer (this->dfb, id, &this->underlay); - if (this->underlay) { + if (this->underlay) { this->underlay->GetConfiguration (this->underlay, &config); this->screen_width = config.width; this->screen_height = config.height; - + if (this->visual_type == XINE_VISUAL_TYPE_FB) { this->underlay->SetCooperativeLevel (this->underlay, DLSCL_EXCLUSIVE); this->underlay->SetConfiguration (this->underlay, &config); } - } + } } else { /* playing to underlay, @@ -1673,42 +1669,42 @@ static DFBResult init_device (directfb_driver_t *this) { IDirectFBSurface *temp; DFBSurfaceDescription dsc; DFBAccelerationMask mask = DFXL_NONE; - + this->layer->AddRef (this->layer); this->underlay = this->layer; - + dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT; dsc.caps = DSCAPS_INTERLACED; dsc.width = 320; dsc.height = 240; dsc.pixelformat = this->config.pixelformat; - + if (this->dfb->CreateSurface (this->dfb, &dsc, &temp) == DFB_OK) { this->surface->GetAccelerationMask (this->surface, temp, &mask); - + if (mask & DFXL_STRETCHBLIT) { xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: " "using hardware accelerated image scaling.\n")); this->temp = temp; - + /* check if stretchblit with deinterlacing is supported */ this->surface->SetBlittingFlags (this->surface, DSBLIT_DEINTERLACE); this->surface->GetAccelerationMask (this->surface, temp, &mask); this->surface->SetBlittingFlags (this->surface, DSBLIT_NOFX); - + this->hw_deinterlace = (mask & DFXL_STRETCHBLIT) ? 1 : 0; if (this->hw_deinterlace) { xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: " "image scaling with deinterlacing is hardware accelerated.\n")); } - + /* used to decide reallocation */ temp->GetSize (temp, &this->temp_frame_width, &this->temp_frame_height); temp->GetPixelFormat (temp, &this->temp_frame_format); - } + } else temp->Release (temp); } @@ -1718,11 +1714,11 @@ static DFBResult init_device (directfb_driver_t *this) { } xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "video_out_directfb: screen size is %dx%d.\n", + "video_out_directfb: screen size is %dx%d.\n", this->screen_width, this->screen_height); - + return DFB_OK; -} +} static void directfb_frame_output_cb (void *user_data, int video_width, int video_height, double video_pixel_aspect, int *dest_x, int *dest_y, @@ -1740,7 +1736,7 @@ static void directfb_frame_output_cb (void *user_data, int video_width, int vide *win_y = 0; } -/*** DirectFB plugin functions ***/ +/*** DirectFB plugin functions ***/ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void *visual_gen) { directfb_class_t *class = (directfb_class_t *) class_gen; @@ -1753,21 +1749,21 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void DFBDisplayLayerID id; DFBResult ret; - this = xine_xmalloc (sizeof (directfb_driver_t)); + this = calloc(1, sizeof(directfb_driver_t)); if (!this) return NULL; - + this->visual_type = XINE_VISUAL_TYPE_FB; this->xine = class->xine; - - /* initialize DirectFB */ + + /* initialize DirectFB */ ret = DirectFBInit (&argn, &argp); if (ret != DFB_OK) { DirectFBError ("DirectFBInit()", ret); free (this); return NULL; } - + /* create the main interface or retrieve an already existing one */ ret = DirectFBCreate (&this->dfb); if (ret != DFB_OK) { @@ -1775,7 +1771,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void free (this); return NULL; } - + /* allow user/application to select a different layer */ id = config->register_num (config, "video.device.directfb_layer_id", -1, @@ -1784,7 +1780,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void 20, NULL, 0); if (id == -1) { IDirectFBScreen *screen; - + /* retrieve an interface to the current screen */ ret = this->dfb->GetScreen (this->dfb, DSCID_PRIMARY, &screen); if (ret != DFB_OK) { @@ -1793,7 +1789,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void free (this); return NULL; } - + /* find an overlay layer on the current screen */ id = DLID_PRIMARY; screen->EnumDisplayLayers (screen, find_overlay, (void*)&id); @@ -1802,11 +1798,11 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: using display layer #%d.\n"), id); - + ret = this->dfb->GetDisplayLayer (this->dfb, id, &this->layer); if (ret == DFB_OK) { DFBDisplayLayerDescription dsc; - this->layer->SetCooperativeLevel (this->layer, DLSCL_EXCLUSIVE); + this->layer->SetCooperativeLevel (this->layer, DLSCL_EXCLUSIVE); this->layer->SetOpacity (this->layer, 0x00); this->layer->GetDescription (this->layer, &dsc); this->type = dsc.type; @@ -1820,7 +1816,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void free (this); return NULL; } - + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; /* set default configuration */ this->buffermode = 1; // double @@ -1829,7 +1825,7 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void this->colorkey = DEFAULT_COLORKEY; this->flicker_filtering = 0; this->field_parity = 0; - + /* get user configuration */ init_config (this); @@ -1840,19 +1836,19 @@ static vo_driver_t *open_plugin_fb (video_driver_class_t *class_gen, const void free (this); return NULL; } - + /* initialize subpicture layer (if available) */ init_subpicture (this); if (this->spic_layer) this->capabilities |= VO_CAP_UNSCALED_OVERLAY; _x_alphablend_init (&this->alphablend_extra_data, this->xine); - + _x_vo_scale_init (&this->sc, 1, 0, this->xine->config); this->sc.user_ratio = XINE_VO_ASPECT_AUTO; this->sc.gui_width = this->screen_width; - this->sc.gui_height = this->screen_height; - + this->sc.gui_height = this->screen_height; + if (visual) { this->sc.frame_output_cb = visual->frame_output_cb; this->sc.user_data = visual->user_data; @@ -1908,7 +1904,7 @@ static void *init_class_fb (xine_t *xine, void *visual_gen) { return NULL; } - this = (directfb_class_t *) xine_xmalloc (sizeof (directfb_class_t)); + this = (directfb_class_t *) calloc(1, sizeof(directfb_class_t)); this->driver_class.open_plugin = open_plugin_fb; this->driver_class.get_identifier = get_identifier_fb; this->driver_class.get_description = get_description_fb; @@ -1939,21 +1935,21 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void DFBDisplayLayerID id = DLID_PRIMARY; DFBResult ret; - this = xine_xmalloc (sizeof (directfb_driver_t)); + this = calloc(1, sizeof(directfb_driver_t)); if (!this) return NULL; - + this->visual_type = class->visual_type; this->xine = class->xine; - - /* initialize DirectFB */ + + /* initialize DirectFB */ ret = DirectFBInit (&argn, &argp); if (ret != DFB_OK) { DirectFBError ("DirectFBInit()", ret); free (this); return NULL; } - + /* create the main interface or retrieve an already existing one */ ret = DirectFBCreate (&this->dfb); if (ret != DFB_OK) { @@ -1961,7 +1957,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void free (this); return NULL; } - + /* retrieve an interface to the current screen */ ret = this->dfb->GetScreen (this->dfb, DSCID_PRIMARY, &screen); if (ret != DFB_OK) { @@ -1970,7 +1966,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void free (this); return NULL; } - + /* find an overlay layer on the current screen */ ret = screen->EnumDisplayLayers (screen, find_overlay, (void*)&id); screen->Release (screen); @@ -1980,7 +1976,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void free (this); return NULL; } - + if (id != DLID_PRIMARY) { DFBDisplayLayerDescription dsc; /* get overlay access */ @@ -2001,7 +1997,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void this->layer = NULL; } } - + if (!this->layer) { xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: no usable display layer was found!\n")); @@ -2009,10 +2005,10 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void free (this); return NULL; } - + xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_directfb: using display layer #%d.\n"), id); - + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; /* set default configuration */ this->buffermode = 1; // double @@ -2021,7 +2017,7 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void this->colorkey = DEFAULT_COLORKEY; this->flicker_filtering = 0; this->field_parity = 0; - + /* get user configuration */ init_config (this); @@ -2032,42 +2028,42 @@ static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void free (this); return NULL; } - + this->display = visual->display; this->screen = visual->screen; this->drawable = visual->d; this->gc = XCreateGC (this->display, this->drawable, 0, NULL); - + XGetWindowAttributes (this->display, this->drawable, &attrs); this->depth = attrs.depth; _x_alphablend_init (&this->alphablend_extra_data, this->xine); - + _x_vo_scale_init (&this->sc, 1, 0, this->xine->config); this->sc.user_ratio = XINE_VO_ASPECT_AUTO; this->sc.gui_width = attrs.width; this->sc.gui_height = attrs.height; this->sc.frame_output_cb = visual->frame_output_cb; this->sc.user_data = visual->user_data; - + if (this->visual_type == XINE_VISUAL_TYPE_X11_2) { this->user_data = visual->user_data; this->lock_display = visual->lock_display; this->unlock_display = visual->unlock_display; - } - + } + if (this->colorkeying) { this->xoverlay = x11osd_create (this->xine, this->display, this->screen, this->drawable, X11OSD_COLORKEY); if (this->xoverlay) { - x11osd_colorkey (this->xoverlay, + x11osd_colorkey (this->xoverlay, directfb_colorkey_to_pixel(this), &this->sc); } } else { this->xoverlay = x11osd_create (this->xine, this->display, this->screen, this->drawable, X11OSD_SHAPED); } - + if (this->xoverlay) this->capabilities |= VO_CAP_UNSCALED_OVERLAY; @@ -2116,18 +2112,18 @@ static void *init_class_x11 (xine_t *xine, void *visual_gen) { "video_out_directfb: %s!\n", error); return NULL; } - + if (!visual) { xprintf (xine, XINE_VERBOSITY_DEBUG, "video_out_directfb: x11 visual is required!\n"); return NULL; } - + /* check if we are running under XDirectFB */ if (strcmp (XServerVendor (visual->display), "Denis Oliver Kropp")) return NULL; - this = (directfb_class_t *) xine_xmalloc (sizeof (directfb_class_t)); + this = (directfb_class_t *) calloc(1, sizeof(directfb_class_t)); this->driver_class.open_plugin = open_plugin_x11; this->driver_class.get_identifier = get_identifier_x11; this->driver_class.get_description = get_description_x11; @@ -2145,7 +2141,7 @@ static void *init_class_x11_2 (xine_t *xine, void *visual_gen) { this = init_class_x11( xine, visual_gen ); if (this) this->visual_type = XINE_VISUAL_TYPE_X11_2; - + return this; } diff --git a/src/video_out/video_out_directfb_fb.c b/src/video_out/video_out_directfb_fb.c index b904407c3..bb01c187b 100644 --- a/src/video_out/video_out_directfb_fb.c +++ b/src/video_out/video_out_directfb_fb.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2007 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/src/video_out/video_out_directfb_x.c b/src/video_out/video_out_directfb_x.c index 48f709eae..78aaa9588 100644 --- a/src/video_out/video_out_directfb_x.c +++ b/src/video_out/video_out_directfb_x.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2007 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c index 11ee709e1..8cb72238a 100644 --- a/src/video_out/video_out_directx.c +++ b/src/video_out/video_out_directx.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -21,6 +21,10 @@ * by Matthew Grooms <elon@altavista.com> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + typedef unsigned char boolean; #include <windows.h> @@ -55,21 +59,33 @@ typedef unsigned char boolean; * the linking stage. *****************************************************************************/ #if 1 -static const GUID IID_IDirectDraw = { +static const GUID xine_IID_IDirectDraw = { 0x6C14DB80,0xA733,0x11CE,{0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60} }; +#ifdef IID_IDirectDraw +# undef IID_IDirectDraw +#endif +#define IID_IDirectDraw xine_IID_IDirectDraw #endif #if 0 static const GUID IID_IDirectDraw2 = { 0xB3A6F3E0,0x2B43,0x11CF,{0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56} }; +#ifdef IID_IDirectDraw2 +# undef IID_IDirectDraw2 +#endif +#define IID_IDirectDraw2 xine_IID_IDirectDraw2 #endif #if 0 static const GUID IID_IDirectDraw4 = { 0x9C59509A,0x39BD,0x11D1,{0x8C,0x4A,0x00,0xC0,0x4F,0xD9,0x30,0xC5} }; +#ifdef IID_IDirectDraw4 +# undef IID_IDirectDraw4 +#endif +#define IID_IDirectDraw4 xine_IID_IDirectDraw4 #endif /* ----------------------------------------- @@ -102,7 +118,7 @@ typedef struct { LPDIRECTDRAW ddobj; /* direct draw object */ LPDIRECTDRAWSURFACE primary; /* primary dd surface */ - LPDIRECTDRAWSURFACE secondary; /* secondary dd surface */ + LPDIRECTDRAWSURFACE secondary; /* secondary dd surface */ LPDIRECTDRAWCLIPPER ddclipper; /* dd clipper object */ uint8_t * contents; /* secondary contents */ win32_frame_t *current; /* current frame */ @@ -117,7 +133,8 @@ typedef struct { yuv2rgb_t *yuv2rgb; /* used for format conversion */ int mode; /* rgb mode */ int bytespp; /* rgb bits per pixel */ - + DDPIXELFORMAT primary_pixel_format; + DDSURFACEDESC ddsd; /* set by Lock(), used during display_frame */ alphablend_t alphablend_extra_data; } win32_driver_t; @@ -134,7 +151,7 @@ typedef struct { * * ----------------------------------------- */ -/* Display formatted error message in +/* Display formatted error message in * popup message box.*/ static void Error( HWND hwnd, LPSTR szfmt, ... ) @@ -152,7 +169,7 @@ static void UpdateRect( win32_visual_t * win32_visual ) { if( win32_visual->FullScreen ) { - SetRect( &win32_visual->WndRect, 0, 0, + SetRect( &win32_visual->WndRect, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) ); } @@ -164,12 +181,12 @@ static void UpdateRect( win32_visual_t * win32_visual ) } } -/* Create our direct draw object, primary +/* Create our direct draw object, primary * surface and clipper object. * - * NOTE : The primary surface is more or + * NOTE : The primary surface is more or * less a viewport into the parent desktop - * window and will always have a pixel format + * window and will always have a pixel format * identical to the current display mode. */ static boolean CreatePrimary( win32_driver_t * win32_driver ) @@ -259,7 +276,7 @@ static boolean CreatePrimary( win32_driver_t * win32_driver ) } /* Create our secondary ( off screen ) buffer. - * The optimal secondary buffer is a h/w + * The optimal secondary buffer is a h/w * overlay with the same pixel format as the * xine frame type. However, since this is * not always supported by the host h/w, @@ -310,7 +327,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he /* the requested format is XINE_IMGFMT_YV12 */ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; + ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwYUVBitCount = 16; @@ -326,7 +343,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he /* the requested format is XINE_IMGFMT_YUY2 */ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; + ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC; ddsd.ddpfPixelFormat.dwYUVBitCount = 16; @@ -343,7 +360,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he /* the requested format is IMGFMT_RGB */ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; - ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; + ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY; ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT); ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB; ddsd.ddpfPixelFormat.dwYUVBitCount = 24; @@ -354,7 +371,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he lprintf("CreateSecondary() - act_format = (RGB) %d\n", IMGFMT_RGB); win32_driver->act_format = IMGFMT_RGB; - } + } #endif /* RGB_SUPPORT */ lprintf("CreateSecondary() - IDirectDraw_CreateSurface()\n"); @@ -367,8 +384,9 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he lprintf("CreateSecondary() - Falling back to back buffer same as primary\n"); lprintf("CreateSecondary() - act_format = (NATIVE) %d\n", IMGFMT_NATIVE); - ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; + ddsd.ddpfPixelFormat = win32_driver->primary_pixel_format; win32_driver->act_format = IMGFMT_NATIVE; if( IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK ) @@ -405,7 +423,7 @@ static void Destroy( win32_driver_t * win32_driver ) IDirectDraw_Release( win32_driver->ddobj ); _x_alphablend_free(&win32_driver->alphablend_extra_data); - + free( win32_driver ); } @@ -430,6 +448,10 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver ) return 0; } + /* store pixel format for CreateSecondary */ + + win32_driver->primary_pixel_format = ddpf; + /* TODO : support paletized video modes */ if( ( ddpf.dwFlags & DDPF_PALETTEINDEXED1 ) || @@ -478,13 +500,15 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver ) win32_driver->mode = MODE_15_BGR; } + lprintf("win32 mode: %u\n", win32_driver->mode); return TRUE; } +#if 0 /* Create a Direct draw surface from * a bitmap resource.. * - * NOTE : This is not really useful + * NOTE : This is not really useful * anymore since the xine logo code is * being pushed to the backend. */ @@ -523,7 +547,7 @@ static LPDIRECTDRAWSURFACE CreateBMP( win32_driver_t * win32_driver, int resourc Error( 0, "CreateSurface ( bitmap ) : could not create dd surface" ); return 0; } - + /* get a handle to our surface dc, * create a compat dc and load * our bitmap into the compat dc */ @@ -546,8 +570,9 @@ static LPDIRECTDRAWSURFACE CreateBMP( win32_driver_t * win32_driver, int resourc return bmp_surf; } +#endif -/* Merge overlay with the current primary +/* Merge overlay with the current primary * surface. This funtion is only used when * a h/w overlay of the current frame type * is supported. */ @@ -558,7 +583,7 @@ static boolean Overlay( LPDIRECTDRAWSURFACE src_surface, RECT * src_rect, { DWORD dw_color_key; DDPIXELFORMAT ddpf; - DDOVERLAYFX ddofx; + DDOVERLAYFX ddofx; int flags; HRESULT result; @@ -755,23 +780,22 @@ static boolean DisplayFrame( win32_driver_t * win32_driver ) /* Lock our back buffer to update its contents. */ -static void * Lock( void * surface ) +static void * Lock( win32_driver_t * win32_driver, void * surface ) { LPDIRECTDRAWSURFACE lock_surface = ( LPDIRECTDRAWSURFACE ) surface; - DDSURFACEDESC ddsd; HRESULT result; if( !surface ) return 0; - memset( &ddsd, 0, sizeof( ddsd ) ); - ddsd.dwSize = sizeof( ddsd ); + memset( &win32_driver->ddsd, 0, sizeof( win32_driver->ddsd ) ); + win32_driver->ddsd.dwSize = sizeof( win32_driver->ddsd ); - result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); + result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); if( result == DDERR_SURFACELOST ) { IDirectDrawSurface_Restore( lock_surface ); - result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); + result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 ); if( result != DD_OK ) return 0; @@ -786,7 +810,7 @@ static void * Lock( void * surface ) } } - return ddsd.lpSurface; + return win32_driver->ddsd.lpSurface; } /* Unlock our back buffer to prepair for display. */ @@ -863,7 +887,7 @@ static vo_frame_t * win32_alloc_frame( vo_driver_t * vo_driver ) { win32_frame_t *win32_frame; - win32_frame = ( win32_frame_t * ) xine_xmalloc( sizeof( win32_frame_t ) ); + win32_frame = calloc(1, sizeof(win32_frame_t)); if (!win32_frame) return NULL; @@ -879,7 +903,7 @@ static vo_frame_t * win32_alloc_frame( vo_driver_t * vo_driver ) } -static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_frame, uint32_t width, +static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_frame, uint32_t width, uint32_t height, double ratio, int format, int flags ) { win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver; @@ -929,7 +953,7 @@ static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_ #endif else { - xprintf (win32_driver->xine, XINE_VERBOSITY_DEBUG, + xprintf (win32_driver->xine, XINE_VERBOSITY_DEBUG, "vo_out_directx : !!! unsupported image format %04x !!!\n", format ); exit (1); } @@ -946,8 +970,6 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame { win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver; win32_frame_t *win32_frame = ( win32_frame_t * ) vo_frame; - int offset; - int size; /* if the required width, height or format has changed @@ -966,7 +988,7 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame /* lock our surface to update its contents */ - win32_driver->contents = Lock( win32_driver->secondary ); + win32_driver->contents = Lock( win32_driver, win32_driver->secondary ); /* surface unavailable, skip frame render */ @@ -993,13 +1015,13 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame #if NEW_YUV win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, - win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1], + win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1], win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp); #else yuv2rgb_setup( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, - win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1], + win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1], win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp ); @@ -1019,7 +1041,7 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame #if NEW_YUV win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb, win32_driver->width, win32_driver->height, - win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[0] / 2, + win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[0] / 2, win32_driver->width, win32_driver->height, win32_driver->width * win32_driver->bytespp ); #else @@ -1051,37 +1073,47 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame /* the actual format is identical to our * stream format. we just need to copy it */ - switch(win32_frame->format) + int line; + uint8_t * src; + vo_frame_t * frame = vo_frame; + uint8_t * dst = (uint8_t *)win32_driver->contents; + + switch(win32_frame->format) { - case XINE_IMGFMT_YV12: - { - vo_frame_t *frame; - uint8_t *img; - - frame = vo_frame; - img = (uint8_t *)win32_driver->contents; - - offset = 0; - size = frame->pitches[0] * frame->height; - xine_fast_memcpy( img+offset, frame->base[0], size); - - offset += size; - size = frame->pitches[2]* frame->height / 2; - xine_fast_memcpy( img+offset, frame->base[2], size); - - offset += size; - size = frame->pitches[1] * frame->height / 2; - xine_fast_memcpy( img+offset, frame->base[1], size); - } + case XINE_IMGFMT_YV12: + src = frame->base[0]; + for (line = 0; line < frame->height ; line++){ + xine_fast_memcpy( dst, src, frame->width); + src += vo_frame->pitches[0]; + dst += win32_driver->ddsd.lPitch; + } + + src = frame->base[2]; + for (line = 0; line < frame->height/2 ; line++){ + xine_fast_memcpy( dst, src, frame->width/2); + src += vo_frame->pitches[2]; + dst += win32_driver->ddsd.lPitch/2; + } + + src = frame->base[1]; + for (line = 0; line < frame->height/2 ; line++){ + xine_fast_memcpy( dst, src, frame->width/2); + src += vo_frame->pitches[1]; + dst += win32_driver->ddsd.lPitch/2; + } break; + case XINE_IMGFMT_YUY2: - xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2); - break; default: - xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2); + src = frame->base[0]; + for (line = 0; line < frame->height ; line++){ + xine_fast_memcpy( dst, src, frame->width*2); + src += vo_frame->pitches[0]; + dst += win32_driver->ddsd.lPitch; + } break; } - } + } /* unlock the surface */ @@ -1143,11 +1175,38 @@ static int win32_gui_data_exchange( vo_driver_t * vo_driver, int data_type, void switch( data_type ) { + case GUI_WIN32_MOVED_OR_RESIZED: UpdateRect( win32_driver->win32_visual ); DisplayFrame( win32_driver ); break; + case XINE_GUI_SEND_DRAWABLE_CHANGED: + { + HRESULT result; + HWND newWndHnd = (HWND) data; + + /* set cooperative level */ + result = IDirectDraw_SetCooperativeLevel( win32_driver->ddobj, newWndHnd, DDSCL_NORMAL ); + if( result != DD_OK ) + { + Error( 0, "SetCooperativeLevel : error 0x%lx", result ); + return 0; + } + /* associate our clipper with new window */ + result = IDirectDrawClipper_SetHWnd( win32_driver->ddclipper, 0, newWndHnd ); + if( result != DD_OK ) + { + Error( 0, "ddclipper->SetHWnd : error 0x%lx", result ); + return 0; + } + /* store our objects in our visual struct */ + win32_driver->win32_visual->WndHnd = newWndHnd; + /* update video area and redraw current frame */ + UpdateRect( win32_driver->win32_visual ); + DisplayFrame( win32_driver ); + break; } + } return 0; } @@ -1158,15 +1217,15 @@ static int win32_redraw_needed(vo_driver_t* this_gen) int ret = 0; /* TC - May need to revisit this! */ -#ifdef TC +#ifdef TC win32_driver_t *win32_driver = (win32_driver_t *) this_gen; if( _x_vo_scale_redraw_needed( &win32_driver->sc ) ) { - win32_gui_data_exchange(this_gen, GUI_WIN32_MOVED_OR_RESIZED, 0); + win32_gui_data_exchange(this_gen, GUI_WIN32_MOVED_OR_RESIZED, 0); ret = 1; } #endif - + return ret; } @@ -1183,11 +1242,11 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *wi /*vo_driver_t *init_video_out_plugin( config_values_t * config, void * win32_visual )*/ { directx_class_t *class = (directx_class_t *)class_gen; - win32_driver_t *win32_driver = ( win32_driver_t * ) xine_xmalloc ( sizeof( win32_driver_t ) ); + win32_driver_t *win32_driver = calloc(1, sizeof(win32_driver_t)); _x_alphablend_init(&win32_driver->alphablend_extra_data, class->xine); - + win32_driver->xine = class->xine; /* Make sure that the DirectX drivers are available and present! */ @@ -1249,7 +1308,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { /* * from this point on, nothing should go wrong anymore */ - directx = (directx_class_t *) xine_xmalloc (sizeof (directx_class_t)); + directx = calloc(1, sizeof (directx_class_t)); directx->driver_class.open_plugin = open_plugin; directx->driver_class.get_identifier = get_identifier; @@ -1258,7 +1317,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { directx->xine = xine; directx->config = xine->config; - + return directx; } diff --git a/src/video_out/video_out_fb.c b/src/video_out/video_out_fb.c index 95060a4d8..315e77e66 100644 --- a/src/video_out/video_out_fb.c +++ b/src/video_out/video_out_fb.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2003 the xine project and Fredrik Noring - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -52,8 +52,8 @@ #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> -#include <fcntl.h> - +#include <fcntl.h> + #include "xine.h" #include "video_out.h" @@ -89,7 +89,7 @@ typedef struct fb_frame_s int format; int flags; - + vo_scale_t sc; uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ @@ -97,7 +97,7 @@ typedef struct fb_frame_s yuv2rgb_t *yuv2rgb; /* yuv2rgb converter for this frame */ uint8_t *rgb_dst; int yuv_stride; - + int bytes_per_line; uint8_t* video_mem; /* mmapped video memory */ @@ -114,12 +114,12 @@ typedef struct fb_driver_s int fd; int mem_size; uint8_t* video_mem_base; /* mmapped video memory */ - + int depth, bpp, bytes_per_pixel; - + int total_num_native_buffers; int used_num_buffers; - + int yuv2rgb_mode; int yuv2rgb_swap; int yuv2rgb_brightness; @@ -132,11 +132,11 @@ typedef struct fb_driver_s /* size / aspect ratio calculations */ vo_scale_t sc; - + int fb_bytes_per_line; fb_frame_t *cur_frame, *old_frame; - + struct fb_var_screeninfo fb_var; struct fb_fix_screeninfo fb_fix; @@ -161,10 +161,10 @@ static uint32_t fb_get_capabilities(vo_driver_t *this_gen) static void fb_frame_proc_slice(vo_frame_t *vo_img, uint8_t **src) { fb_frame_t *frame = (fb_frame_t *)vo_img ; - + vo_img->proc_called = 1; - - if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) { /* we don't support crop, so don't even waste cpu cycles. @@ -184,18 +184,18 @@ static void fb_frame_proc_slice(vo_frame_t *vo_img, uint8_t **src) static void fb_frame_field(vo_frame_t *vo_img, int which_field) { fb_frame_t *frame = (fb_frame_t *)vo_img ; - + switch(which_field) { case VO_TOP_FIELD: frame->rgb_dst = frame->data; break; - + case VO_BOTTOM_FIELD: frame->rgb_dst = frame->data + frame->bytes_per_line ; break; - + case VO_BOTH_FIELDS: frame->rgb_dst = frame->data; break; @@ -221,23 +221,23 @@ static vo_frame_t *fb_alloc_frame(vo_driver_t *this_gen) this->total_num_native_buffers <= this->used_num_buffers) return 0; - frame = (fb_frame_t *)xine_xmalloc(sizeof(fb_frame_t)); + frame = calloc(1, sizeof(fb_frame_t)); if(!frame) return NULL; memcpy(&frame->sc, &this->sc, sizeof(vo_scale_t)); pthread_mutex_init(&frame->vo_frame.mutex, NULL); - + /* supply required functions */ frame->vo_frame.proc_slice = fb_frame_proc_slice; frame->vo_frame.proc_frame = NULL; - frame->vo_frame.field = fb_frame_field; + frame->vo_frame.field = fb_frame_field; frame->vo_frame.dispose = fb_frame_dispose; frame->vo_frame.driver = this_gen; - + frame->this = this; - + /* colorspace converter for this frame */ frame->yuv2rgb = this->yuv2rgb_factory->create_converter(this->yuv2rgb_factory); @@ -268,7 +268,7 @@ static void fb_compute_ideal_size(fb_driver_t *this, fb_frame_t *frame) static void fb_compute_rgb_size(fb_driver_t *this, fb_frame_t *frame) { _x_vo_scale_compute_output_size(&frame->sc); - + /* avoid problems in yuv2rgb */ if(frame->sc.output_height < (frame->sc.delivered_height+15) >> 4) frame->sc.output_height = (frame->sc.delivered_height+15) >> 4; @@ -277,7 +277,7 @@ static void fb_compute_rgb_size(fb_driver_t *this, fb_frame_t *frame) frame->sc.output_width = 8; /* yuv2rgb_mlib needs an even YUV2 width */ - if (frame->sc.output_width & 1) + if (frame->sc.output_width & 1) frame->sc.output_width++; lprintf("frame source %d x %d => screen output %d x %d%s\n", @@ -305,7 +305,7 @@ static void setup_colorspace_converter(fb_frame_t *frame, int flags) frame->bytes_per_line * 2); frame->yuv_stride = frame->bytes_per_line * 2; break; - + case VO_BOTH_FIELDS: frame->yuv2rgb-> configure(frame->yuv2rgb, @@ -324,22 +324,11 @@ static void setup_colorspace_converter(fb_frame_t *frame, int flags) static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, uint32_t width, uint32_t height, int format) { - if(frame->chunk[0]) - { - free(frame->chunk[0]); - frame->chunk[0] = NULL; - } - if(frame->chunk[1]) - { - free(frame->chunk[1]); - frame->chunk[1] = NULL; - } - if(frame->chunk[2]) - { - free(frame->chunk[2]); - frame->chunk[2] = NULL; - } - + free(frame->chunk[0]); + free(frame->chunk[1]); + free(frame->chunk[2]); + memset(frame->chunk, 0, sizeof(frame->chunk[0])*3); + if(this->use_zero_copy) { frame->data = frame->video_mem + @@ -348,10 +337,9 @@ static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, } else { - if(frame->data) - free(frame->data); - frame->data = xine_xmalloc(frame->sc.output_width * - frame->sc.output_height * + free(frame->data); + frame->data = calloc(frame->sc.output_width * + frame->sc.output_height, this->bytes_per_pixel); } @@ -360,19 +348,19 @@ static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, frame->vo_frame.pitches[0] = 8*((width + 7) / 8); frame->vo_frame.pitches[1] = 8*((width + 15) / 16); frame->vo_frame.pitches[2] = 8*((width + 15) / 16); - + frame->vo_frame.base[0] = xine_xmalloc_aligned(16, frame->vo_frame.pitches[0] * height, (void **)&frame->chunk[0]); - + frame->vo_frame.base[1] = xine_xmalloc_aligned(16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **)&frame->chunk[1]); - + frame->vo_frame.base[2] = xine_xmalloc_aligned(16, frame->vo_frame.pitches[2] * @@ -382,7 +370,7 @@ static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, else { frame->vo_frame.pitches[0] = 8 * ((width + 3) / 4); - + frame->vo_frame.base[0] = xine_xmalloc_aligned(16, frame->vo_frame.pitches[0] * @@ -392,7 +380,7 @@ static void frame_reallocate(fb_driver_t *this, fb_frame_t *frame, frame->chunk[2] = NULL; } } - + static void fb_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, @@ -400,7 +388,7 @@ static void fb_update_frame_format(vo_driver_t *this_gen, { fb_driver_t *this = (fb_driver_t *)this_gen; fb_frame_t *frame = (fb_frame_t *)frame_gen; - + flags &= VO_BOTH_FIELDS; /* Find out if we need to adapt this frame. */ @@ -430,7 +418,7 @@ static void fb_update_frame_format(vo_driver_t *this_gen, else frame->bytes_per_line = frame->sc.output_width * this->bytes_per_pixel; - + setup_colorspace_converter(frame, flags); } @@ -442,7 +430,7 @@ static void fb_overlay_clut_yuv2rgb(fb_driver_t *this, { int i; clut_t* clut = (clut_t*)overlay->color; - + if(!overlay->rgb_clut) { for(i = 0; @@ -458,11 +446,11 @@ static void fb_overlay_clut_yuv2rgb(fb_driver_t *this, } overlay->rgb_clut++; } - + if(!overlay->hili_rgb_clut) { clut = (clut_t*) overlay->hili_color; - + for(i = 0; i < sizeof(overlay->color)/sizeof(overlay->color[0]); i++) @@ -504,7 +492,7 @@ static void fb_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, frame->sc.delivered_height, &this->alphablend_extra_data); break; - + case 24: _x_blend_rgb24(frame->data, overlay, @@ -514,7 +502,7 @@ static void fb_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, frame->sc.delivered_height, &this->alphablend_extra_data); break; - + case 32: _x_blend_rgb32(frame->data, overlay, @@ -524,7 +512,7 @@ static void fb_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, frame->sc.delivered_height, &this->alphablend_extra_data); break; - } + } } } @@ -546,11 +534,11 @@ static void fb_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) this->sc.output_width = frame->sc.output_width; this->sc.output_height = frame->sc.output_height; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_fb: gui size %d x %d, frame size %d x %d\n", this->sc.gui_width, this->sc.gui_height, frame->sc.output_width, frame->sc.output_height); - + memset(this->video_mem_base, 0, this->mem_size); } @@ -567,10 +555,10 @@ static void fb_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) (&this->old_frame->vo_frame); this->old_frame = this->cur_frame; this->cur_frame = frame; - + this->fb_var.yoffset = frame->yoffset; if(ioctl(this->fd, FBIOPAN_DISPLAY, &this->fb_var) == -1) - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_fb: ioctl FBIOPAN_DISPLAY failed: %s\n", strerror(errno)); } else @@ -579,14 +567,14 @@ static void fb_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) frame->sc.output_yoffset * this->fb_bytes_per_line + frame->sc.output_xoffset * this->bytes_per_pixel; src = frame->data; - + for(y = 0; y < frame->sc.output_height; y++) { xine_fast_memcpy(dst, src, frame->bytes_per_line); src += frame->bytes_per_line; dst += this->fb_bytes_per_line; - } - + } + frame->vo_frame.free(&frame->vo_frame); } } @@ -609,7 +597,7 @@ static int fb_get_property(vo_driver_t *this_gen, int property) case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; - + case VO_PROP_WINDOW_HEIGHT: return this->sc.gui_height; @@ -626,7 +614,7 @@ static int fb_get_property(vo_driver_t *this_gen, int property) return this->cur_frame->sc.output_yoffset; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_fb: tried to get unsupported property %d\n", property); } @@ -643,7 +631,7 @@ static int fb_set_property(vo_driver_t *this_gen, int property, int value) if(value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->sc.user_ratio = value; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_fb: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); break; @@ -672,7 +660,7 @@ static int fb_set_property(vo_driver_t *this_gen, int property, int value) break; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_fb: tried to set unsupported property %d\n", property); } @@ -710,8 +698,8 @@ static int fb_gui_data_exchange(vo_driver_t *this_gen, static void fb_dispose(vo_driver_t *this_gen) { fb_driver_t *this = (fb_driver_t *)this_gen; - - munmap(0, this->mem_size); + + munmap(0, this->mem_size); close(this->fd); _x_alphablend_free(&this->alphablend_extra_data); @@ -722,7 +710,7 @@ static void fb_dispose(vo_driver_t *this_gen) static int get_fb_var_screeninfo(int fd, struct fb_var_screeninfo *var, xine_t *xine) { int i; - + if(ioctl(fd, FBIOGET_VSCREENINFO, var)) { xprintf(xine, XINE_VERBOSITY_DEBUG, "video_out_fb: ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); @@ -743,7 +731,7 @@ static int get_fb_var_screeninfo(int fd, struct fb_var_screeninfo *var, xine_t * continue; break; } - + /* Get proper value for maximized var->yres_virtual. */ if(ioctl(fd, FBIOGET_VSCREENINFO, var) == -1) { @@ -843,26 +831,26 @@ static int open_fb_device(config_values_t *config, xine_t *xine) { device_name = "/dev/fb1"; fd = open(device_name, O_RDWR); - + if(fd < 0) - { + { device_name = "/dev/fb0"; fd = open(device_name, O_RDWR); } } - + if(fd < 0) { - xprintf(xine, XINE_VERBOSITY_DEBUG, + xprintf(xine, XINE_VERBOSITY_DEBUG, "video_out_fb: Unable to open device \"%s\", aborting: %s\n", device_name, strerror(errno)); return -1; } - + config->update_string(config, devkey, device_name); return fd; } - + static int mode_visual(fb_driver_t *this, config_values_t *config, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix) @@ -888,7 +876,7 @@ static int mode_visual(fb_driver_t *this, config_values_t *config, if(!var->blue.offset) return MODE_16_RGB; return MODE_16_BGR; - + case 15: if(!var->blue.offset) return MODE_15_RGB; @@ -896,16 +884,16 @@ static int mode_visual(fb_driver_t *this, config_values_t *config, case 8: if(!var->blue.offset) - return MODE_8_RGB; - return MODE_8_BGR; + return MODE_8_RGB; + return MODE_8_BGR; } } - + xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_fb: Your video mode was not recognized, sorry.\n")); return 0; } - + static int setup_yuv2rgb(fb_driver_t *this, config_values_t *config, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix) @@ -919,13 +907,13 @@ static int setup_yuv2rgb(fb_driver_t *this, config_values_t *config, this->yuv2rgb_contrast = this->yuv2rgb_saturation = 128; this->yuv2rgb_factory = yuv2rgb_factory_init(this->yuv2rgb_mode, - this->yuv2rgb_swap, + this->yuv2rgb_swap, this->yuv2rgb_cmap); this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, this->yuv2rgb_brightness, this->yuv2rgb_contrast, this->yuv2rgb_saturation); - + return 1; } @@ -946,7 +934,7 @@ static void setup_buffers(fb_driver_t *this, * bpp <= 32 * msb_right = 0 */ - + this->bytes_per_pixel = (this->fb_var.bits_per_pixel + 7)/8; this->bpp = this->bytes_per_pixel * 8; this->depth = this->fb_var.red.length + @@ -955,9 +943,9 @@ static void setup_buffers(fb_driver_t *this, this->total_num_native_buffers = var->yres_virtual / var->yres; this->used_num_buffers = 0; - + this->cur_frame = this->old_frame = 0; - + xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_fb: %d video RAM buffers are available.\n"), this->total_num_native_buffers); @@ -967,7 +955,7 @@ static void setup_buffers(fb_driver_t *this, xprintf(this->xine, XINE_VERBOSITY_LOG, _("WARNING: video_out_fb: Zero copy buffers are DISABLED because only %d buffers\n" " are available which is less than the recommended %d buffers. Lowering\n" - " the frame buffer resolution might help.\n"), + " the frame buffer resolution might help.\n"), this->total_num_native_buffers, RECOMMENDED_NUM_BUFFERS); } else @@ -995,21 +983,21 @@ static vo_driver_t *fb_open_plugin(video_driver_class_t *class_gen, fb_driver_t *this; fb_class_t *class; fb_visual_t *visual = NULL; - + if (visual_gen) { visual = (fb_visual_t *) visual_gen; } - + class = (fb_class_t *)class_gen; config = class->config; /* allocate plugin struct */ - this = (fb_driver_t *) xine_xmalloc(sizeof(fb_driver_t)); + this = calloc(1, sizeof(fb_driver_t)); if(!this) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + register_callbacks(this); this->fd = open_fb_device(config, class->xine); @@ -1021,7 +1009,7 @@ static vo_driver_t *fb_open_plugin(video_driver_class_t *class_gen, goto error; if (!set_fb_palette (this->fd, &this->fb_var)) goto error; - + this->xine = class->xine; if(this->fb_fix.line_length) @@ -1030,7 +1018,7 @@ static vo_driver_t *fb_open_plugin(video_driver_class_t *class_gen, this->fb_bytes_per_line = (this->fb_var.xres_virtual * this->fb_var.bits_per_pixel)/8; - + _x_vo_scale_init(&this->sc, 0, 0, config); this->sc.gui_width = this->fb_var.xres; this->sc.gui_height = this->fb_var.yres; @@ -1055,10 +1043,10 @@ static vo_driver_t *fb_open_plugin(video_driver_class_t *class_gen, this->fb_var.red.length, this->fb_var.red.offset, this->fb_var.green.length, this->fb_var.green.offset, this->fb_var.blue.length, this->fb_var.blue.offset); - + if(!setup_yuv2rgb(this, config, &this->fb_var, &this->fb_fix)) goto error; - + /* mmap whole video memory */ this->mem_size = this->fb_fix.smem_len; this->video_mem_base = mmap(0, this->mem_size, PROT_READ | PROT_WRITE, @@ -1087,7 +1075,7 @@ static void fb_dispose_class(video_driver_class_t *this_gen) static void *fb_init_class(xine_t *xine, void *visual_gen) { - fb_class_t *this = (fb_class_t *)xine_xmalloc(sizeof(fb_class_t)); + fb_class_t *this = calloc(1, sizeof(fb_class_t)); this->driver_class.open_plugin = fb_open_plugin; this->driver_class.get_identifier = fb_get_identifier; @@ -1112,7 +1100,7 @@ static const vo_info_t vo_info_fb = /* exported plugin catalog entry */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "fb", XINE_VERSION_CODE, &vo_info_fb, fb_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/video_out/video_out_macosx.m b/src/video_out/video_out_macosx.m index 4621d31b9..b5b4d731c 100644 --- a/src/video_out/video_out_macosx.m +++ b/src/video_out/video_out_macosx.m @@ -97,7 +97,7 @@ static vo_frame_t *macosx_alloc_frame(vo_driver_t *vo_driver) { /* macosx_driver_t *this = (macosx_driver_t *) vo_driver; */ macosx_frame_t *frame; - frame = (macosx_frame_t *) xine_xmalloc(sizeof(macosx_frame_t)); + frame = calloc(1, sizeof(macosx_frame_t)); if(!frame) return NULL; @@ -207,7 +207,7 @@ static void macosx_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) { break; case XINE_IMGFMT_YUY2: xine_fast_memcpy (texture_buffer, vo_frame->base[0], - vo_frame->pitches[0] * vo_frame->height * 2); + vo_frame->pitches[0] * vo_frame->height); [driver->view updateTexture]; break; default: @@ -320,7 +320,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void * macosx_driver_t *driver; XineOpenGLView *view = (XineOpenGLView *) visual; - driver = (macosx_driver_t *) xine_xmalloc(sizeof(macosx_driver_t)); + driver = calloc(1, sizeof(macosx_driver_t)); driver->config = class->config; driver->xine = class->xine; @@ -366,7 +366,7 @@ static void dispose_class (video_driver_class_t *driver_class) { static void *init_class (xine_t *xine, void *visual) { macosx_class_t *this; - this = (macosx_class_t *) xine_xmalloc(sizeof(macosx_class_t)); + this = calloc(1, sizeof(macosx_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_none.c b/src/video_out/video_out_none.c index 5f2424a60..15bc52abe 100644 --- a/src/video_out/video_out_none.c +++ b/src/video_out/video_out_none.c @@ -72,7 +72,7 @@ static void free_framedata(none_frame_t* frame) { static void none_frame_dispose(vo_frame_t *vo_frame) { none_frame_t *frame = (none_frame_t *)vo_frame; - free_framedata(frame); + free_framedata(frame); free (frame); } @@ -87,8 +87,8 @@ static uint32_t none_get_capabilities(vo_driver_t *vo_driver) { static vo_frame_t *none_alloc_frame(vo_driver_t *vo_driver) { /* none_driver_t *this = (none_driver_t *) vo_driver; */ none_frame_t *frame; - - frame = (none_frame_t *) xine_xmalloc(sizeof(none_frame_t)); + + frame = calloc(1, sizeof(none_frame_t)); if(!frame) return NULL; @@ -97,43 +97,43 @@ static vo_frame_t *none_alloc_frame(vo_driver_t *vo_driver) { frame->vo_frame.base[0] = NULL; frame->vo_frame.base[1] = NULL; frame->vo_frame.base[2] = NULL; - + frame->vo_frame.proc_slice = NULL; frame->vo_frame.proc_frame = NULL; frame->vo_frame.field = none_frame_field; frame->vo_frame.dispose = none_frame_dispose; frame->vo_frame.driver = vo_driver; - + return (vo_frame_t *)frame; } static void none_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_frame, - uint32_t width, uint32_t height, + uint32_t width, uint32_t height, double ratio, int format, int flags) { none_driver_t *this = (none_driver_t *) vo_driver; none_frame_t *frame = (none_frame_t *) vo_frame; if((frame->width != width) || (frame->height != height) || (frame->format != format)) { - + free_framedata(frame); - + frame->width = width; frame->height = height; frame->format = format; - + switch(format) { - case XINE_IMGFMT_YV12: + case XINE_IMGFMT_YV12: { int y_size, uv_size; - + frame->vo_frame.pitches[0] = 8*((width + 7) / 8); frame->vo_frame.pitches[1] = 8*((width + 15) / 16); frame->vo_frame.pitches[2] = 8*((width + 15) / 16); - + y_size = frame->vo_frame.pitches[0] * height; uv_size = frame->vo_frame.pitches[1] * ((height+1)/2); - + frame->vo_frame.base[0] = malloc (y_size + 2*uv_size); frame->vo_frame.base[1] = frame->vo_frame.base[0]+y_size+uv_size; frame->vo_frame.base[2] = frame->vo_frame.base[0]+y_size; @@ -152,14 +152,14 @@ static void none_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_fram break; } - - if((format == XINE_IMGFMT_YV12 - && (frame->vo_frame.base[0] == NULL - || frame->vo_frame.base[1] == NULL + + if((format == XINE_IMGFMT_YV12 + && (frame->vo_frame.base[0] == NULL + || frame->vo_frame.base[1] == NULL || frame->vo_frame.base[2] == NULL)) || (format == XINE_IMGFMT_YUY2 && frame->vo_frame.base[0] == NULL)) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "video_out_none: error. (framedata allocation failed: out of memory)\n"); + "video_out_none: error. (framedata allocation failed: out of memory)\n"); free_framedata(frame); } } @@ -170,19 +170,19 @@ static void none_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_fram static void none_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) { /* none_driver_t *driver = (none_driver_t *)vo_driver; */ none_frame_t *frame = (none_frame_t *)vo_frame; - + frame->vo_frame.free(&frame->vo_frame); } static int none_get_property(vo_driver_t *vo_driver, int property) { none_driver_t *driver = (none_driver_t *)vo_driver; - + switch(property) { case VO_PROP_ASPECT_RATIO: return driver->ratio; break; - + default: break; } @@ -192,7 +192,7 @@ static int none_get_property(vo_driver_t *vo_driver, int property) { static int none_set_property(vo_driver_t *vo_driver, int property, int value) { none_driver_t *driver = (none_driver_t *)vo_driver; - + switch(property) { case VO_PROP_ASPECT_RATIO: @@ -208,7 +208,7 @@ static int none_set_property(vo_driver_t *vo_driver, int property, int value) { return value; } -static void none_get_property_min_max(vo_driver_t *vo_driver, +static void none_get_property_min_max(vo_driver_t *vo_driver, int property, int *min, int *max) { *min = 0; *max = 0; @@ -242,13 +242,13 @@ static int none_redraw_needed(vo_driver_t *vo_driver) { static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void *visual) { none_class_t *class = (none_class_t *) driver_class; none_driver_t *driver; - - driver = (none_driver_t *) xine_xmalloc(sizeof(none_driver_t)); - + + driver = calloc(1, sizeof(none_driver_t)); + driver->config = class->config; driver->xine = class->xine; driver->ratio = XINE_VO_ASPECT_AUTO; - + driver->vo_driver.get_capabilities = none_get_capabilities; driver->vo_driver.alloc_frame = none_alloc_frame ; driver->vo_driver.update_frame_format = none_update_frame_format; @@ -262,9 +262,9 @@ static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void * driver->vo_driver.gui_data_exchange = none_gui_data_exchange; driver->vo_driver.dispose = none_dispose; driver->vo_driver.redraw_needed = none_redraw_needed; - + return &driver->vo_driver; -} +} /* * Class related functions. @@ -279,14 +279,14 @@ static char* get_description (video_driver_class_t *driver_class) { static void dispose_class (video_driver_class_t *driver_class) { none_class_t *this = (none_class_t *) driver_class; - + free (this); } static void *init_class (xine_t *xine, void *visual) { none_class_t *this; - - this = (none_class_t *) xine_xmalloc(sizeof(none_class_t)); + + this = calloc(1, sizeof(none_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; @@ -305,7 +305,7 @@ static const vo_info_t vo_info_none = { }; const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "none", XINE_VERSION_CODE, &vo_info_none, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/video_out/video_out_opengl.c b/src/video_out/video_out_opengl.c index 54696f452..1904fe6af 100644 --- a/src/video_out/video_out_opengl.c +++ b/src/video_out/video_out_opengl.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -142,7 +142,7 @@ typedef struct { uint8_t *chunk[4]; /* mem alloc by xmalloc_aligned */ uint8_t *rgb, *rgb_dst; - + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ } opengl_frame_t; @@ -198,7 +198,7 @@ typedef struct { PFNMYGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB; PFNMYGLGENTEXTURESEXTPROC glGenTexturesEXT; PFNMYGLBINDTEXTUREEXTPROC glBindTextureEXT; - + int yuv2rgb_brightness; int yuv2rgb_contrast; int yuv2rgb_saturation; @@ -233,7 +233,7 @@ typedef struct { int (*setup)(opengl_driver_t *); /* Flag: needs output converted to rgb (is able to do YUV otherwise) */ int needsrgb; - /* Default action: what to do if there's no new image + /* Default action: what to do if there's no new image * typically either RENDER_NONE or RENDER_DRAW (for animated render's) */ enum render_e defaction; /* Fallback: change to following render backend if this one doesn't work */ @@ -327,7 +327,7 @@ static void render_cyl (opengl_driver_t *this, opengl_frame_t *frame) { float off; float tx, ty; struct timeval curtime; - + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); /* Calc timing + texture coords */ @@ -341,10 +341,10 @@ static void render_cyl (opengl_driver_t *this, opengl_frame_t *frame) { glMatrixMode (GL_MODELVIEW); glLoadIdentity (); glTranslatef (0, 0, -10); - glRotatef (off * CYCLE_FACTOR1, 1, 0, 0); - glRotatef (off, 0, 0, 1); - glRotatef (off * CYCLE_FACTOR2, 0, 1, 0); - + glRotatef (off * CYCLE_FACTOR1, 1, 0, 0); + glRotatef (off, 0, 0, 1); + glRotatef (off * CYCLE_FACTOR2, 0, 1, 0); + /* Note that this is not aspect ratio corrected */ glBegin (GL_QUADS); for (i = 0; i < CYL_TESSELATION; i++) { @@ -363,7 +363,7 @@ static void render_cyl (opengl_driver_t *this, opengl_frame_t *frame) { } /* Animated spinning environment mapped torus */ -#define DIST_FACTOR 16.568542 /* 2 * (sqrt(2)-1) * 20 */ +#define DIST_FACTOR 16.568542 /* 2 * (sqrt(2)-1) * 20 */ static void render_env_tor (opengl_driver_t *this, opengl_frame_t *frame) { float off; float x1, y1, x2, y2, tx, ty; @@ -397,7 +397,7 @@ static void render_env_tor (opengl_driver_t *this, opengl_frame_t *frame) { glLoadIdentity (); glDepthFunc (GL_ALWAYS); glDepthMask (GL_FALSE); - + glBegin (GL_QUADS); glColor3f (1, 1, 1); glTexCoord2f (tx, 0); glVertex3f (x2, y2, -20); @@ -405,7 +405,7 @@ static void render_env_tor (opengl_driver_t *this, opengl_frame_t *frame) { glTexCoord2f (0, ty); glVertex3f (x1, y1, -20); glTexCoord2f (tx, ty); glVertex3f (x2, y1, -20); glEnd (); - + glPopMatrix (); glDepthFunc (GL_LEQUAL); glDepthMask (GL_TRUE); @@ -442,7 +442,7 @@ static int render_help_image_tex (opengl_driver_t *this, int new_w, int new_h, tex_w <<= 1; while (tex_h < new_h) tex_h <<= 1; - + if (tex_w != this->tex_width || tex_h != this->tex_height) { char *tmp = calloc (tex_w * tex_h, 4); /* 4 enough until RGBA */ if (this->glBindTextureEXT) @@ -458,7 +458,7 @@ static int render_help_image_tex (opengl_driver_t *this, int new_w, int new_h, this->tex_width = tex_w; this->tex_height = tex_h; lprintf ("* new texsize: %dx%d\n", tex_w, tex_h); - } + } this->last_width = new_w; this->last_height = new_h; return 1; @@ -481,7 +481,7 @@ static int render_help_image_tiledtex (opengl_driver_t *this, tex_w <<= 1; while (tex_h < new_h) tex_h <<= 1; - + if (tex_w != this->tex_width || tex_h != this->tex_height) { char *tmp = calloc (tex_w * tex_h, 4); /* 4 enough until RGBA */ if (this->glBindTextureEXT) @@ -521,7 +521,7 @@ static int render_help_image_tiledtex (opengl_driver_t *this, this->tex_width = tex_w; this->tex_height = tex_h; lprintf ("* new texsize: %dx%d on %d tiles\n", tex_w, tex_h, num); - } + } this->last_width = new_w; this->last_height = new_h; return 1; @@ -669,8 +669,8 @@ static int render_image_envtex (opengl_driver_t *this, opengl_frame_t *frame) { * Render setup functions */ static int render_help_verify_ext (opengl_driver_t *this, char *ext) { - int ret = 0; - int l = strlen (ext); + int ret = 0; + const size_t l = strlen (ext); const char *e; for (e = (char *) this->gl_exts; e && *e; e = strchr (e, ' ')) { while (isspace (*e)) @@ -694,10 +694,9 @@ static void *getdladdr (const GLubyte *_funcName) { return NULL; #elif defined(__APPLE__) - char *temp = xine_xmalloc (strlen (funcName) + 2); + char *temp; + asprintf(&temp, "_%s", funcName); void *res = NULL; - temp[0] = '_'; /* Mac OS X prepends an underscore on function names */ - strcpy (temp+1, funcName); if (NSIsSymbolNameDefined (temp)) { NSSymbol symbol = NSLookupAndBindSymbol (temp); res = NSAddressOfSymbol (symbol); @@ -711,7 +710,7 @@ static void *getdladdr (const GLubyte *_funcName) { handle = dlopen (NULL, RTLD_LAZY); } return dlsym (handle, funcName); - + #else /* all other Un*xes */ return dlsym (0, funcName); @@ -884,7 +883,7 @@ static int render_setup_cyl (opengl_driver_t *this) { static int render_setup_torus (opengl_driver_t *this) { int i, j, k; int ret; - + ret = render_setup_3d (this); ret &= render_help_setup_tex (this); @@ -938,7 +937,7 @@ static int render_setup_fp_yuv (opengl_driver_t *this) { "MAD res, { 0, -.391, 2.018 }, tmp.xxxw, res;" "MAD result.color, { 1.596, -.813, 0 }, tmp.yyyw, res;" "END"; - + ret = render_setup_tex2d (this); if (! this->has_fragprog) return 0; @@ -964,7 +963,7 @@ static int render_setup_fp_yuv (opengl_driver_t *this) { */ /* name, display, image, setup, needsrgb, defaction, fallback */ static const opengl_render_t opengl_rb[] = { - { "2D_Tex_Fragprog", render_tex2d, render_image_fp_yuv, + { "2D_Tex_Fragprog", render_tex2d, render_image_fp_yuv, render_setup_fp_yuv, 0, RENDER_NONE, 1 }, { "2D_Tex", render_tex2d, render_image_tex, render_setup_tex2d, 1, RENDER_NONE, 2 }, @@ -1005,10 +1004,10 @@ static void *render_run (opengl_driver_t *this) { struct timeval curtime; struct timespec timeout; const opengl_render_t *render; - + lprintf ("* render thread created\n"); while (1) { - + /* Wait for render action */ pthread_mutex_lock (&this->render_action_mutex); if (! this->render_action) { @@ -1212,28 +1211,28 @@ static uint32_t opengl_get_capabilities (vo_driver_t *this_gen) { static void opengl_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { opengl_frame_t *frame = (opengl_frame_t *) vo_img ; /* opengl_driver_t *this = (opengl_driver_t *) vo_img->driver; */ - + vo_img->proc_called = 1; if (! frame->rgb_dst) return; /* lprintf ("%p: frame_copy src %p=%p to %p\n", frame, src[0], frame->chunk[0], frame->rgb_dst); */ - if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) { /* TODO: opengl *could* support this?!? */ /* cropping will be performed by video_out.c */ return; } - + if (frame->format == XINE_IMGFMT_YV12) frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0], src[1], src[2]); else frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0]); - + /* lprintf ("frame_copy...done\n"); */ } @@ -1244,7 +1243,7 @@ static void opengl_frame_field (vo_frame_t *vo_img, int which_field) { /* lprintf ("%p: frame_field rgb %p which_field %x\n", frame, frame->rgb, which_field); */ if (! opengl_rb[this->render_fun_id].needsrgb) { - frame->rgb_dst = NULL; + frame->rgb_dst = NULL; return; } @@ -1281,7 +1280,7 @@ static vo_frame_t *opengl_alloc_frame (vo_driver_t *this_gen) { opengl_frame_t *frame; opengl_driver_t *this = (opengl_driver_t *) this_gen; - frame = (opengl_frame_t *) xine_xmalloc (sizeof (opengl_frame_t)); + frame = (opengl_frame_t *) calloc(1, sizeof(opengl_frame_t)); if (!frame) return NULL; @@ -1292,7 +1291,7 @@ static vo_frame_t *opengl_alloc_frame (vo_driver_t *this_gen) { */ frame->vo_frame.proc_slice = opengl_frame_proc_slice; frame->vo_frame.proc_frame = NULL; - frame->vo_frame.field = opengl_frame_field; + frame->vo_frame.field = opengl_frame_field; frame->vo_frame.dispose = opengl_frame_dispose; frame->vo_frame.driver = this_gen; @@ -1346,7 +1345,7 @@ static void opengl_update_frame_format (vo_driver_t *this_gen, /* lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ flags &= VO_BOTH_FIELDS; - + XLockDisplay (this->display); /* (re-) allocate render space */ @@ -1400,7 +1399,7 @@ static void opengl_update_frame_format (vo_driver_t *this_gen, frame->height = height; frame->format = format; - XUnlockDisplay (this->display); + XUnlockDisplay (this->display); opengl_frame_field ((vo_frame_t *)frame, flags); } @@ -1434,7 +1433,7 @@ static void opengl_overlay_clut_yuv2rgb(opengl_driver_t *this, vo_overlay_t *ov } } -static void opengl_overlay_begin (vo_driver_t *this_gen, +static void opengl_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { opengl_driver_t *this = (opengl_driver_t *) this_gen; @@ -1442,10 +1441,10 @@ static void opengl_overlay_begin (vo_driver_t *this_gen, if (this->ovl_changed && this->xoverlay) { XLockDisplay (this->display); - x11osd_clear(this->xoverlay); + x11osd_clear(this->xoverlay); XUnlockDisplay (this->display); } - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -1462,7 +1461,7 @@ static void opengl_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { this->ovl_changed = 0; } -static void opengl_overlay_blend (vo_driver_t *this_gen, +static void opengl_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { opengl_driver_t *this = (opengl_driver_t *) this_gen; opengl_frame_t *frame = (opengl_frame_t *) frame_gen; @@ -1472,7 +1471,7 @@ static void opengl_overlay_blend (vo_driver_t *this_gen, if (overlay->unscaled) { if (this->ovl_changed && this->xoverlay) { XLockDisplay (this->display); - x11osd_blend (this->xoverlay, overlay); + x11osd_blend (this->xoverlay, overlay); XUnlockDisplay (this->display); } } else { @@ -1513,7 +1512,7 @@ static int opengl_redraw_needed (vo_driver_t *this_gen) { opengl_compute_ideal_size(this); - if( _x_vo_scale_redraw_needed( &this->sc ) ) { + if( _x_vo_scale_redraw_needed( &this->sc ) ) { opengl_compute_rgb_size(this); pthread_mutex_lock (&this->render_action_mutex); if (this->render_action <= RENDER_CLEAN) { @@ -1523,10 +1522,10 @@ static int opengl_redraw_needed (vo_driver_t *this_gen) { pthread_mutex_unlock (&this->render_action_mutex); ret = 1; } - } + } else ret = 1; - + /* lprintf ("done...redraw_needed: %d\n", ret); */ return ret; } @@ -1546,7 +1545,7 @@ static void opengl_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->frame[0] = frame; this->render_frame_changed = 1; /* lprintf ("video_out_opengl: cur_frame updated to %d\n", frame->vo_frame.id); */ - + /* * let's see if this frame is different in size / aspect * ratio from the previous one @@ -1557,7 +1556,7 @@ static void opengl_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) /* lprintf("frame format changed\n"); */ this->sc.force_redraw = 1; /* trigger re-calc of output size */ } - + /* * tell gui that we are about to display a frame, * ask for offset and output size @@ -1593,14 +1592,14 @@ static int opengl_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_WINDOW_HEIGHT: return this->sc.gui_height; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_opengl: tried to get unsupported property %d\n", property); } return 0; } -static int opengl_set_property (vo_driver_t *this_gen, +static int opengl_set_property (vo_driver_t *this_gen, int property, int value) { opengl_driver_t *this = (opengl_driver_t *) this_gen; @@ -1612,7 +1611,7 @@ static int opengl_set_property (vo_driver_t *this_gen, opengl_compute_ideal_size (this); this->sc.force_redraw = 1; /* trigger re-calc of output size */ - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_opengl: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); break; case VO_PROP_BRIGHTNESS: @@ -1640,7 +1639,7 @@ static int opengl_set_property (vo_driver_t *this_gen, this->sc.force_redraw = 1; break; default: - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_opengl: tried to set unsupported property %d\n", property); } @@ -1663,7 +1662,7 @@ static void opengl_get_property_min_max (vo_driver_t *this_gen, } } -static int opengl_gui_data_exchange (vo_driver_t *this_gen, +static int opengl_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { opengl_driver_t *this = (opengl_driver_t *) this_gen; @@ -1678,7 +1677,7 @@ static int opengl_gui_data_exchange (vo_driver_t *this_gen, /* lprintf ("expose event\n"); */ if (this->frame[0]) { XExposeEvent * xev = (XExposeEvent *) data; - + if (xev && xev->count == 0) { pthread_mutex_lock (&this->render_action_mutex); if (this->render_action <= RENDER_CLEAN) { @@ -1715,9 +1714,9 @@ static int opengl_gui_data_exchange (vo_driver_t *this_gen, &this->render_action_mutex); pthread_mutex_unlock (&this->render_action_mutex); break; - + case XINE_GUI_SEND_DRAWABLE_CHANGED: - + pthread_mutex_lock (&this->render_action_mutex); this->render_action = RENDER_RELEASE; pthread_cond_signal (&this->render_action_cond); @@ -1745,7 +1744,7 @@ static int opengl_gui_data_exchange (vo_driver_t *this_gen, if (this->frame[0]) { x11_rectangle_t *rect = data; int x1, y1, x2, y2; - + _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, &x1, &y1); @@ -1774,7 +1773,7 @@ static void opengl_dispose (vo_driver_t *this_gen) { this->render_action = RENDER_EXIT; pthread_cond_signal (&this->render_action_cond); pthread_mutex_unlock (&this->render_action_mutex); - pthread_join (this->render_thread, NULL); + pthread_join (this->render_thread, NULL); pthread_mutex_destroy (&this->render_action_mutex); pthread_cond_destroy (&this->render_action_cond); pthread_cond_destroy (&this->render_return_cond); @@ -1792,7 +1791,7 @@ static void opengl_dispose (vo_driver_t *this_gen) { } _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -1819,8 +1818,8 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v opengl_driver_t *this; char **render_fun_names; int i; - - this = (opengl_driver_t *) xine_xmalloc (sizeof (opengl_driver_t)); + + this = (opengl_driver_t *) calloc(1, sizeof(opengl_driver_t)); if (!this) return NULL; @@ -1833,9 +1832,9 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v this->sc.dest_size_cb = visual->dest_size_cb; this->sc.user_data = visual->user_data; this->sc.user_ratio = XINE_VO_ASPECT_AUTO; - + _x_alphablend_init (&this->alphablend_extra_data, class->xine); - + this->drawable = visual->d; this->gui_width = this->gui_height = -1; this->last_width = this->last_height = -1; @@ -1845,7 +1844,7 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v this->ovl_changed = 0; this->xine = class->xine; this->config = config; - + this->vo_driver.get_capabilities = opengl_get_capabilities; this->vo_driver.alloc_frame = opengl_alloc_frame; this->vo_driver.update_frame_format = opengl_update_frame_format; @@ -1863,8 +1862,8 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v this->yuv2rgb_brightness = 0; this->yuv2rgb_contrast = 128; this->yuv2rgb_saturation = 128; - - this->yuv2rgb_factory = yuv2rgb_factory_init (YUV_FORMAT, YUV_SWAP_MODE, + + this->yuv2rgb_factory = yuv2rgb_factory_init (YUV_FORMAT, YUV_SWAP_MODE, NULL); this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, this->yuv2rgb_brightness, @@ -1876,8 +1875,7 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v this->drawable, X11OSD_SHAPED); XUnlockDisplay (this->display); - render_fun_names = xine_xmalloc ((sizeof(opengl_rb)/sizeof(opengl_render_t)+1) - * sizeof (const char *)); + render_fun_names = calloc((sizeof(opengl_rb)/sizeof(opengl_render_t)+1), sizeof(const char*)); for (i = 0; i < sizeof (opengl_rb) / sizeof (opengl_render_t); i++) render_fun_names[i] = opengl_rb[i].name; render_fun_names[i] = NULL; @@ -1917,7 +1915,7 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v "it also reduces flickering a lot.\n" "It should not have any performance impact."), 20, NULL, NULL); - + pthread_mutex_init (&this->render_action_mutex, NULL); pthread_cond_init (&this->render_action_cond, NULL); pthread_cond_init (&this->render_return_cond, NULL); @@ -1947,7 +1945,7 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v xprintf (this->xine, XINE_VERBOSITY_LOG, "video_out_opengl: default visual not OpenGL capable\n" " plugin will only work with clients supporting XINE_GUI_SEND_SELECT_VISUAL.\n"); - + return &this->vo_driver; } @@ -1955,6 +1953,52 @@ static vo_driver_t *opengl_open_plugin (video_driver_class_t *class_gen, const v * class functions */ +static int opengl_verify_direct (x11_visual_t *vis) { + int attribs[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + None + }; + Window root, win; + XVisualInfo *visinfo; + GLXContext ctx; + XSetWindowAttributes xattr; + int ret = 0; + + if (!vis || !vis->display || + ! (root = RootWindow (vis->display, vis->screen))) { + fprintf (stderr, "[videoout_opengl]: Don't have a root window to verify\n"); + return 0; + } + if (! (visinfo = glXChooseVisual (vis->display, vis->screen, attribs))) + return 0; + if (! (ctx = glXCreateContext (vis->display, visinfo, NULL, 1))) + return 0; + memset (&xattr, 0, sizeof (xattr)); + xattr.colormap = XCreateColormap(vis->display, root, visinfo->visual, AllocNone); + xattr.event_mask = StructureNotifyMask | ExposureMask; + if ( (win = XCreateWindow (vis->display, root, 0, 0, 1, 1, 0, visinfo->depth, + InputOutput, visinfo->visual, + CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, + &xattr))) { + if (glXMakeCurrent (vis->display, win, ctx)) { + const char *renderer = (const char *) glGetString(GL_RENDERER); + if (glXIsDirect (vis->display, ctx) && + ! strstr (renderer, "Software") && + ! strstr (renderer, "Indirect")) + ret = 1; + glXMakeCurrent (vis->display, None, NULL); + } + XDestroyWindow (vis->display, win); + } + glXDestroyContext (vis->display, ctx); + XFreeColormap (vis->display, xattr.colormap); + + return ret; +} + static char* opengl_get_identifier (video_driver_class_t *this_gen) { return "opengl"; } @@ -1970,7 +2014,18 @@ static void opengl_dispose_class (video_driver_class_t *this_gen) { } static void *opengl_init_class (xine_t *xine, void *visual_gen) { - opengl_class_t *this = (opengl_class_t *) xine_xmalloc (sizeof (opengl_class_t)); + + opengl_class_t *this; + + xprintf (xine, XINE_VERBOSITY_LOG, + "video_out_opengl: Testing for hardware accelerated direct rendering visual\n"); + if (! opengl_verify_direct ((x11_visual_t *)visual_gen)) { + xprintf (xine, XINE_VERBOSITY_LOG, + "video_out_opengl: Didn't find any\n"); + return NULL; + } + + this = (opengl_class_t *) calloc (1, sizeof(opengl_class_t)); this->driver_class.open_plugin = opengl_open_plugin; this->driver_class.get_identifier = opengl_get_identifier; @@ -1993,7 +2048,7 @@ static const vo_info_t vo_info_opengl = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "opengl", XINE_VERSION_CODE, &vo_info_opengl, opengl_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/video_out/video_out_pgx32.c b/src/video_out/video_out_pgx32.c index d903efc89..fa1b0ef99 100644 --- a/src/video_out/video_out_pgx32.c +++ b/src/video_out/video_out_pgx32.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -149,7 +149,7 @@ typedef struct { double ratio; } pgx32_frame_t; -typedef struct { +typedef struct { vo_driver_t vo_driver; vo_scale_t vo_scale; @@ -210,7 +210,7 @@ static int setup_dga(pgx32_driver_t *this) } if (strcmp("TSIgfxp", ident.name) != 0) { - xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_pgx32: Error: '%s' is not a pgx32 framebuffer device\n"), devname); + xprintf(this->class->xine, XINE_VERBOSITY_LOG, _("video_out_pgx32: Error: '%s' is not a pgx32 framebuffer device\n"), devname); XDgaUnGrabDrawable(this->dgadraw); XUnlockDisplay(this->display); return 0; @@ -386,7 +386,7 @@ static vo_frame_t *pgx32_alloc_frame(vo_driver_t *this_gen) /*pgx32_driver_t *this = (pgx32_driver_t *)(void *)this_gen;*/ pgx32_frame_t *frame; - frame = (pgx32_frame_t *) xine_xmalloc(sizeof(pgx32_frame_t)); + frame = calloc(1, sizeof(pgx32_frame_t)); if (!frame) { return NULL; } @@ -485,7 +485,7 @@ static void pgx32_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) _x_vo_scale_compute_ideal_size(&this->vo_scale); } - if (_x_vo_scale_redraw_needed(&this->vo_scale)) { + if (_x_vo_scale_redraw_needed(&this->vo_scale)) { int i; _x_vo_scale_compute_output_size(&this->vo_scale); @@ -589,7 +589,7 @@ static void pgx32_overlay_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen, vo { /*pgx32_driver_t *this = (pgx32_driver_t *)(void *)this_gen;*/ pgx32_frame_t *frame = (pgx32_frame_t *)frame_gen; - + if (overlay->rle) { int i, j, x, y, len, width; int use_clip_palette; @@ -757,7 +757,7 @@ static int pgx32_redraw_needed(vo_driver_t *this_gen) { pgx32_driver_t *this = (pgx32_driver_t *)(void *)this_gen; - if (_x_vo_scale_redraw_needed(&this->vo_scale)) { + if (_x_vo_scale_redraw_needed(&this->vo_scale)) { this->vo_scale.force_redraw = 1; return 1; } @@ -775,7 +775,7 @@ static void pgx32_dispose(vo_driver_t *this_gen) munmap((void *)this->vregs, GFXP_REGS_MMAPLEN); _x_alphablend_free(&this->alphablend_extra_data); - + free(this); } @@ -800,13 +800,13 @@ static vo_driver_t *pgx32_init_driver(video_driver_class_t *class_gen, const voi pgx32_driver_class_t *class = (pgx32_driver_class_t *)(void *)class_gen; pgx32_driver_t *this; - this = (pgx32_driver_t *)xine_xmalloc(sizeof(pgx32_driver_t)); + this = calloc(1, sizeof(pgx32_driver_t)); if (!this) { return NULL; } _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->vo_driver.get_capabilities = pgx32_get_capabilities; this->vo_driver.alloc_frame = pgx32_alloc_frame; this->vo_driver.update_frame_format = pgx32_update_frame_format; @@ -869,7 +869,7 @@ static void *pgx32_init_class(xine_t *xine, void *visual_gen) { pgx32_driver_class_t *class; - class = (pgx32_driver_class_t *)xine_xmalloc(sizeof(pgx32_driver_class_t)); + class = calloc(1, sizeof(pgx32_driver_class_t)); if (!class) { return NULL; } diff --git a/src/video_out/video_out_pgx64.c b/src/video_out/video_out_pgx64.c index 4abb794d7..c9ec38aa8 100644 --- a/src/video_out/video_out_pgx64.c +++ b/src/video_out/video_out_pgx64.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -213,7 +213,7 @@ typedef struct { uint8_t *buffer_ptrs[3]; } pgx64_frame_t; -typedef struct { +typedef struct { vo_driver_t vo_driver; vo_scale_t vo_scale; @@ -561,7 +561,7 @@ static vo_frame_t *pgx64_alloc_frame(vo_driver_t *this_gen) /*pgx64_driver_t *this = (pgx64_driver_t *)(void *)this_gen;*/ pgx64_frame_t *frame; - frame = (pgx64_frame_t *) xine_xmalloc(sizeof(pgx64_frame_t)); + frame = calloc(1, sizeof(pgx64_frame_t)); if (!frame) { return NULL; } @@ -671,7 +671,7 @@ static void pgx64_display_frame(vo_driver_t *this_gen, vo_frame_t *frame_gen) DGA_DRAW_UNLOCK(this->dgadraw); XUnlockDisplay(this->display); - if (_x_vo_scale_redraw_needed(&this->vo_scale)) { + if (_x_vo_scale_redraw_needed(&this->vo_scale)) { short int *cliprects, wx0, wy0, wx1, wy1, cx0, cy0, cx1, cy1; int dgavis; @@ -991,7 +991,7 @@ static void pgx64_overlay_key_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen if (x + width - 1 > overlay->hili_right) { width -= overlay->hili_right - x; len += overlay->hili_right - x; - } + } } } @@ -999,7 +999,7 @@ static void pgx64_overlay_key_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen int j; clut_t *src_clut; uint8_t *src_trans; - + if (use_clip_palette) { src_clut = (clut_t *)&overlay->hili_color; src_trans = (uint8_t *)&overlay->hili_trans; @@ -1035,7 +1035,7 @@ static void pgx64_overlay_key_blend(vo_driver_t *this_gen, vo_frame_t *frame_gen else { palette[use_clip_palette][j] = BlackPixel(this->display, this->screen); } - } + } } else { palette[use_clip_palette][j] = this->colour_key; @@ -1273,7 +1273,7 @@ static int pgx64_redraw_needed(vo_driver_t *this_gen) DGA_DRAW_UNLOCK(this->dgadraw); XUnlockDisplay(this->display); - if (modif || _x_vo_scale_redraw_needed(&this->vo_scale)) { + if (modif || _x_vo_scale_redraw_needed(&this->vo_scale)) { this->vo_scale.force_redraw = 1; this->chromakey_regen_needed = 1; return 1; @@ -1320,7 +1320,7 @@ static void pgx64_config_changed(void *user_data, xine_cfg_entry_t *entry) if (strcmp(entry->key, "video.device.pgx64_colour_key") == 0) { pgx64_set_property(this_gen, VO_PROP_COLORKEY, entry->num_value); update_colour_key_rgb(this); - } + } else if (strcmp(entry->key, "video.device.pgx64_chromakey_en") == 0) { this->chromakey_en = entry->num_value; } @@ -1352,7 +1352,7 @@ static vo_driver_t *pgx64_init_driver(video_driver_class_t *class_gen, const voi struct fbgattr attr; long page_size; - this = (pgx64_driver_t *)xine_xmalloc(sizeof(pgx64_driver_t)); + this = calloc(1, sizeof(pgx64_driver_t)); if (!this) { return NULL; } @@ -1493,7 +1493,7 @@ static void *pgx64_init_class(xine_t *xine, void *visual_gen) { pgx64_driver_class_t *class; - class = (pgx64_driver_class_t *)xine_xmalloc(sizeof(pgx64_driver_class_t)); + class = calloc(1, sizeof(pgx64_driver_class_t)); if (!class) { return NULL; } diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c new file mode 100644 index 000000000..860efdfb7 --- /dev/null +++ b/src/video_out/video_out_raw.c @@ -0,0 +1,610 @@ +/* + * Copyright (C) 2007-2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * + * video_out_raw.c, a video output plugin to pass raw data to frontend + * + * Written by Christophe Thommeret <hftom@free.fr>, + * based on others' video output plugins. + * + */ + +/* #define LOG */ +#define LOG_MODULE "video_out_raw" + +/* Allow frontend some time to render frames +* However, frontends are strongly advised to render synchronously */ +#define NUM_FRAMES_BACKLOG 4 +#define BYTES_PER_PIXEL 3 + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <math.h> +#include <errno.h> +#include <ctype.h> +#include <pthread.h> + +#include "xine.h" +#include "video_out.h" + +#include "xine_internal.h" +#include "yuv2rgb.h" +#include "xineutils.h" + + + +typedef struct { + vo_frame_t vo_frame; + + int width, height, format, flags; + double ratio; + uint8_t *chunk[4]; /* mem alloc by xmalloc_aligned */ + uint8_t *rgb, *rgb_dst; + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ + +} raw_frame_t; + +typedef struct { + vo_driver_t vo_driver; + + void *user_data; + + void (*raw_output_cb) (void *user_data, int format, + int frame_width, int frame_height, double frame_aspect, + void *data0, void *data1, void *data2); + + void (*raw_overlay_cb) (void *user_data, int num_ovl, + raw_overlay_t *overlays_p); + + int ovl_changed; + raw_overlay_t overlays[XINE_VORAW_MAX_OVL]; + yuv2rgb_t *ovl_yuv2rgb; + + int doYV12; + int doYUY2; + yuv2rgb_factory_t *yuv2rgb_factory; + /* Frame state */ + raw_frame_t *frame[NUM_FRAMES_BACKLOG]; + xine_t *xine; +} raw_driver_t; + + +typedef struct { + video_driver_class_t driver_class; + xine_t *xine; +} raw_class_t; + + + +static void raw_overlay_clut_yuv2rgb(raw_driver_t *this, vo_overlay_t *overlay, raw_frame_t *frame) +{ + int i; + clut_t* clut = (clut_t*) overlay->color; + + if (!overlay->rgb_clut) { + for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++ ) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->rgb_clut++; + } + if (!overlay->hili_rgb_clut) { + clut = (clut_t*) overlay->hili_color; + for ( i=0; i<sizeof(overlay->color)/sizeof(overlay->color[0]); i++) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->hili_rgb_clut++; + } +} + + +static int raw_process_ovl( raw_driver_t *this_gen, vo_overlay_t *overlay ) +{ + raw_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; + + if ( overlay->width<=0 || overlay->height<=0 ) + return 0; + + if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) ) + ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 ); + ovl->ovl_w = overlay->width; + ovl->ovl_h = overlay->height; + ovl->ovl_x = overlay->x; + ovl->ovl_y = overlay->y; + + int num_rle = overlay->num_rle; + rle_elem_t *rle = overlay->rle; + uint8_t *rgba = ovl->ovl_rgba; + clut_t *low_colors = (clut_t*)overlay->color; + clut_t *hili_colors = (clut_t*)overlay->hili_color; + uint8_t *low_trans = overlay->trans; + uint8_t *hili_trans = overlay->hili_trans; + clut_t *colors; + uint8_t *trans; + uint8_t alpha; + int rlelen = 0; + uint8_t clr = 0; + int i, pos=0, x, y; + + while ( num_rle>0 ) { + x = pos%ovl->ovl_w; + y = pos/ovl->ovl_w; + if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) { + colors = hili_colors; + trans = hili_trans; + } + else { + colors = low_colors; + trans = low_trans; + } + rlelen = rle->len; + clr = rle->color; + alpha = trans[clr]; + for ( i=0; i<rlelen; ++i ) { + rgba[0] = colors[clr].y; + rgba[1] = colors[clr].cr; + rgba[2] = colors[clr].cb; + rgba[3] = alpha*255/15; + rgba+= 4; + ++pos; + } + ++rle; + --num_rle; + } + return 1; +} + + +static void raw_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + + if ( !changed ) + return; + + ++this->ovl_changed; +} + + +static void raw_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + + if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL ) + return; + + if (overlay->rle) { + if (!overlay->rgb_clut || !overlay->hili_rgb_clut) + raw_overlay_clut_yuv2rgb (this, overlay, frame); + if ( raw_process_ovl( this, overlay ) ) + ++this->ovl_changed; + } +} + + +static void raw_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + + if ( !this->ovl_changed ) + return; + + this->raw_overlay_cb( this->user_data, this->ovl_changed-1, this->overlays ); + + this->ovl_changed = 0; +} + + +static void raw_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + + vo_img->proc_called = 1; + if (! frame->rgb_dst) + return; + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) + { + /* TODO: ?!? */ + return; + } + + if (frame->format == XINE_IMGFMT_YV12) + frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0], src[1], src[2]); + else + frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0]); +} + + + +static void raw_frame_field (vo_frame_t *vo_img, int which_field) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + raw_driver_t *this = (raw_driver_t *) vo_img->driver; + + if ( frame->format==XINE_IMGFMT_YV12 && this->doYV12 ) { + frame->rgb_dst = 0; + return; + } + else if ( frame->format==XINE_IMGFMT_YUY2 && this->doYUY2 ) { + frame->rgb_dst = 0; + return; + } + + switch (which_field) { + case VO_TOP_FIELD: + frame->rgb_dst = (uint8_t *)frame->rgb; + break; + case VO_BOTTOM_FIELD: + frame->rgb_dst = (uint8_t *)frame->rgb + frame->width * BYTES_PER_PIXEL; + break; + case VO_BOTH_FIELDS: + frame->rgb_dst = (uint8_t *)frame->rgb; + break; + } + + frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL); +} + + + +static void raw_frame_dispose (vo_frame_t *vo_img) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + + frame->yuv2rgb->dispose (frame->yuv2rgb); + + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame->chunk[3]); + free (frame); +} + + + +static vo_frame_t *raw_alloc_frame (vo_driver_t *this_gen) +{ + raw_frame_t *frame; + raw_driver_t *this = (raw_driver_t *) this_gen; + + frame = (raw_frame_t *) calloc(1, sizeof(raw_frame_t)); + + if (!frame) + return NULL; + + pthread_mutex_init (&frame->vo_frame.mutex, NULL); + + /* + * supply required functions/fields + */ + frame->vo_frame.proc_slice = raw_frame_proc_slice; + frame->vo_frame.proc_frame = NULL; + frame->vo_frame.field = raw_frame_field; + frame->vo_frame.dispose = raw_frame_dispose; + frame->vo_frame.driver = this_gen; + + /* + * colorspace converter for this frame + */ + frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); + + return (vo_frame_t *) frame; +} + + + +static void raw_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, + uint32_t width, uint32_t height, double ratio, int format, int flags) +{ + raw_frame_t *frame = (raw_frame_t *) frame_gen; + + /* Check frame size and format and reallocate if necessary */ + if ((frame->width != width) + || (frame->height != height) + || (frame->format != format) + || (frame->flags != flags)) { +/* lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ + + flags &= VO_BOTH_FIELDS; + + /* (re-) allocate render space */ + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame->chunk[3]); + + if (format == XINE_IMGFMT_YV12) { + frame->vo_frame.pitches[0] = 8*((width + 7) / 8); + frame->vo_frame.pitches[1] = 8*((width + 15) / 16); + frame->vo_frame.pitches[2] = 8*((width + 15) / 16); + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); + frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]); + frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]); + } else { + frame->vo_frame.pitches[0] = 8*((width + 3) / 4); + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); + frame->chunk[1] = NULL; + frame->chunk[2] = NULL; + } + frame->rgb = xine_xmalloc_aligned (16, BYTES_PER_PIXEL*width*height, + (void **) &frame->chunk[3]); + + /* set up colorspace converter */ + switch (flags) { + case VO_TOP_FIELD: + case VO_BOTTOM_FIELD: + frame->yuv2rgb->configure (frame->yuv2rgb, + width, + height, + 2*frame->vo_frame.pitches[0], + 2*frame->vo_frame.pitches[1], + width, + height, + BYTES_PER_PIXEL*width * 2); + break; + case VO_BOTH_FIELDS: + frame->yuv2rgb->configure (frame->yuv2rgb, + width, + height, + frame->vo_frame.pitches[0], + frame->vo_frame.pitches[1], + width, + height, + BYTES_PER_PIXEL*width); + break; + } + + frame->width = width; + frame->height = height; + frame->format = format; + + raw_frame_field ((vo_frame_t *)frame, flags); + } + + frame->ratio = ratio; +} + + + +static int raw_redraw_needed (vo_driver_t *this_gen) +{ + return 0; +} + + + +static void raw_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + int i; + + if (this->frame[NUM_FRAMES_BACKLOG-1]) { + this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame.free (&this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame); + } + for (i = NUM_FRAMES_BACKLOG-1; i > 0; i--) + this->frame[i] = this->frame[i-1]; + this->frame[0] = frame; + + if ( frame->rgb_dst ) { + this->raw_output_cb( this->user_data, XINE_VORAW_RGB, frame->width, frame->height, frame->ratio, frame->rgb, 0, 0 ); + } + else if ( frame->format==XINE_IMGFMT_YV12 ) { + this->raw_output_cb( this->user_data, XINE_VORAW_YV12, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], + frame->vo_frame.base[1], frame->vo_frame.base[2] ); + } + else { + this->raw_output_cb( this->user_data, XINE_VORAW_YUY2, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], 0, 0 ); + } +} + + + +static int raw_get_property (vo_driver_t *this_gen, int property) +{ + switch (property) { + case VO_PROP_ASPECT_RATIO: + return XINE_VO_ASPECT_AUTO; + case VO_PROP_MAX_NUM_FRAMES: + return 15; + case VO_PROP_BRIGHTNESS: + return 0; + case VO_PROP_CONTRAST: + return 128; + case VO_PROP_SATURATION: + return 128; + case VO_PROP_WINDOW_WIDTH: + return 0; + case VO_PROP_WINDOW_HEIGHT: + return 0; + default: + return 0; + } +} + + + +static int raw_set_property (vo_driver_t *this_gen, int property, int value) +{ + return value; +} + + + +static void raw_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) +{ + *min = 0; + *max = 0; +} + + + +static int raw_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) +{ + return 0; +} + + + +static uint32_t raw_get_capabilities (vo_driver_t *this_gen) +{ + uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; + return capabilities; +} + + + +static void raw_dispose (vo_driver_t *this_gen) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + int i; + + for (i = 0; i < NUM_FRAMES_BACKLOG; i++) + if (this->frame[i]) + this->frame[i]->vo_frame.dispose (&this->frame[i]->vo_frame); + + this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + + for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) + free( this->overlays[i].ovl_rgba ); + + free (this); +} + + + +static vo_driver_t *raw_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) +{ + raw_class_t *class = (raw_class_t *) class_gen; + raw_visual_t *visual = (raw_visual_t *) visual_gen; + raw_driver_t *this; + int i; + + this = (raw_driver_t *) calloc(1, sizeof(raw_driver_t)); + + if (!this) + return NULL; + + this->raw_output_cb = visual->raw_output_cb; + this->user_data = visual->user_data; + this->xine = class->xine; + this->raw_overlay_cb = visual->raw_overlay_cb; + this->doYV12 = visual->supported_formats&XINE_VORAW_YV12; + this->doYUY2 = visual->supported_formats&XINE_VORAW_YUY2; + + this->vo_driver.get_capabilities = raw_get_capabilities; + this->vo_driver.alloc_frame = raw_alloc_frame; + this->vo_driver.update_frame_format = raw_update_frame_format; + this->vo_driver.overlay_begin = raw_overlay_begin; + this->vo_driver.overlay_blend = raw_overlay_blend; + this->vo_driver.overlay_end = raw_overlay_end; + this->vo_driver.display_frame = raw_display_frame; + this->vo_driver.get_property = raw_get_property; + this->vo_driver.set_property = raw_set_property; + this->vo_driver.get_property_min_max = raw_get_property_min_max; + this->vo_driver.gui_data_exchange = raw_gui_data_exchange; + this->vo_driver.dispose = raw_dispose; + this->vo_driver.redraw_needed = raw_redraw_needed; + + this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 1, NULL); /* converts to rgb */ + + for (i = 0; i < NUM_FRAMES_BACKLOG; i++) + this->frame[i] = 0; + + for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) { + this->overlays[i].ovl_w = this->overlays[i].ovl_h = 2; + this->overlays[i].ovl_rgba = (uint8_t*)malloc(2*2*4); + this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; + } + this->ovl_changed = 0; + + /* we have to use a second converter for overlays + * because "MODE_24_BGR, 1 (swap)" breaks overlays conversion */ + yuv2rgb_factory_t *factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); + this->ovl_yuv2rgb = factory->create_converter( factory ); + factory->dispose( factory ); + + return &this->vo_driver; +} + +/* + * class functions + */ + +static char* raw_get_identifier (video_driver_class_t *this_gen) +{ + return "raw"; +} + + + +static char* raw_get_description (video_driver_class_t *this_gen) +{ + return _("xine video output plugin passing raw data to supplied callback"); +} + + + +static void raw_dispose_class (video_driver_class_t *this_gen) +{ + raw_class_t *this = (raw_class_t *) this_gen; + free (this); +} + + + +static void *raw_init_class (xine_t *xine, void *visual_gen) +{ + raw_class_t *this = (raw_class_t *) calloc(1, sizeof(raw_class_t)); + + this->driver_class.open_plugin = raw_open_plugin; + this->driver_class.get_identifier = raw_get_identifier; + this->driver_class.get_description = raw_get_description; + this->driver_class.dispose = raw_dispose_class; + this->xine = xine; + + return this; +} + + + +static const vo_info_t vo_info_raw = { + 7, /* priority */ + XINE_VISUAL_TYPE_RAW /* visual type */ +}; + + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_VIDEO_OUT, 21, "raw", XINE_VERSION_CODE, &vo_info_raw, raw_init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/video_out/video_out_sdl.c b/src/video_out/video_out_sdl.c index 6705b4176..36d66cd86 100644 --- a/src/video_out/video_out_sdl.c +++ b/src/video_out/video_out_sdl.c @@ -83,7 +83,7 @@ struct sdl_driver_s { vo_driver_t vo_driver; config_values_t *config; - + int hw_accel; SDL_Surface *surface; @@ -100,7 +100,7 @@ struct sdl_driver_s { int screen; Drawable drawable; #endif - + vo_scale_t sc; xine_t *xine; @@ -138,11 +138,11 @@ static vo_frame_t *sdl_alloc_frame (vo_driver_t *this_gen) { /* sdl_driver_t *this = (sdl_driver_t *) this_gen; */ sdl_frame_t *frame ; - frame = (sdl_frame_t *) xine_xmalloc (sizeof (sdl_frame_t)); + frame = (sdl_frame_t *) calloc(1, sizeof(sdl_frame_t)); if (!frame) return NULL; - + pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* @@ -207,8 +207,8 @@ static void sdl_update_frame_format (vo_driver_t *this_gen, if (frame->overlay == NULL) return; - /* - * This needs to be done becuase I have found that + /* + * This needs to be done becuase I have found that * pixels isn't setup until this is called. */ SDL_LockYUVOverlay (frame->overlay); @@ -242,7 +242,7 @@ static void sdl_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_ this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; - + if (overlay->rle) { if( frame->format == XINE_IMGFMT_YV12 ) _x_blend_yuv( frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); @@ -354,7 +354,7 @@ static void sdl_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { static int sdl_get_property (vo_driver_t *this_gen, int property) { sdl_driver_t *this = (sdl_driver_t *) this_gen; - + switch (property) { case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; @@ -383,7 +383,7 @@ static int sdl_set_property (vo_driver_t *this_gen, if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->sc.user_ratio = value; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_sdl: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); sdl_compute_ideal_size (this); @@ -458,7 +458,7 @@ static void sdl_dispose (vo_driver_t * this_gen) { SDL_QuitSubSystem (SDL_INIT_VIDEO); _x_alphablend_free(&this->alphablend_extra_data); - + free(this); } @@ -469,21 +469,23 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi sdl_driver_t *this; const SDL_VideoInfo *vidInfo; -#ifdef HAVE_X11 +#if defined(HAVE_X11) || defined(WIN32) static char SDL_windowhack[32]; x11_visual_t *visual = (x11_visual_t *) visual_gen; +#endif +#ifdef HAVE_X11 XWindowAttributes window_attributes; #endif - - this = (sdl_driver_t *) xine_xmalloc (sizeof (sdl_driver_t)); + + this = (sdl_driver_t *) calloc(1, sizeof(sdl_driver_t)); if (!this) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->sdlflags = SDL_HWSURFACE | SDL_RESIZABLE; - - this->hw_accel = class->config->register_bool(class->config, + + this->hw_accel = class->config->register_bool(class->config, "video.device.sdl_hw_accel", 1, _("use hardware acceleration if available"), _("When your system supports it, hardware acceleration provided by your " @@ -502,14 +504,18 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi _x_vo_scale_init( &this->sc, 0, 0, config); this->sc.frame_output_cb = visual->frame_output_cb; this->sc.user_data = visual->user_data; - - /* set SDL to use our existing X11 window */ - sprintf(SDL_windowhack,"SDL_WINDOWID=0x%x", (uint32_t) this->drawable ); - putenv(SDL_windowhack); #else _x_vo_scale_init( &this->sc, 0, 0, config ); #endif +#if defined(HAVE_X11) || defined(WIN32) + /* set SDL to use our existing X11/win32 window */ + if (visual->d){ + sprintf(SDL_windowhack,"SDL_WINDOWID=0x%x", (uint32_t) visual->d); + putenv(SDL_windowhack); + } +#endif + if ((SDL_Init (SDL_INIT_VIDEO)) < 0) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_sdl: open_plugin - sdl video initialization failed.\n"); return NULL; @@ -519,7 +525,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi if (!SDL_ListModes (vidInfo->vfmt, SDL_HWSURFACE | SDL_RESIZABLE)) { this->sdlflags = SDL_RESIZABLE; if (!SDL_ListModes (vidInfo->vfmt, SDL_RESIZABLE)) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_sdl: open_plugin - sdl couldn't get any acceptable video mode\n"); return NULL; } @@ -527,7 +533,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->bpp = vidInfo->vfmt->BitsPerPixel; if (this->bpp < 16) { - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("sdl has to emulate a 16 bit surfaces, that will slow things down.\n")); this->bpp = 16; } @@ -587,17 +593,17 @@ static void dispose_class (video_driver_class_t *this_gen) { static void *init_class (xine_t *xine, void *visual_gen) { /* x11_visual_t *visual = (x11_visual_t *) visual_gen; */ sdl_class_t *this; - + /* check if we have SDL */ if ((SDL_Init (SDL_INIT_VIDEO)) < 0) { - xprintf (xine, XINE_VERBOSITY_DEBUG, + xprintf (xine, XINE_VERBOSITY_DEBUG, "video_out_sdl: open_plugin - sdl video initialization failed.\n"); return NULL; } SDL_QuitSubSystem (SDL_INIT_VIDEO); - this = (sdl_class_t*) xine_xmalloc (sizeof (sdl_class_t)); - + this = (sdl_class_t*) calloc(1, sizeof(sdl_class_t)); + this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; this->driver_class.get_description = get_description; diff --git a/src/video_out/video_out_stk.c b/src/video_out/video_out_stk.c index dfc4ae385..647760fd2 100644 --- a/src/video_out/video_out_stk.c +++ b/src/video_out/video_out_stk.c @@ -22,7 +22,7 @@ * * based on video_out_sdl from * Miguel Freitas - * + * * based on mpeg2dec code from * Ryan C. Gordon <icculus@lokigames.com> and * Dominik Schnitzer <aeneas@linuxvideo.org> @@ -82,9 +82,9 @@ typedef struct stk_driver_s { vo_driver_t vo_driver; /* stk private data */ - config_values_t* config; - surface_t* surface; - xine_panel_t* xine_panel; + config_values_t* config; + surface_t* surface; + xine_panel_t* xine_panel; uint8_t bpp; /* do we need this ? */ pthread_mutex_t mutex; uint32_t capabilities; @@ -133,7 +133,7 @@ static vo_frame_t *stk_alloc_frame(vo_driver_t *this_gen) { stk_frame_t* frame; //printf("video_out_stk: alloc_frame()\n"); - frame = (stk_frame_t *) xine_xmalloc(sizeof(stk_frame_t)); + frame = calloc(1, sizeof(stk_frame_t)); if (!frame) return NULL; @@ -171,25 +171,25 @@ static void stk_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ge //printf("video_out_stk: update_frame_format()\n"); if ((frame->width != width) || (frame->height != height) || (frame->format != format)) { - lprintf("update_frame_format - %d=%d, %d=%d, %d=%d\n", + lprintf("update_frame_format - %d=%d, %d=%d, %d=%d\n", frame->width, width, frame->height, height, frame->format, format); - lprintf("vo_frame data - width, height, format: %d, %d, %d\n", + lprintf("vo_frame data - width, height, format: %d, %d, %d\n", frame->vo_frame.width, frame->vo_frame.height, frame->vo_frame.format); - + /* (re-) allocate image */ if (frame->overlay) { - stk_overlay_free(frame->overlay); + stk_overlay_free(frame->overlay); frame->overlay = NULL; } if (format == XINE_IMGFMT_YV12) { lprintf ("format YV12\n"); - frame->overlay = stk_surface_create_overlay(this->surface, width, height, + frame->overlay = stk_surface_create_overlay(this->surface, width, height, STK_FORMAT_YV12); } else if (format == XINE_IMGFMT_YUY2) { lprintf("format YUY2\n"); - frame->overlay = stk_surface_create_overlay(this->surface, width, height, + frame->overlay = stk_surface_create_overlay(this->surface, width, height, STK_FORMAT_YUY2); } @@ -197,7 +197,7 @@ static void stk_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ge return; /* From the SDL driver: - * This needs to be done becuase I have found that + * This needs to be done becuase I have found that * pixels isn't setup until this is called. */ stk_overlay_lock(frame->overlay); @@ -224,7 +224,7 @@ static void stk_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_ stk_driver_t* this = (stk_driver_t*)this_gen; stk_frame_t* frame = (stk_frame_t*)frame_gen; //printf("video_out_stk: overlay_blend()\n"); - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; @@ -238,7 +238,7 @@ static void stk_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_ } static void stk_check_events (stk_driver_t* this) { - /* SDL checks for a resize, our video panels aren't resizeable... */ + /* SDL checks for a resize, our video panels aren't resizeable... */ //printf("video_out_stk: check_events()\n"); } @@ -247,7 +247,7 @@ static int stk_redraw_needed (vo_driver_t* this_gen) { stk_driver_t* this = (stk_driver_t*)this_gen; int ret = 0; static int last_gui_width, last_gui_height; - + //printf("video_out_stk: redraw_needed()\n"); if( last_gui_width != this->sc.gui_width || @@ -273,7 +273,7 @@ static void stk_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { stk_frame_t* frame = (stk_frame_t*)frame_gen; //printf("video_out_stk: display_frame()\n"); - + pthread_mutex_lock(&this->mutex); if ( (frame->width != this->sc.delivered_width) @@ -308,7 +308,7 @@ static void stk_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { static int stk_get_property (vo_driver_t* this_gen, int property) { stk_driver_t* this = (stk_driver_t *)this_gen; - + //printf("video_out_stk: get_property()\n"); if (property == VO_PROP_ASPECT_RATIO) @@ -321,7 +321,7 @@ static int stk_set_property (vo_driver_t* this_gen, int property, int value) { stk_driver_t* this = (stk_driver_t*)this_gen; //printf("video_out_stk: set_property()\n"); - + if ( property == VO_PROP_ASPECT_RATIO) { if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; @@ -341,7 +341,7 @@ static void stk_get_property_min_max (vo_driver_t *this_gen, int property, int * //printf("video_out_stk: get_property_min_max()\n"); } -static int stk_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { +static int stk_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { stk_driver_t *this = (stk_driver_t*)this_gen; switch (data_type) @@ -349,9 +349,9 @@ static int stk_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *da case XINE_GUI_SEND_COMPLETION_EVENT: break; - case XINE_GUI_SEND_EXPOSE_EVENT: + case XINE_GUI_SEND_EXPOSE_EVENT: break; - + case XINE_GUI_SEND_DRAWABLE_CHANGED: this->xine_panel = (xine_panel_t*)data; this->surface = stk_xine_panel_surface(this->xine_panel); @@ -365,18 +365,18 @@ static int stk_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *da case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: break; } - + return 0; } static void stk_dispose (vo_driver_t * this_gen) { stk_driver_t* this = (stk_driver_t*)this_gen; - + //printf("video_out_stk: dispose()\n"); - - /* FIXME: any libstk deleting must be done in the app or library + + /* FIXME: any libstk deleting must be done in the app or library * since we didn't create the surface */ - + _x_alphablend_free(&this->alphablend_extra_data); free(this); @@ -386,10 +386,10 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis stk_class_t * class = (stk_class_t *) class_gen; /* allocate the video output driver class */ stk_driver_t* this; - + //printf("video_out_stk: open_plugin()\n"); - - this = (stk_driver_t *) xine_xmalloc (sizeof (stk_driver_t)); + + this = calloc(1, sizeof (stk_driver_t)); if (!this) return NULL; @@ -432,7 +432,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis /* FIXME: move this to the stk SDL driver code */ xine_setenv("SDL_VIDEO_YUV_HWACCEL", "1", 1); xine_setenv("SDL_VIDEO_X11_NODIRECTCOLOR", "1", 1); - + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_stk: warning, xine's STK driver is EXPERIMENTAL\n"); return &this->vo_driver; @@ -460,16 +460,16 @@ static void dispose_class (video_driver_class_t *this_gen) { static void *init_class (xine_t *xine, void *visual_gen) { stk_class_t* this; - + //printf("video_out_stk: init_class()\n"); - this = (stk_class_t *) xine_xmalloc(sizeof(stk_class_t)); + this = calloc(1, sizeof(stk_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; this->driver_class.get_description = get_description; this->driver_class.dispose = dispose_class; - + this->config = xine->config; this->xine = xine; diff --git a/src/video_out/video_out_syncfb.c b/src/video_out/video_out_syncfb.c index b1fadbd58..aaf7d43c7 100644 --- a/src/video_out/video_out_syncfb.c +++ b/src/video_out/video_out_syncfb.c @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -18,14 +18,14 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * video_out_syncfb.c, SyncFB (for Matrox G200/G400 cards) interface for xine - * + * * based on video_out_xv.c by (see file for original authors) - * + * * with lot's of code from: * video_out_syncfb.c by Joachim Koenig <joachim.koenig@gmx.net> * and by Matthias Oelmann <mao@well.com> * video_out_mga by Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - * + * * glued together for xine by Matthias Dahl <matthew2k@web.de> */ @@ -133,7 +133,7 @@ typedef struct { /* returns boolean value (1 success, 0 failure) */ static int syncfb_overlay_on(syncfb_driver_t* this) { - if(ioctl(this->fd, SYNCFB_ON)) { + if(ioctl(this->fd, SYNCFB_ON)) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (on ioctl failed)\n"); return 0; @@ -145,7 +145,7 @@ static int syncfb_overlay_on(syncfb_driver_t* this) /* returns boolean value (1 success, 0 failure) */ static int syncfb_overlay_off(syncfb_driver_t* this) -{ +{ if(ioctl(this->fd, SYNCFB_OFF)) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (off ioctl failed)\n"); @@ -169,7 +169,7 @@ static void write_frame_YUV422(syncfb_driver_t* this, syncfb_frame_t* frame) for(h = 0; h < (frame->height / 2); h++) { cbp = cb; crp = cr; - + for(w = 0; w < (frame->width / 2); w++) { *dst32++ = (*y) + ((*cb)<<8) + ((*(y+1))<<16) + ((*cr)<<24); y++; y++; cb++; cr++; @@ -181,33 +181,33 @@ static void write_frame_YUV422(syncfb_driver_t* this, syncfb_frame_t* frame) *dst32++ = (*y) + ((*cbp)<<8) + ((*(y+1))<<16) + ((*crp)<<24); y++; y++; cbp++; crp++; } - + dst32 += (this->syncfb_config.src_pitch - frame->width) / 2; } } static void write_frame_YUV420P2(syncfb_driver_t* this, syncfb_frame_t* frame) -{ +{ uint8_t* y = (uint8_t *)frame->vo_frame.base[0]; uint8_t* cb = (uint8_t *)frame->vo_frame.base[1]; uint8_t* cr = (uint8_t *)frame->vo_frame.base[2]; uint8_t* dst8 = this->video_mem + this->bufinfo.offset_p2; - int h, w; - + int h, w; + register uint32_t* tmp32; register uint8_t* rcr; register uint8_t* rcb; rcr = cr; rcb = cb; - + for(h = 0; h < (frame->height / 2); h++) { tmp32 = (uint32_t *)dst8; w = (frame->width / 8) * 2; - + while(w--) { register uint32_t temp; - + temp = (*rcb) | (*rcr << 8); rcr++; rcb++; @@ -217,7 +217,7 @@ static void write_frame_YUV420P2(syncfb_driver_t* this, syncfb_frame_t* frame) *tmp32 = temp; tmp32++; } - + dst8 += this->syncfb_config.src_pitch; } @@ -230,13 +230,13 @@ static void write_frame_YUV420P2(syncfb_driver_t* this, syncfb_frame_t* frame) } static void write_frame_YUV420P3(syncfb_driver_t* this, syncfb_frame_t* frame) -{ +{ uint8_t* y = (uint8_t *)frame->vo_frame.base[0]; uint8_t* cb = (uint8_t *)frame->vo_frame.base[1]; uint8_t* cr = (uint8_t *)frame->vo_frame.base[2]; uint8_t* dst8 = this->video_mem + this->bufinfo.offset; int h, half_width = (frame->width/2); - + for(h = 0; h < frame->height; h++) { xine_fast_memcpy(dst8, y, frame->width); y += frame->width; @@ -247,16 +247,16 @@ static void write_frame_YUV420P3(syncfb_driver_t* this, syncfb_frame_t* frame) for(h = 0; h < (frame->height / 2); h++) { xine_fast_memcpy((dst8 + this->bufinfo.offset_p2), cb, half_width); xine_fast_memcpy((dst8 + this->bufinfo.offset_p3), cr, half_width); - + cb += half_width; cr += half_width; - + dst8 += (this->syncfb_config.src_pitch / 2); } } static void write_frame_YUY2(syncfb_driver_t* this, syncfb_frame_t* frame) -{ +{ uint8_t* src8 = (uint8_t *)frame->vo_frame.base[0]; uint8_t* dst8 = (uint8_t *)(this->video_mem + this->bufinfo.offset); int h, double_width = (frame->width * 2); @@ -271,7 +271,7 @@ static void write_frame_YUY2(syncfb_driver_t* this, syncfb_frame_t* frame) static void write_frame_sfb(syncfb_driver_t* this, syncfb_frame_t* frame) { - switch(frame->format) { + switch(frame->format) { case XINE_IMGFMT_YUY2: if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV422)) write_frame_YUY2(this, frame); @@ -279,7 +279,7 @@ static void write_frame_sfb(syncfb_driver_t* this, syncfb_frame_t* frame) xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_syncfb: error. (YUY2 not supported by your graphic card)\n")); break; - + case XINE_IMGFMT_YV12: switch(this->yuv_format) { case VIDEO_PALETTE_YUV422: @@ -294,14 +294,14 @@ static void write_frame_sfb(syncfb_driver_t* this, syncfb_frame_t* frame) default: xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_syncfb: error. (YV12 not supported by your graphic card)\n")); - } + } break; - + default: xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (unknown frame format)\n"); break; } - + frame->vo_frame.free(&frame->vo_frame); } @@ -321,7 +321,7 @@ static void free_framedata(syncfb_frame_t* frame) free(frame->data_mem[2]); frame->data_mem[2] = NULL; }*/ - + if(frame->vo_frame.base[0]) { free(frame->vo_frame.base[0]); frame->vo_frame.base[0] = NULL; @@ -371,24 +371,24 @@ static void syncfb_compute_output_size(syncfb_driver_t *this) * configuring SyncFB module from this point on. */ syncfb_overlay_off(this); - + /* sanity checking - certain situations *may* crash the SyncFB module, so * take care that we always have valid numbers. */ - if(this->sc.output_xoffset >= 0 && this->sc.output_yoffset >= 0 && - this->cur_frame->width > 0 && this->cur_frame->height > 0 && - this->sc.output_width > 0 && this->sc.output_height > 0 && + if(this->sc.output_xoffset >= 0 && this->sc.output_yoffset >= 0 && + this->cur_frame->width > 0 && this->cur_frame->height > 0 && + this->sc.output_width > 0 && this->sc.output_height > 0 && this->cur_frame->format > 0 && this->video_win_visibility) { - + if(ioctl(this->fd, SYNCFB_GET_CONFIG, &this->syncfb_config)) - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (get_config ioctl failed)\n"); - + this->syncfb_config.syncfb_mode = SYNCFB_FEATURE_SCALE | SYNCFB_FEATURE_CROP; - + if(this->props[VO_PROP_INTERLACED].value) this->syncfb_config.syncfb_mode |= SYNCFB_FEATURE_DEINTERLACE; - + switch(this->cur_frame->format) { case XINE_IMGFMT_YV12: this->syncfb_config.src_palette = this->yuv_format; @@ -397,33 +397,33 @@ static void syncfb_compute_output_size(syncfb_driver_t *this) this->syncfb_config.src_palette = VIDEO_PALETTE_YUV422; break; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (unknown frame format)\n"); this->syncfb_config.src_palette = 0; break; } - + this->syncfb_config.fb_screen_size = this->virtual_screen_width * this->virtual_screen_height * (this->screen_depth / 8) * 2; this->syncfb_config.src_width = this->cur_frame->width; this->syncfb_config.src_height = this->cur_frame->height; - + this->syncfb_config.image_width = this->sc.output_width; this->syncfb_config.image_height = this->sc.output_height; - + this->syncfb_config.image_xorg = this->sc.output_xoffset + this->sc.gui_win_x; this->syncfb_config.image_yorg = this->sc.output_yoffset + this->sc.gui_win_y; - + this->syncfb_config.src_crop_top = this->sc.displayed_yoffset; this->syncfb_config.src_crop_bot = (this->props[VO_PROP_INTERLACED].value && this->sc.displayed_yoffset == 0) ? 1 : this->sc.displayed_yoffset; this->syncfb_config.src_crop_left = this->sc.displayed_xoffset; this->syncfb_config.src_crop_right = this->sc.displayed_xoffset; - + this->syncfb_config.default_repeat = (this->props[VO_PROP_INTERLACED].value) ? 1 : this->default_repeat; - + if(this->capabilities.palettes & (1<<this->syncfb_config.src_palette)) { if(ioctl(this->fd,SYNCFB_SET_CONFIG,&this->syncfb_config)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (set_config ioctl failed)\n"); - + syncfb_overlay_on(this); } } @@ -438,16 +438,16 @@ static int syncfb_redraw_needed(vo_driver_t* this_gen) syncfb_driver_t* this = (syncfb_driver_t *) this_gen; int ret = 0; - + if( _x_vo_scale_redraw_needed( &this->sc ) ) { syncfb_compute_output_size (this); syncfb_clean_output_area (this); - + ret = 1; } - + return ret; } @@ -466,7 +466,7 @@ static void syncfb_frame_field (vo_frame_t *vo_img, int which_field) static void syncfb_frame_dispose(vo_frame_t* vo_img) { syncfb_frame_t* frame = (syncfb_frame_t *) vo_img; - + if(frame) { free_framedata(frame); free(frame); @@ -477,17 +477,17 @@ static vo_frame_t* syncfb_alloc_frame(vo_driver_t* this_gen) { /* syncfb_driver_t *this = (syncfb_driver_t *) this_gen; */ syncfb_frame_t *frame; - - frame = (syncfb_frame_t *) xine_xmalloc(sizeof(syncfb_frame_t)); + + frame = calloc(1, sizeof(syncfb_frame_t)); if(!frame) return NULL; - + pthread_mutex_init(&frame->vo_frame.mutex, NULL); - + frame->vo_frame.base[0] = NULL; frame->vo_frame.base[1] = NULL; frame->vo_frame.base[2] = NULL; - + /* * supply required functions */ @@ -495,9 +495,9 @@ static vo_frame_t* syncfb_alloc_frame(vo_driver_t* this_gen) frame->vo_frame.proc_frame = NULL; frame->vo_frame.field = syncfb_frame_field; frame->vo_frame.dispose = syncfb_frame_dispose; - + frame->vo_frame.driver = this_gen; - + return (vo_frame_t *) frame; } @@ -509,7 +509,7 @@ static void syncfb_update_frame_format(vo_driver_t* this_gen, syncfb_driver_t *this = (syncfb_driver_t *) this_gen; syncfb_frame_t *frame = (syncfb_frame_t *) frame_gen; /* uint32_t frame_size = width*height; */ - + if((frame->width != width) || (frame->height != height) || (frame->format != format)) { @@ -518,7 +518,7 @@ static void syncfb_update_frame_format(vo_driver_t* this_gen, printf("video_out_syncfb: debug. (update frame format: old values [width=%d, height=%d, format=%04x], new values [width=%d, height=%d, format=%04x])\n", frame->width, frame->height, frame->format, width, height, format); #endif free_framedata(frame); - + frame->width = width; frame->height = height; frame->format = format; @@ -547,14 +547,14 @@ static void syncfb_update_frame_format(vo_driver_t* this_gen, "video_out_syncfb: error. (unable to allocate " "framedata because of unknown frame format: %04x)\n", format); } - + /* if((format == IMGFMT_YV12 && (frame->data_mem[0] == NULL || frame->data_mem[1] == NULL || frame->data_mem[2] == NULL)) || (format == IMGFMT_YUY2 && frame->data_mem[0] == NULL)) {*/ if((format == XINE_IMGFMT_YV12 && (frame->vo_frame.base[0] == NULL || frame->vo_frame.base[1] == NULL || frame->vo_frame.base[2] == NULL)) || (format == XINE_IMGFMT_YUY2 && frame->vo_frame.base[0] == NULL)) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (framedata allocation failed: out of memory)\n"); - + free_framedata(frame); } } @@ -566,7 +566,7 @@ static void syncfb_overlay_blend(vo_driver_t* this_gen, vo_frame_t* frame_gen, v { syncfb_frame_t* frame = (syncfb_frame_t *) frame_gen; syncfb_driver_t* this = (syncfb_driver_t *) this_gen; - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; @@ -600,23 +600,23 @@ static void syncfb_display_frame(vo_driver_t* this_gen, vo_frame_t* frame_gen) this->sc.delivered_width = frame->width; this->sc.delivered_height = frame->height; this->sc.delivered_ratio = frame->ratio; - + this->sc.crop_left = frame->vo_frame.crop_left; this->sc.crop_right = frame->vo_frame.crop_right; this->sc.crop_top = frame->vo_frame.crop_top; this->sc.crop_bottom = frame->vo_frame.crop_bottom; syncfb_compute_ideal_size(this); - + this->sc.force_redraw = 1; } - /* + /* * tell gui that we are about to display a frame, * ask for offset and output size - */ + */ syncfb_redraw_needed(this_gen); - + /* the rest is only successful and safe, if the overlay is really on */ if(this->overlay_state) { if(this->bufinfo.id != -1) { @@ -626,16 +626,16 @@ static void syncfb_display_frame(vo_driver_t* this_gen, vo_frame_t* frame_gen) return; } - + if(ioctl(this->fd, SYNCFB_REQUEST_BUFFER, &this->bufinfo)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (request ioctl failed)\n"); - + if(this->bufinfo.id == -1) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (syncfb module couldn't allocate image buffer)\n"); frame->vo_frame.free(&frame->vo_frame); - - /* + + /* * there are several "fixable" situations when this request will fail. * for example when the screen resolution changes, the kernel module * will get confused - reinitializing everything will fix things for @@ -643,26 +643,26 @@ static void syncfb_display_frame(vo_driver_t* this_gen, vo_frame_t* frame_gen) */ syncfb_compute_ideal_size(this); syncfb_compute_output_size(this); - syncfb_clean_output_area(this); - + syncfb_clean_output_area(this); + return; } - + write_frame_sfb(this, frame); - + if(ioctl(this->fd, SYNCFB_COMMIT_BUFFER, &this->bufinfo)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (commit ioctl failed)\n"); } else frame->vo_frame.free(&frame->vo_frame); - - this->bufinfo.id = -1; + + this->bufinfo.id = -1; } static int syncfb_get_property(vo_driver_t* this_gen, int property) { syncfb_driver_t* this = (syncfb_driver_t *) this_gen; - + switch (property) { case VO_PROP_WINDOW_WIDTH: this->props[property].value = this->sc.gui_width; @@ -683,28 +683,28 @@ static int syncfb_get_property(vo_driver_t* this_gen, int property) this->props[property].value = this->sc.output_yoffset; break; } - + return this->props[property].value; } static int syncfb_set_property(vo_driver_t* this_gen, int property, int value) { syncfb_driver_t* this = (syncfb_driver_t *) this_gen; - + switch (property) { case VO_PROP_INTERLACED: this->props[property].value = value; #ifdef DEBUG_OUTPUT - printf("video_out_syncfb: debug. (VO_PROP_INTERLACED(%d))\n", + printf("video_out_syncfb: debug. (VO_PROP_INTERLACED(%d))\n", this->props[property].value); #endif - + syncfb_compute_ideal_size(this); syncfb_compute_output_size(this); - syncfb_clean_output_area(this); + syncfb_clean_output_area(this); break; - + case VO_PROP_ASPECT_RATIO: if(value >= XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; @@ -721,14 +721,14 @@ static int syncfb_set_property(vo_driver_t* this_gen, int property, int value) syncfb_compute_output_size(this); syncfb_clean_output_area(this); break; - + case VO_PROP_ZOOM_X: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->props[property].value = value; this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; - + syncfb_compute_ideal_size (this); - + this->sc.force_redraw = 1; } /* @@ -740,16 +740,16 @@ static int syncfb_set_property(vo_driver_t* this_gen, int property, int value) if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->props[property].value = value; this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; - + syncfb_compute_ideal_size (this); - + this->sc.force_redraw = 1; } /* printf("video_out_syncfb: info. (the zooming feature is not supported at the moment because of a bug with the SyncFB kernel driver, please refer to README.syncfb)\n"); */ break; - + case VO_PROP_CONTRAST: this->props[property].value = value; @@ -764,7 +764,7 @@ static int syncfb_set_property(vo_driver_t* this_gen, int property, int value) this->params.image_height = this->syncfb_config.image_height; this->params.image_xorg = this->syncfb_config.image_xorg; this->params.image_yorg = this->syncfb_config.image_yorg; - + if(ioctl(this->fd,SYNCFB_SET_PARAMS,&this->params)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (setting of contrast value failed)\n"); @@ -778,25 +778,25 @@ static int syncfb_set_property(vo_driver_t* this_gen, int property, int value) printf("video_out_syncfb: debug. (VO_PROP_BRIGHTNESS(%d))\n", this->props[property].value); #endif - + this->params.brightness = value; this->params.contrast = this->props[VO_PROP_CONTRAST].value; this->params.image_width = this->syncfb_config.image_width; /* FIXME */ this->params.image_height = this->syncfb_config.image_height; this->params.image_xorg = this->syncfb_config.image_xorg; this->params.image_yorg = this->syncfb_config.image_yorg; - + if(ioctl(this->fd,SYNCFB_SET_PARAMS,&this->params)) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: error. (setting of brightness value failed)\n"); - + break; - } + } return value; } -static void syncfb_get_property_min_max(vo_driver_t *this_gen, +static void syncfb_get_property_min_max(vo_driver_t *this_gen, int property, int *min, int *max) { syncfb_driver_t* this = (syncfb_driver_t *) this_gen; @@ -809,7 +809,7 @@ static int syncfb_gui_data_exchange(vo_driver_t* this_gen, int data_type, void *data) { syncfb_driver_t* this = (syncfb_driver_t *) this_gen; - + switch (data_type) { case XINE_GUI_SEND_DRAWABLE_CHANGED: this->drawable = (Drawable) data; @@ -839,8 +839,8 @@ static int syncfb_gui_data_exchange(vo_driver_t* this_gen, int data_type, this->video_win_visibility = (int)(int *)data; syncfb_compute_output_size(this); break; - */ - + */ + default: return -1; } @@ -854,39 +854,39 @@ static void syncfb_dispose(vo_driver_t *this_gen) /* get it off the screen - I wanna see my desktop again :-) */ syncfb_overlay_off(this); - + /* don't know if it is necessary are even right, but anyway...?! */ - munmap(0, this->capabilities.memory_size); - + munmap(0, this->capabilities.memory_size); + close(this->fd); XLockDisplay (this->display); XFreeGC(this->display, this->gc); XUnlockDisplay (this->display); - + _x_alphablend_free(&this->alphablend_extra_data); - + free(this); } static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { - + syncfb_class_t *class = (syncfb_class_t *) class_gen; config_values_t *config = class->config; syncfb_driver_t* this; - Display* display = NULL; + Display* display = NULL; unsigned int i; x11_visual_t* visual = (x11_visual_t *) visual_gen; XColor dummy; XWindowAttributes attr; display = visual->display; - - if(!(this = xine_xmalloc(sizeof (syncfb_driver_t)))) + + if(!(this = calloc(1, sizeof (syncfb_driver_t)))) return NULL; - + _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + /* check for syncfb device */ if((this->fd = open(class->device_name, O_RDWR)) < 0) { xprintf(class->xine, XINE_VERBOSITY_DEBUG, @@ -894,17 +894,17 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi free(this); return NULL; } - + this->xine = class->xine; /* get capabilities from the syncfb module */ if(ioctl(this->fd, SYNCFB_GET_CAPS, &this->capabilities)) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: aborting. (syncfb_get_caps ioctl failed)\n"); - + close(this->fd); free(this); - + return NULL; } @@ -914,16 +914,16 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi if(this->video_mem == MAP_FAILED) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_syncfb: aborting. (mmap of video memory failed)\n"); - + close(this->fd); free(this); - + return NULL; } - + /* * init properties and capabilities - */ + */ for (i = 0; i<VO_NUM_PROPERTIES; i++) { this->props[i].value = 0; this->props[i].min = 0; @@ -953,13 +953,13 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->yuv_format = VIDEO_PALETTE_YUV420P2; xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_syncfb: info. (SyncFB module supports YUV 4:2:0 (2 plane))\n")); - } else if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV422)) { + } else if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV422)) { this->supported_capabilities |= VO_CAP_YV12; this->yuv_format = VIDEO_PALETTE_YUV422; xprintf(this->xine, XINE_VERBOSITY_DEBUG, _("video_out_syncfb: info. (SyncFB module supports YUV 4:2:2)\n")); } - + if(this->capabilities.palettes & (1<<VIDEO_PALETTE_YUV422)) { this->supported_capabilities |= VO_CAP_YUY2; xprintf(this->xine, XINE_VERBOSITY_DEBUG, @@ -976,11 +976,11 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi if(!this->supported_capabilities) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, _("video_out_syncfb: aborting. (SyncFB module does not support YV12, YUY2 nor RGB565)\n")); - - munmap(0, this->capabilities.memory_size); + + munmap(0, this->capabilities.memory_size); close(this->fd); free(this); - + return NULL; } @@ -1002,21 +1002,21 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi /* check for virtual screen size and screen depth - this is rather important because that data is later used for free memory calculation */ XGetWindowAttributes(visual->display, DefaultRootWindow(visual->display), &attr); - + this->virtual_screen_height = attr.height; this->virtual_screen_width = attr.width; this->screen_depth = attr.depth; - + /* initialize the rest of the variables now with default values */ this->bufinfo.id = -1; this->config = config; this->cur_frame = NULL; - + /* FIXME: setting the default_repeat to anything higher than 1 will result in a distorted video, so for now, set this manually to 0 until the kernel driver is fixed... */ #if 0 - this->default_repeat = config->register_range(config, + this->default_repeat = config->register_range(config, "video.device.syncfb_default_repeat", 3, 1, 4, _("default number of frame repetitions"), _("This specifies how many times a single video " @@ -1024,7 +1024,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi 10, NULL, NULL); #endif this->default_repeat = 0; - + this->display = visual->display; this->drawable = visual->d; this->gc = XCreateGC (this->display, this->drawable, 0, NULL); @@ -1034,9 +1034,9 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi this->sc.user_data = visual->user_data; this->overlay = NULL; - this->screen = visual->screen; + this->screen = visual->screen; this->video_win_visibility = 1; - + XAllocNamedColor(this->display, DefaultColormap(this->display, this->screen), "black", &this->black, &dummy); @@ -1084,7 +1084,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { int fd; device_name = xine->config->register_filename(xine->config, "video.device.syncfb_device", "/dev/syncfb", - XINE_CONFIG_STRING_IS_DEVICE_NAME, + XINE_CONFIG_STRING_IS_DEVICE_NAME, _("SyncFB device name"), _("Specifies the file name for the SyncFB (TeleTux) device " "to be used.\nThis setting is security critical, " @@ -1093,7 +1093,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { "So you should be careful that the value you enter " "really is a proper framebuffer device."), XINE_CONFIG_SECURITY, NULL, NULL); - + /* check for syncfb device */ if((fd = open(device_name, O_RDWR)) < 0) { xprintf(xine, XINE_VERBOSITY_DEBUG, @@ -1101,11 +1101,11 @@ static void *init_class (xine_t *xine, void *visual_gen) { return NULL; } close(fd); - + /* * from this point on, nothing should go wrong anymore */ - this = (syncfb_class_t *) xine_xmalloc (sizeof (syncfb_class_t)); + this = calloc(1, sizeof (syncfb_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; @@ -1115,7 +1115,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { this->config = xine->config; this->xine = xine; this->device_name = device_name; - + return this; } diff --git a/src/video_out/video_out_syncfb.h b/src/video_out/video_out_syncfb.h index 1fc3df83a..069cbcedc 100644 --- a/src/video_out/video_out_syncfb.h +++ b/src/video_out/video_out_syncfb.h @@ -83,16 +83,16 @@ typedef unsigned char uint_8; #define SYNCFB_FEATURE_SCALE_H 1 #define SYNCFB_FEATURE_SCALE_V 2 #define SYNCFB_FEATURE_SCALE 3 -#define SYNCFB_FEATURE_CROP 4 +#define SYNCFB_FEATURE_CROP 4 #define SYNCFB_FEATURE_OFFSET 8 -#define SYNCFB_FEATURE_DEINTERLACE 16 -#define SYNCFB_FEATURE_PROCAMP 32 -#define SYNCFB_FEATURE_TRANSITIONS 64 -#define SYNCFB_FEATURE_COLKEY 128 -#define SYNCFB_FEATURE_MIRROR_H 256 -#define SYNCFB_FEATURE_MIRROR_V 512 -#define SYNCFB_FEATURE_BLOCK_REQUEST 1024 -#define SYNCFB_FEATURE_FREQDIV2 2048 +#define SYNCFB_FEATURE_DEINTERLACE 16 +#define SYNCFB_FEATURE_PROCAMP 32 +#define SYNCFB_FEATURE_TRANSITIONS 64 +#define SYNCFB_FEATURE_COLKEY 128 +#define SYNCFB_FEATURE_MIRROR_H 256 +#define SYNCFB_FEATURE_MIRROR_V 512 +#define SYNCFB_FEATURE_BLOCK_REQUEST 1024 +#define SYNCFB_FEATURE_FREQDIV2 2048 typedef struct syncfb_config_s @@ -107,7 +107,7 @@ typedef struct syncfb_config_s uint_32 buffers; /* RO, number of available buffers */ uint_32 buffer_size; /* RO, filled in by syncfb */ - uint_32 default_repeat; /* default repeat time for a single frame, can be overridden in syncfb_buffer_info_t */ + uint_32 default_repeat; /* default repeat time for a single frame, can be overridden in syncfb_buffer_info_t */ uint_32 src_width; /* source image width in pixel */ uint_32 src_height; /* source image height in pixel */ @@ -121,7 +121,7 @@ typedef struct syncfb_config_s uint_32 scale_filters; /* 0: no filtering, 255: all filters on */ uint_32 image_width; /* onscreen image width */ uint_32 image_height; /* onscreen image height */ - + /* if syncfb has FEATURE_CROP */ uint_32 src_crop_left; /* */ uint_32 src_crop_right; /* */ @@ -176,8 +176,8 @@ typedef struct syncfb_status_info_s uint_32 skip_field_cnt; /* skipped fields when fifo was about to fill up */ uint_32 request_frames; /* number of request_buffer calls */ - uint_32 commit_frames; /* number of commit_buffer calls */ - + uint_32 commit_frames; /* number of commit_buffer calls */ + uint_32 failed_requests; /* number of calls to request_buffer that failed */ uint_32 buffers_waiting; @@ -188,7 +188,7 @@ typedef struct syncfb_status_info_s -typedef struct syncfb_capability_s +typedef struct syncfb_capability_s { char name[64]; /* A name for the syncfb ... */ uint_32 palettes; /* supported palettes - see videodev.h for palettes, test the corresponding bit here */ diff --git a/src/video_out/video_out_vidix.c b/src/video_out/video_out_vidix.c index 9e3f870b1..618ce1023 100644 --- a/src/video_out/video_out_vidix.c +++ b/src/video_out/video_out_vidix.c @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -65,7 +65,7 @@ #ifdef HAVE_X11 #include "x11osd.h" #endif - + #define NUM_FRAMES 3 typedef struct vidix_driver_s vidix_driver_t; @@ -109,16 +109,16 @@ struct vidix_driver_s { uint32_t colourkey; int use_doublebuffer; - + int supports_yv12; - + pthread_mutex_t mutex; vidix_property_t props[VO_NUM_PROPERTIES]; uint32_t capabilities; int visual_type; - + /* X11 related stuff */ #ifdef HAVE_X11 Display *display; @@ -128,17 +128,17 @@ struct vidix_driver_s { x11osd *xoverlay; int ovl_changed; #endif - + /* fb related stuff */ int fb_width; int fb_height; - + int depth; vo_scale_t sc; int delivered_format; - + xine_t *xine; alphablend_t alphablend_extra_data; @@ -151,7 +151,7 @@ typedef struct vidix_class_s { VDL_HANDLE vidix_handler; vidix_capability_t vidix_cap; - + xine_t *xine; } vidix_class_t; @@ -175,7 +175,7 @@ static void free_framedata(vidix_frame_t* frame) } static void write_frame_YUV420P2(vidix_driver_t* this, vidix_frame_t* frame) -{ +{ uint8_t* y = frame->vo_frame.base[0] + this->sc.displayed_xoffset + this->sc.displayed_yoffset*frame->vo_frame.pitches[0]; uint8_t* cb = frame->vo_frame.base[1] + this->sc.displayed_xoffset/2 + @@ -183,16 +183,16 @@ static void write_frame_YUV420P2(vidix_driver_t* this, vidix_frame_t* frame) uint8_t* cr = frame->vo_frame.base[2]+this->sc.displayed_xoffset/2 + this->sc.displayed_yoffset*frame->vo_frame.pitches[2]/2; uint8_t* dst8 = (this->vidix_mem + - this->vidix_play.offsets[this->next_frame] + + this->vidix_play.offsets[this->next_frame] + this->vidix_play.offset.y); - int h, w; - + int h, w; + for(h = 0; h < this->sc.displayed_height; h++) { xine_fast_memcpy(dst8, y, this->sc.displayed_width); y += frame->vo_frame.pitches[0]; dst8 += this->dstrides.y; } - + dst8 = (this->vidix_mem + this->vidix_play.offsets[this->next_frame] + this->vidix_play.offset.v); @@ -211,7 +211,7 @@ static void write_frame_sfb(vidix_driver_t* this, vidix_frame_t* frame) { uint8_t *base = this->vidix_mem+this->vidix_play.offsets[this->next_frame]; - switch(frame->format) { + switch(frame->format) { case XINE_IMGFMT_YUY2: yuy2_to_yuy2( /* src */ @@ -223,7 +223,7 @@ static void write_frame_sfb(vidix_driver_t* this, vidix_frame_t* frame) /* width x height */ this->sc.displayed_width, this->sc.displayed_height); break; - + case XINE_IMGFMT_YV12: { uint8_t* y = frame->vo_frame.base[0] + this->sc.displayed_xoffset + this->sc.displayed_yoffset*frame->vo_frame.pitches[0]; @@ -231,7 +231,7 @@ static void write_frame_sfb(vidix_driver_t* this, vidix_frame_t* frame) this->sc.displayed_yoffset*frame->vo_frame.pitches[1]/2; uint8_t* cr = frame->vo_frame.base[2] + this->sc.displayed_xoffset/2 + this->sc.displayed_yoffset*frame->vo_frame.pitches[2]/2; - + if(this->supports_yv12) { if(this->vidix_play.flags & VID_PLAY_INTERLEAVED_UV) write_frame_YUV420P2(this, frame); @@ -262,9 +262,9 @@ static void write_frame_sfb(vidix_driver_t* this, vidix_frame_t* frame) frame->vo_frame.progressive_frame); break; } - + default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: error. (unknown frame format %04x)\n", frame->format); break; } @@ -276,11 +276,11 @@ static void vidix_clean_output_area(vidix_driver_t *this) { if(this->visual_type == XINE_VISUAL_TYPE_X11) { #ifdef HAVE_X11 int i; - - XLockDisplay(this->display); - + + XLockDisplay(this->display); + XSetForeground(this->display, this->gc, BlackPixel(this->display, this->screen)); - + for( i = 0; i < 4; i++ ) { if( this->sc.border[i].w && this->sc.border[i].h ) { XFillRectangle(this->display, this->drawable, this->gc, @@ -288,15 +288,15 @@ static void vidix_clean_output_area(vidix_driver_t *this) { this->sc.border[i].w, this->sc.border[i].h); } } - + XSetForeground(this->display, this->gc, this->colourkey); XFillRectangle(this->display, this->drawable, this->gc, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height); - + if (this->xoverlay) { x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + XFlush(this->display); XUnlockDisplay(this->display); @@ -326,12 +326,12 @@ static void vidix_update_colourkey(vidix_driver_t *this) { default: break; } - + vidix_clean_output_area(this); - + vdlSetGrKeys(this->vidix_handler, &this->vidix_grkey); } - + static uint32_t vidix_get_capabilities (vo_driver_t *this_gen) { @@ -362,7 +362,7 @@ static void vidix_frame_dispose (vo_frame_t *vo_img) { vidix_frame_t *frame = (vidix_frame_t *) vo_img ; - free_framedata(frame); + free_framedata(frame); free (frame); } @@ -370,12 +370,12 @@ static vo_frame_t *vidix_alloc_frame (vo_driver_t *this_gen) { /* vidix_driver_t *this = (vidix_driver_t *) this_gen; */ vidix_frame_t *frame ; - frame = (vidix_frame_t *) xine_xmalloc (sizeof (vidix_frame_t)); + frame = (vidix_frame_t *) calloc(1, sizeof(vidix_frame_t)); if (!frame) return NULL; pthread_mutex_init (&frame->vo_frame.mutex, NULL); - + frame->vo_frame.base[0] = NULL; frame->vo_frame.base[1] = NULL; frame->vo_frame.base[2] = NULL; @@ -407,33 +407,33 @@ static void vidix_config_playback (vidix_driver_t *this) { uint32_t apitch; int err,i; - + _x_vo_scale_compute_output_size( &this->sc ); - + /* We require that the displayed xoffset and width are even. * To prevent displaying more than we're supposed to we round the * xoffset up and the width down */ this->sc.displayed_xoffset = (this->sc.displayed_xoffset+1) & ~1; this->sc.displayed_width = this->sc.displayed_width & ~1; - + /* For yv12 source displayed yoffset and height need to be even too */ if(this->delivered_format == XINE_IMGFMT_YV12) { this->sc.displayed_yoffset = (this->sc.displayed_yoffset+1) & ~1; this->sc.displayed_height = this->sc.displayed_height & ~1; } - + if( this->vidix_started > 0 ) { lprintf("video_out_vidix: overlay off\n"); vdlPlaybackOff(this->vidix_handler); } memset(&this->vidix_play,0,sizeof(vidix_playback_t)); - + if(this->delivered_format == XINE_IMGFMT_YV12 && this->supports_yv12) this->vidix_play.fourcc = IMGFMT_YV12; else this->vidix_play.fourcc = IMGFMT_YUY2; - + this->vidix_play.capability = this->vidix_cap.flags; /* every ;) */ this->vidix_play.blend_factor = 0; /* for now */ this->vidix_play.src.x = 0; @@ -449,7 +449,7 @@ static void vidix_config_playback (vidix_driver_t *this) { if((err=vdlConfigPlayback(this->vidix_handler,&this->vidix_play))!=0) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: Can't configure playback: %s\n",strerror(err)); this->vidix_started = -1; return; @@ -458,27 +458,27 @@ static void vidix_config_playback (vidix_driver_t *this) { lprintf("video_out_vidix: dga_addr = %p frame_size = %u frames = %u\n", this->vidix_play.dga_addr, this->vidix_play.frame_size, this->vidix_play.num_frames ); - + lprintf("video_out_vidix: offsets[0..2] = %u %u %u\n", this->vidix_play.offsets[0], this->vidix_play.offsets[1], this->vidix_play.offsets[2] ); - + lprintf("video_out_vidix: offset.y/u/v = %u/%u/%u\n", this->vidix_play.offset.y, this->vidix_play.offset.u, this->vidix_play.offset.v ); - + lprintf("video_out_vidix: src.x/y/w/h = %u/%u/%u/%u\n", this->vidix_play.src.x, this->vidix_play.src.y, this->vidix_play.src.w, this->vidix_play.src.h ); - + lprintf("video_out_vidix: dest.x/y/w/h = %u/%u/%u/%u\n", this->vidix_play.dest.x, this->vidix_play.dest.y, this->vidix_play.dest.w, this->vidix_play.dest.h ); - + lprintf("video_out_vidix: dest.pitch.y/u/v = %u/%u/%u\n", this->vidix_play.dest.pitch.y, this->vidix_play.dest.pitch.u, this->vidix_play.dest.pitch.v ); - + this->vidix_mem = this->vidix_play.dga_addr; this->next_frame = 0; @@ -502,7 +502,7 @@ static void vidix_config_playback (vidix_driver_t *this) { this->dstrides.y = (this->sc.displayed_width*2 + apitch) & ~apitch; break; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: error. (unknown frame format: %04x)\n", this->delivered_format); } @@ -517,7 +517,7 @@ static void vidix_update_frame_format (vo_driver_t *this_gen, double ratio, int format, int flags) { vidix_driver_t *this = (vidix_driver_t *) this_gen; vidix_frame_t *frame = (vidix_frame_t *) frame_gen; - + if ((frame->width != width) || (frame->height != height) || (frame->format != format)) { @@ -525,9 +525,9 @@ static void vidix_update_frame_format (vo_driver_t *this_gen, /* * (re-) allocate image */ - + free_framedata(frame); - + frame->width = width; frame->height = height; frame->format = format; @@ -548,15 +548,15 @@ static void vidix_update_frame_format (vo_driver_t *this_gen, frame->vo_frame.base[2] = NULL; break; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: error. (unknown frame format: %04x)\n", format); } - + if((format == XINE_IMGFMT_YV12 && (frame->vo_frame.base[0] == NULL || frame->vo_frame.base[1] == NULL || frame->vo_frame.base[2] == NULL)) || (format == XINE_IMGFMT_YUY2 && frame->vo_frame.base[0] == NULL)) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: error. (framedata allocation failed: out of memory)\n"); - + free_framedata(frame); } } @@ -564,7 +564,7 @@ static void vidix_update_frame_format (vo_driver_t *this_gen, frame->ratio = ratio; } -static void vidix_overlay_begin (vo_driver_t *this_gen, +static void vidix_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { vidix_driver_t *this = (vidix_driver_t *) this_gen; @@ -573,11 +573,11 @@ static void vidix_overlay_begin (vo_driver_t *this_gen, if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); - x11osd_clear(this->xoverlay); + x11osd_clear(this->xoverlay); XUnlockDisplay (this->display); } #endif - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -603,17 +603,17 @@ static void vidix_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v vidix_frame_t *frame = (vidix_frame_t *) frame_gen; vidix_driver_t *this = (vidix_driver_t *) this_gen; - + if (overlay->rle) { if( overlay->unscaled ) { #ifdef HAVE_X11 if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); - x11osd_blend(this->xoverlay, overlay); + x11osd_blend(this->xoverlay, overlay); XUnlockDisplay (this->display); } #endif - } else { + } else { if( frame->format == XINE_IMGFMT_YV12 ) _x_blend_yuv( frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); else @@ -649,25 +649,25 @@ static void vidix_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) - || (frame->ratio != this->sc.delivered_ratio) + || (frame->ratio != this->sc.delivered_ratio) || (frame->format != this->delivered_format ) ) { lprintf("video_out_vidix: change frame format\n"); - + this->sc.delivered_width = frame->width; this->sc.delivered_height = frame->height; this->sc.delivered_ratio = frame->ratio; this->delivered_format = frame->format; - + this->sc.crop_left = frame->vo_frame.crop_left; this->sc.crop_right = frame->vo_frame.crop_right; this->sc.crop_top = frame->vo_frame.crop_top; this->sc.crop_bottom = frame->vo_frame.crop_bottom; - + vidix_compute_ideal_size( this ); this->sc.force_redraw = 1; } - - /* + + /* * check if we have to reconfigure vidix because of * format/window position change */ @@ -692,7 +692,7 @@ static void vidix_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { static int vidix_get_property (vo_driver_t *this_gen, int property) { vidix_driver_t *this = (vidix_driver_t *) this_gen; - + switch (property) { case VO_PROP_WINDOW_WIDTH: this->props[property].value = this->sc.gui_width; @@ -713,7 +713,7 @@ static int vidix_get_property (vo_driver_t *this_gen, int property) { this->props[property].value = this->sc.output_yoffset; break; } - + lprintf ("video_out_vidix: property #%d = %d\n", property, this->props[property].value); @@ -726,91 +726,91 @@ static int vidix_set_property (vo_driver_t *this_gen, vidix_driver_t *this = (vidix_driver_t *) this_gen; int err; - + if ((value >= this->props[property].min) && (value <= this->props[property].max)) { this->props[property].value = value; - + if ( property == VO_PROP_ASPECT_RATIO) { lprintf("video_out_vidix: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); - + if(value == XINE_VO_ASPECT_NUM_RATIOS) value = this->props[property].value = XINE_VO_ASPECT_AUTO; - this->sc.user_ratio = value; + this->sc.user_ratio = value; vidix_compute_ideal_size (this); this->sc.force_redraw = 1; - } + } if ( property == VO_PROP_ZOOM_X ) { this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; vidix_compute_ideal_size (this); this->sc.force_redraw = 1; - } + } if ( property == VO_PROP_ZOOM_Y ) { this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; vidix_compute_ideal_size (this); this->sc.force_redraw = 1; - } - + } + if ( property == VO_PROP_HUE ) { this->vidix_eq.cap = VEQ_CAP_HUE; this->vidix_eq.hue = value; - + if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set hue: %s\n", strerror(err)); } - + if ( property == VO_PROP_SATURATION ) { this->vidix_eq.cap = VEQ_CAP_SATURATION; this->vidix_eq.saturation = value; - + if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set saturation: %s\n", strerror(err)); } - + if ( property == VO_PROP_BRIGHTNESS ) { this->vidix_eq.cap = VEQ_CAP_BRIGHTNESS; this->vidix_eq.brightness = value; - + if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set brightness: %s\n", strerror(err)); } - + if ( property == VO_PROP_CONTRAST ) { this->vidix_eq.cap = VEQ_CAP_CONTRAST; this->vidix_eq.contrast = value; - + if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq)) != 0) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set contrast: %s\n", strerror(err)); } } - + return value; } static void vidix_ckey_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) { - vidix_driver_t *this = (vidix_driver_t *) this_gen; - + vidix_driver_t *this = (vidix_driver_t *) this_gen; + if(strcmp(entry->key, "video.device.vidix_colour_key_red") == 0) { this->vidix_grkey.ckey.red = entry->num_value; } - + if(strcmp(entry->key, "video.device.vidix_colour_key_green") == 0) { this->vidix_grkey.ckey.green = entry->num_value; } - + if(strcmp(entry->key, "video.device.vidix_colour_key_blue") == 0) { this->vidix_grkey.ckey.blue = entry->num_value; } - + vidix_update_colourkey(this); this->sc.force_redraw = 1; } @@ -818,7 +818,7 @@ static void vidix_ckey_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) static void vidix_db_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) { - vidix_driver_t *this = (vidix_driver_t *) this_gen; + vidix_driver_t *this = (vidix_driver_t *) this_gen; this->use_doublebuffer = entry->num_value; this->sc.force_redraw = 1; @@ -828,16 +828,16 @@ static void vidix_db_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) { static void vidix_rgb_callback(vo_driver_t *this_gen, xine_cfg_entry_t *entry) { int err; vidix_driver_t *this = (vidix_driver_t *) this_gen; - + this->vidix_eq.cap = VEQ_CAP_RGB_INTENSITY; - + if(!strcmp(entry->key, "video.output.vidix_red_intensity")) { this->vidix_eq.red_intensity = entry->num_value; } else if(!strcmp(entry->key, "video.output.vidix_green_intensity")) { this->vidix_eq.green_intensity = entry->num_value; } else if(!strcmp(entry->key, "video.output.vidix_blue_intensity")) { this->vidix_eq.blue_intensity = entry->num_value; - } + } if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq))) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set rgb intensity: %s\n", strerror(err)); @@ -860,12 +860,12 @@ static int vidix_gui_data_exchange (vo_driver_t *this_gen, vidix_driver_t *this = (vidix_driver_t *) this_gen; pthread_mutex_lock(&this->mutex); - + switch (data_type) { case XINE_GUI_SEND_DRAWABLE_CHANGED: lprintf ("video_out_vidix: GUI_DATA_EX_DRAWABLE_CHANGED\n"); - + if(this->visual_type == XINE_VISUAL_TYPE_X11) { #ifdef HAVE_X11 this->drawable = (Drawable) data; @@ -879,7 +879,7 @@ static int vidix_gui_data_exchange (vo_driver_t *this_gen, #endif } break; - + case XINE_GUI_SEND_EXPOSE_EVENT: lprintf ("video_out_vidix: GUI_DATA_EX_EXPOSE_EVENT\n"); vidix_clean_output_area(this); @@ -908,7 +908,7 @@ static int vidix_gui_data_exchange (vo_driver_t *this_gen, rect->h = y2-y1; } break; - + default: ret = -1; } @@ -916,7 +916,7 @@ static int vidix_gui_data_exchange (vo_driver_t *this_gen, return ret; } - + static void vidix_exit (vo_driver_t *this_gen) { vidix_driver_t *this = (vidix_driver_t *) this_gen; @@ -937,7 +937,7 @@ static void vidix_exit (vo_driver_t *this_gen) { #endif _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -946,30 +946,30 @@ static vidix_driver_t *open_plugin (video_driver_class_t *class_gen) { config_values_t *config = class->config; vidix_driver_t *this; int err; - - this = (vidix_driver_t *) xine_xmalloc (sizeof (vidix_driver_t)); + + this = (vidix_driver_t *) calloc(1, sizeof(vidix_driver_t)); if (!this) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + pthread_mutex_init (&this->mutex, NULL); this->vidix_handler = class->vidix_handler; this->vidix_cap = class->vidix_cap; _x_vo_scale_init( &this->sc, 1, /*this->vidix_cap.flags & FLAG_UPSCALER,*/ 0, config ); - + this->xine = class->xine; this->config = config; - + this->got_frame_data = 0; this->capabilities = VO_CAP_CROP; /* Find what equalizer flags are supported */ if(this->vidix_cap.flags & FLAG_EQUALIZER) { if((err = vdlPlaybackGetEq(this->vidix_handler, &this->vidix_eq)) != 0) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: couldn't get equalizer capabilities: %s\n", strerror(err)); } else { if(this->vidix_eq.cap & VEQ_CAP_BRIGHTNESS) { @@ -977,48 +977,48 @@ static vidix_driver_t *open_plugin (video_driver_class_t *class_gen) { this->props[VO_PROP_BRIGHTNESS].min = -1000; this->props[VO_PROP_BRIGHTNESS].max = 1000; } - + if(this->vidix_eq.cap & VEQ_CAP_CONTRAST) { this->props[VO_PROP_CONTRAST].value = 0; this->props[VO_PROP_CONTRAST].min = -1000; this->props[VO_PROP_CONTRAST].max = 1000; } - + if(this->vidix_eq.cap & VEQ_CAP_SATURATION) { this->props[VO_PROP_SATURATION].value = 0; this->props[VO_PROP_SATURATION].min = -1000; this->props[VO_PROP_SATURATION].max = 1000; } - + if(this->vidix_eq.cap & VEQ_CAP_HUE) { this->props[VO_PROP_HUE].value = 0; this->props[VO_PROP_HUE].min = -1000; this->props[VO_PROP_HUE].max = 1000; } - + if(this->vidix_eq.cap & VEQ_CAP_RGB_INTENSITY) { this->vidix_eq.red_intensity = config->register_range(config, - "video.output.vidix_red_intensity", 0, -1000, 1000, + "video.output.vidix_red_intensity", 0, -1000, 1000, _("red intensity"), _("The intensity of the red colour components."), 10, - (void*) vidix_rgb_callback, this); + (void*) vidix_rgb_callback, this); this->vidix_eq.green_intensity = config->register_range(config, - "video.output.vidix_green_intensity", 0, -1000, 1000, + "video.output.vidix_green_intensity", 0, -1000, 1000, _("green intensity"), _("The intensity of the green colour components."), 10, (void*) vidix_rgb_callback, this); this->vidix_eq.blue_intensity = config->register_range(config, - "video.output.vidix_blue_intensity", 0, -1000, 1000, + "video.output.vidix_blue_intensity", 0, -1000, 1000, _("blue intensity"), _("The intensity of the blue colour components."), 10, (void*) vidix_rgb_callback, this); - + if((err = vdlPlaybackSetEq(this->vidix_handler, &this->vidix_eq))) - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: can't set rgb intensity: %s\n", strerror(err)); - } + } } } - + /* Configuration for double buffering */ this->use_doublebuffer = config->register_bool(config, "video.device.vidix_double_buffer", 1, _("enable double buffering"), @@ -1026,20 +1026,20 @@ static vidix_driver_t *open_plugin (video_driver_class_t *class_gen) { "screen (\"vertical retrace\"). This eliminates flickering and tearing artifacts, but will use " "more graphics memory."), 20, (void*) vidix_db_callback, this); - + /* Set up remaining props */ this->props[VO_PROP_ASPECT_RATIO].value = XINE_VO_ASPECT_AUTO; this->props[VO_PROP_ASPECT_RATIO].min = 0; this->props[VO_PROP_ASPECT_RATIO].max = XINE_VO_ASPECT_NUM_RATIOS; - + this->props[VO_PROP_ZOOM_X].value = 100; this->props[VO_PROP_ZOOM_X].min = XINE_VO_ZOOM_MIN; this->props[VO_PROP_ZOOM_X].max = XINE_VO_ZOOM_MAX; - + this->props[VO_PROP_ZOOM_Y].value = 100; this->props[VO_PROP_ZOOM_Y].min = XINE_VO_ZOOM_MIN; this->props[VO_PROP_ZOOM_Y].max = XINE_VO_ZOOM_MAX; - + this->vo_driver.get_capabilities = vidix_get_capabilities; this->vo_driver.alloc_frame = vidix_alloc_frame; this->vo_driver.update_frame_format = vidix_update_frame_format; @@ -1060,23 +1060,23 @@ static vidix_driver_t *open_plugin (video_driver_class_t *class_gen) { static void query_fourccs (vidix_driver_t *this) { vidix_fourcc_t vidix_fourcc; int err; - + /* Detect if YUY2 is supported */ memset(&vidix_fourcc, 0, sizeof(vidix_fourcc_t)); vidix_fourcc.fourcc = IMGFMT_YUY2; vidix_fourcc.depth = this->depth; - + if((err = vdlQueryFourcc(this->vidix_handler, &vidix_fourcc)) == 0) { this->capabilities |= VO_CAP_YUY2; xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_vidix: adaptor supports the yuy2 format\n")); } - + /* Detect if YV12 is supported - we always support yv12 but we need to know if we have to convert */ this->capabilities |= VO_CAP_YV12; vidix_fourcc.fourcc = IMGFMT_YV12; - + if((err = vdlQueryFourcc(this->vidix_handler, &vidix_fourcc)) == 0) { this->supports_yv12 = 1; xprintf(this->xine, XINE_VERBOSITY_LOG, @@ -1088,14 +1088,14 @@ static void query_fourccs (vidix_driver_t *this) { static void *init_class (xine_t *xine, void *visual_gen) { vidix_class_t *this; int err; - - this = (vidix_class_t *) xine_xmalloc (sizeof (vidix_class_t)); + + this = (vidix_class_t *) calloc(1, sizeof(vidix_class_t)); if (!this) return NULL; - + if(vdlGetVersion() != VIDIX_VERSION) { - xprintf(xine, XINE_VERBOSITY_LOG, + xprintf(xine, XINE_VERBOSITY_LOG, _("video_out_vidix: You have wrong version of VIDIX library\n")); free(this); return NULL; @@ -1110,18 +1110,18 @@ static void *init_class (xine_t *xine, void *visual_gen) { } if((err=vdlGetCapability(this->vidix_handler,&this->vidix_cap)) != 0) { - xprintf(xine, XINE_VERBOSITY_DEBUG, + xprintf(xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: Couldn't get capability: %s\n",strerror(err)); free(this); return NULL; } - xprintf(xine, XINE_VERBOSITY_LOG, + xprintf(xine, XINE_VERBOSITY_LOG, _("video_out_vidix: using driver: %s by %s\n"), this->vidix_cap.name, this->vidix_cap.author); this->xine = xine; this->config = xine->config; - + return this; } @@ -1138,63 +1138,63 @@ static vo_driver_t *vidix_open_plugin (video_driver_class_t *class_gen, const vo vidix_driver_t *this = open_plugin(class_gen); config_values_t *config = this->config; x11_visual_t *visual = (x11_visual_t *) visual_gen; - XWindowAttributes window_attributes; - + XWindowAttributes window_attributes; + this->visual_type = XINE_VISUAL_TYPE_X11; - + this->display = visual->display; this->screen = visual->screen; this->drawable = visual->d; this->gc = XCreateGC(this->display, this->drawable, 0, NULL); this->xoverlay = NULL; this->ovl_changed = 0; - + XGetWindowAttributes(this->display, this->drawable, &window_attributes); this->sc.gui_width = window_attributes.width; this->sc.gui_height = window_attributes.height; this->depth = window_attributes.depth; - + this->sc.frame_output_cb = visual->frame_output_cb; this->sc.user_data = visual->user_data; - - /* We'll assume all drivers support colour keying (which they do + + /* We'll assume all drivers support colour keying (which they do at the moment) */ this->vidix_grkey.ckey.op = CKEY_TRUE; - + /* Colour key components */ this->vidix_grkey.ckey.red = config->register_range(config, - "video.device.vidix_colour_key_red", 255, 0, 255, + "video.device.vidix_colour_key_red", 255, 0, 255, _("video overlay colour key red component"), _("The colour key is used to tell the graphics card where to overlay the video image. " "Try different values, if you experience windows becoming transparent."), 20, - (void*) vidix_ckey_callback, this); - + (void*) vidix_ckey_callback, this); + this->vidix_grkey.ckey.green = config->register_range(config, - "video.device.vidix_colour_key_green", 0, 0, 255, + "video.device.vidix_colour_key_green", 0, 0, 255, _("video overlay colour key green component"), _("The colour key is used to tell the graphics card where to overlay the video image. " "Try different values, if you experience windows becoming transparent."), 20, - (void*) vidix_ckey_callback, this); - + (void*) vidix_ckey_callback, this); + this->vidix_grkey.ckey.blue = config->register_range(config, - "video.device.vidix_colour_key_blue", 255, 0, 255, + "video.device.vidix_colour_key_blue", 255, 0, 255, _("video overlay colour key blue component"), _("The colour key is used to tell the graphics card where to overlay the video image. " "Try different values, if you experience windows becoming transparent."), 20, - (void*) vidix_ckey_callback, this); - + (void*) vidix_ckey_callback, this); + vidix_update_colourkey(this); query_fourccs(this); XLockDisplay (this->display); - if(this->colourkey) { + if(this->colourkey) { this->xoverlay = x11osd_create (this->xine, this->display, this->screen, this->drawable, X11OSD_COLORKEY); if(this->xoverlay) x11osd_colorkey(this->xoverlay, this->colourkey, &this->sc); } else { - this->xoverlay = x11osd_create (this->xine, this->display, this->screen, + this->xoverlay = x11osd_create (this->xine, this->display, this->screen, this->drawable, X11OSD_SHAPED); } XUnlockDisplay (this->display); @@ -1216,14 +1216,14 @@ static char* vidix_get_description (video_driver_class_t *this_gen) { static void *vidix_init_class (xine_t *xine, void *visual_gen) { vidix_class_t *this = init_class (xine, visual_gen); - + if(this) { this->driver_class.open_plugin = vidix_open_plugin; this->driver_class.get_identifier = vidix_get_identifier; this->driver_class.get_description = vidix_get_description; this->driver_class.dispose = dispose_class; } - + return this; } @@ -1240,9 +1240,9 @@ static vo_driver_t *vidixfb_open_plugin (video_driver_class_t *class_gen, const char *device; int fd; struct fb_var_screeninfo fb_var; - + this->visual_type = XINE_VISUAL_TYPE_FB; - + /* Register config option for fb device */ device = config->register_filename(config, "video.device.vidixfb_device", "/dev/fb0", XINE_CONFIG_STRING_IS_DEVICE_NAME, _("framebuffer device name"), @@ -1251,45 +1251,45 @@ static vo_driver_t *vidixfb_open_plugin (video_driver_class_t *class_gen, const "can be used to fill this file with arbitrary content. So you should be careful that " "the value you enter really is a proper framebuffer device."), XINE_CONFIG_SECURITY, NULL, NULL); - + /* Open fb device for reading */ if((fd = open("/dev/fb0", O_RDONLY)) < 0) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: unable to open frame buffer device \"%s\": %s\n", device, strerror(errno)); return NULL; } - + /* Read screen info */ if(ioctl(fd, FBIOGET_VSCREENINFO, &fb_var) != 0) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_vidix: error in ioctl FBIOGET_VSCREENINFO: %s", strerror(errno)); close(fd); return NULL; } - + /* Store screen bpp and dimensions */ this->depth = fb_var.bits_per_pixel; this->fb_width = fb_var.xres; this->fb_height = fb_var.yres; - + /* Close device */ close(fd); - + this->sc.frame_output_cb = vidixfb_frame_output_cb; this->sc.user_data = this; - + /* Make sure colour keying is turned off */ this->vidix_grkey.ckey.op = CKEY_FALSE; vdlSetGrKeys(this->vidix_handler, &this->vidix_grkey); - + query_fourccs(this); - + return &this->vo_driver; } static char* vidixfb_get_identifier (video_driver_class_t *this_gen) { return "vidixfb"; -} +} static char* vidixfb_get_description (video_driver_class_t *this_gen) { return _("xine video output plugin using libvidix for linux frame buffer"); @@ -1298,14 +1298,14 @@ static char* vidixfb_get_description (video_driver_class_t *this_gen) { static void *vidixfb_init_class (xine_t *xine, void *visual_gen) { vidix_class_t *this = init_class (xine, visual_gen); - + if(this) { this->driver_class.open_plugin = vidixfb_open_plugin; this->driver_class.get_identifier = vidixfb_get_identifier; this->driver_class.get_description = vidixfb_get_description; this->driver_class.dispose = dispose_class; } - + return this; } @@ -1320,7 +1320,7 @@ static const vo_info_t vo_info_vidixfb = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ #ifdef HAVE_X11 { PLUGIN_VIDEO_OUT, 21, "vidix", XINE_VERSION_CODE, &vo_info_vidix, vidix_init_class }, #endif diff --git a/src/video_out/video_out_xcbshm.c b/src/video_out/video_out_xcbshm.c index 2ac579555..c93cf8c1e 100644 --- a/src/video_out/video_out_xcbshm.c +++ b/src/video_out/video_out_xcbshm.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2003, 2007 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -23,7 +23,7 @@ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de> - * + * * ported to xcb by Christoph Pfister - Feb 2007 */ @@ -71,7 +71,7 @@ typedef struct { int flags; vo_scale_t sc; - + uint8_t *image; int bytes_per_line; xcb_shm_seg_t shmseg; @@ -96,7 +96,7 @@ typedef struct { int bpp; int scanline_pad; int use_shm; - + int yuv2rgb_brightness; int yuv2rgb_contrast; int yuv2rgb_saturation; @@ -104,7 +104,7 @@ typedef struct { yuv2rgb_factory_t *yuv2rgb_factory; vo_scale_t sc; - + xshm_frame_t *cur_frame; xcbosd *xoverlay; int ovl_changed; @@ -126,7 +126,7 @@ typedef struct { /* - * allocate an XImage, try XShm first but fall back to + * allocate an XImage, try XShm first but fall back to * plain X11 if XShm should fail */ static void create_ximage(xshm_driver_t *this, xshm_frame_t *frame, int width, int height) @@ -151,9 +151,9 @@ static void create_ximage(xshm_driver_t *this, xshm_frame_t *frame, int width, i "video_out_xcbshm: => not using MIT Shared Memory extension.\n"), strerror(errno)); goto shm_fail1; } - + frame->image = shmat(shmid, 0, 0); - + if (frame->image == ((void *) -1)) { xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xcbshm: shared memory error (address error) when allocating image \n" @@ -173,10 +173,10 @@ static void create_ximage(xshm_driver_t *this, xshm_frame_t *frame, int width, i goto shm_fail3; } - /* + /* * Now that the Xserver has learned about and attached to the * shared memory segment, delete it. It's actually deleted by - * the kernel when all users of that segment have detached from + * the kernel when all users of that segment have detached from * it. Gives an automatic shared memory cleanup in case we crash. */ @@ -229,10 +229,10 @@ static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */ - - vo_img->proc_called = 1; - - if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + + vo_img->proc_called = 1; + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) { /* we don't support crop, so don't even waste cpu cycles. @@ -240,7 +240,7 @@ static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { */ return; } - + lprintf ("copy... (format %d)\n", frame->format); if (frame->format == XINE_IMGFMT_YV12) @@ -249,7 +249,7 @@ static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { else frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0]); - + lprintf ("copy...done\n"); } @@ -295,7 +295,7 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { xshm_frame_t *frame; xshm_driver_t *this = (xshm_driver_t *) this_gen; - frame = (xshm_frame_t *) xine_xmalloc (sizeof (xshm_frame_t)); + frame = (xshm_frame_t *) calloc(1, sizeof(xshm_frame_t)); if (!frame) return NULL; @@ -306,10 +306,10 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { /* * supply required functions/fields */ - + frame->vo_frame.proc_slice = xshm_frame_proc_slice; frame->vo_frame.proc_frame = NULL; - frame->vo_frame.field = xshm_frame_field; + frame->vo_frame.field = xshm_frame_field; frame->vo_frame.dispose = xshm_frame_dispose; frame->vo_frame.driver = this_gen; @@ -369,7 +369,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, frame->sc.video_pixel_aspect, &gui_width, &gui_height, &gui_pixel_aspect); - + /* find out if we need to adapt this frame */ do_adapt = 0; @@ -394,7 +394,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, frame->sc.user_ratio = this->sc.user_ratio; xshm_compute_ideal_size (this, frame); - + /* now we have updated video_aspect_pixel we use the callback */ /* again to obtain the correct gui_width and gui_height values. */ frame->sc.dest_size_cb (frame->sc.user_data, width, height, @@ -402,20 +402,20 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, &gui_width, &gui_height, &gui_pixel_aspect); } - + if ((frame->sc.gui_width != gui_width) || (frame->sc.gui_height != gui_height) || do_adapt) { - + do_adapt = 1; frame->sc.gui_width = gui_width; frame->sc.gui_height = gui_height; - + xshm_compute_rgb_size (this, frame); - + lprintf ("gui_size has changed => adapt\n"); } - + /* ok, now do what we have to do */ @@ -469,7 +469,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, lprintf ("stripe out_ht=%i, deliv_ht=%i\n", frame->sc.output_height, frame->sc.delivered_height); - /* + /* * set up colorspace converter */ @@ -525,7 +525,7 @@ static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overla } } -static void xshm_overlay_begin (vo_driver_t *this_gen, +static void xshm_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -536,7 +536,7 @@ static void xshm_overlay_begin (vo_driver_t *this_gen, xcbosd_clear(this->xoverlay); pthread_mutex_unlock(&this->main_mutex); } - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -553,7 +553,7 @@ static void xshm_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { this->ovl_changed = 0; } -static void xshm_overlay_blend (vo_driver_t *this_gen, +static void xshm_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { xshm_driver_t *this = (xshm_driver_t *) this_gen; xshm_frame_t *frame = (xshm_frame_t *) frame_gen; @@ -569,7 +569,7 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, } else { if (!overlay->rgb_clut || !overlay->hili_rgb_clut) xshm_overlay_clut_yuv2rgb (this, overlay, frame); - + switch (this->bpp) { case 16: _x_blend_rgb16(frame->image, overlay, @@ -590,7 +590,7 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, &this->alphablend_extra_data); break; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "xine-lib:video_out_xcbshm:xshm_overlay_blend: Cannot blend bpp:%i\n", this->bpp); /* it should never get here, unless a user tries to play in bpp:8 */ break; @@ -603,11 +603,11 @@ static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) { int i; xcb_rectangle_t rects[4]; int rects_count = 0; - + memcpy( this->sc.border, frame->sc.border, sizeof(this->sc.border) ); - + pthread_mutex_lock(&this->main_mutex); - + for( i = 0; i < 4; i++ ) { if( this->sc.border[i].w && this->sc.border[i].h ) rects[rects_count].x = this->sc.border[i].x; @@ -624,7 +624,7 @@ static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) { xcbosd_resize(this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + pthread_mutex_unlock(&this->main_mutex); } @@ -636,15 +636,15 @@ static int xshm_redraw_needed (vo_driver_t *this_gen) { this->sc.delivered_height = this->cur_frame->sc.delivered_height; this->sc.delivered_width = this->cur_frame->sc.delivered_width; this->sc.video_pixel_aspect = this->cur_frame->sc.video_pixel_aspect; - if( _x_vo_scale_redraw_needed( &this->sc ) ) { + if( _x_vo_scale_redraw_needed( &this->sc ) ) { clean_output_area (this, this->cur_frame); ret = 1; } - } + } else ret = 1; - + return ret; } @@ -657,22 +657,22 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { frame->vo_frame.id, frame->sc.output_width, frame->sc.output_height); - /* + /* * tell gui that we are about to display a frame, * ask for offset */ - + this->sc.delivered_height = frame->sc.delivered_height; this->sc.delivered_width = frame->sc.delivered_width; this->sc.video_pixel_aspect = frame->sc.video_pixel_aspect; - if( _x_vo_scale_redraw_needed( &this->sc ) ) { + if( _x_vo_scale_redraw_needed( &this->sc ) ) { clean_output_area (this, frame); } - + if (this->cur_frame) { - if ( (this->cur_frame->sc.output_width != frame->sc.output_width) + if ( (this->cur_frame->sc.output_width != frame->sc.output_width) || (this->cur_frame->sc.output_height != frame->sc.output_height) || (this->cur_frame->sc.output_xoffset != frame->sc.output_xoffset) || (this->cur_frame->sc.output_yoffset != frame->sc.output_yoffset) ) @@ -682,10 +682,10 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { } this->cur_frame = frame; - + pthread_mutex_lock(&this->main_mutex); lprintf ("display locked...\n"); - + if (frame->shmseg) { lprintf ("put image (shm)\n"); @@ -736,14 +736,14 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_OUTPUT_YOFFSET: return this->cur_frame->sc.output_yoffset; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xcbshm: tried to get unsupported property %d\n", property); } return 0; } -static int xshm_set_property (vo_driver_t *this_gen, +static int xshm_set_property (vo_driver_t *this_gen, int property, int value) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -752,7 +752,7 @@ static int xshm_set_property (vo_driver_t *this_gen, if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->sc.user_ratio = value; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xcbshm: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); } else if (property == VO_PROP_BRIGHTNESS) { @@ -786,7 +786,7 @@ static int xshm_set_property (vo_driver_t *this_gen, this->sc.force_redraw = 1; } else { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xcbshm: tried to set unsupported property %d\n", property); } @@ -812,7 +812,7 @@ static void xshm_get_property_min_max (vo_driver_t *this_gen, } } -static int xshm_gui_data_exchange (vo_driver_t *this_gen, +static int xshm_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -823,17 +823,17 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, #endif case XINE_GUI_SEND_EXPOSE_EVENT: - + lprintf ("expose event\n"); if (this->cur_frame) { xcb_expose_event_t *xev = (xcb_expose_event_t *) data; - + if (xev && xev->count == 0) { int i; xcb_rectangle_t rects[4]; int rects_count = 0; - + pthread_mutex_lock(&this->main_mutex); if (this->cur_frame->shmseg) xcb_shm_put_image(this->connection, this->window, this->gc, this->cur_frame->sc.output_width, @@ -868,7 +868,7 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, } } break; - + case XINE_GUI_SEND_DRAWABLE_CHANGED: this->window = (xcb_window_t) data; @@ -887,7 +887,7 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, if (this->cur_frame) { x11_rectangle_t *rect = data; int x1, y1, x2, y2; - + _x_vo_scale_translate_gui2video(&this->cur_frame->sc, rect->x, rect->y, &x1, &y1); @@ -910,16 +910,16 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, static void xshm_dispose (vo_driver_t *this_gen) { xshm_driver_t *this = (xshm_driver_t *) this_gen; - + if (this->cur_frame) this->cur_frame->vo_frame.dispose (&this->cur_frame->vo_frame); this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); - + pthread_mutex_lock(&this->main_mutex); xcb_free_gc(this->connection, this->gc); pthread_mutex_unlock(&this->main_mutex); - + if( this->xoverlay ) { pthread_mutex_lock(&this->main_mutex); xcbosd_destroy(this->xoverlay); @@ -929,7 +929,7 @@ static void xshm_dispose (vo_driver_t *this_gen) { pthread_mutex_destroy(&this->main_mutex); _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -1014,8 +1014,8 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void xcb_get_geometry_reply_t *geometry_reply; const xcb_query_extension_reply_t *query_extension_reply; - - this = (xshm_driver_t *) xine_xmalloc (sizeof (xshm_driver_t)); + + this = (xshm_driver_t *) calloc(1, sizeof(xshm_driver_t)); if (!this) return NULL; @@ -1023,7 +1023,7 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void pthread_mutex_init(&this->main_mutex, NULL); _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->connection = visual->connection; this->screen = visual->screen; this->window = visual->window; @@ -1032,15 +1032,15 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void this->sc.frame_output_cb = visual->frame_output_cb; this->sc.dest_size_cb = visual->dest_size_cb; this->sc.user_data = visual->user_data; - + this->sc.user_ratio = XINE_VO_ASPECT_AUTO; - + this->cur_frame = NULL; this->gc = xcb_generate_id(this->connection); xcb_create_gc(this->connection, this->gc, this->window, XCB_GC_FOREGROUND, &this->screen->black_pixel); this->xoverlay = NULL; this->ovl_changed = 0; - + this->xine = class->xine; this->vo_driver.get_capabilities = xshm_get_capabilities; @@ -1108,7 +1108,7 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void query_extension_reply = xcb_get_extension_data(this->connection, &xcb_shm_id); if (query_extension_reply && query_extension_reply->present) { this->use_shm = 1; - } + } else { xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xcbshm: MIT shared memory extension not present on display.\n")); @@ -1147,7 +1147,7 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void */ cpu_byte_order = htonl(1) == 1 ? XCB_IMAGE_ORDER_MSB_FIRST : XCB_IMAGE_ORDER_LSB_FIRST; swapped = cpu_byte_order != image_byte_order; - + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xcbshm: video mode depth is %d (%d bpp), %s, %sswapped,\n" "\tred: %08x, green: %08x, blue: %08x\n", @@ -1209,16 +1209,16 @@ static vo_driver_t *xshm_open_plugin(video_driver_class_t *class_gen, const void } if (!mode) { - xprintf (this->xine, XINE_VERBOSITY_LOG, + xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_xcbshm: your video mode was not recognized, sorry :-(\n")); return NULL; } - + this->yuv2rgb_brightness = 0; this->yuv2rgb_contrast = 128; this->yuv2rgb_saturation = 128; - - this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, + + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, this->yuv2rgb_cmap); this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, this->yuv2rgb_brightness, @@ -1250,7 +1250,7 @@ static void xshm_dispose_class (video_driver_class_t *this_gen) { } static void *xshm_init_class (xine_t *xine, void *visual_gen) { - xshm_class_t *this = (xshm_class_t *) xine_xmalloc (sizeof (xshm_class_t)); + xshm_class_t *this = (xshm_class_t *) calloc(1, sizeof(xshm_class_t)); this->driver_class.open_plugin = xshm_open_plugin; this->driver_class.get_identifier = xshm_get_identifier; @@ -1274,7 +1274,7 @@ static const vo_info_t vo_info_xshm = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/video_out/video_out_xcbxv.c b/src/video_out/video_out_xcbxv.c index 18ab5c6fb..b3a141e61 100644 --- a/src/video_out/video_out_xcbxv.c +++ b/src/video_out/video_out_xcbxv.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004, 2007 the xine project + * Copyright (C) 2000-2004, 2007-2008 the xine project * * This file is part of xine, a free video player. * @@ -65,6 +65,7 @@ #include "xineutils.h" #include "vo_scale.h" #include "xcbosd.h" +#include "xv_common.h" typedef struct xv_driver_s xv_driver_t; @@ -137,6 +138,8 @@ struct xv_driver_s { int use_colorkey; uint32_t colorkey; + int sync_is_vsync; + /* hold initial port attributes values to restore on exit */ xine_list_t *port_attributes; @@ -155,6 +158,10 @@ typedef struct { xine_t *xine; } xv_class_t; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; + static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -186,10 +193,10 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { /* xv_driver_t *this = (xv_driver_t *) this_gen; */ xv_frame_t *frame ; - frame = (xv_frame_t *) xine_xmalloc (sizeof (xv_frame_t)); + frame = (xv_frame_t *) calloc(1, sizeof(xv_frame_t)); if (!frame) return NULL; - + pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* @@ -373,7 +380,7 @@ static void xv_update_frame_format (vo_driver_t *this_gen, if(format == XINE_IMGFMT_YUY2) { frame->vo_frame.pitches[0] = frame->xv_pitches[0]; frame->vo_frame.base[0] = frame->image + frame->xv_offsets[0]; - } + } else { frame->vo_frame.pitches[0] = frame->xv_pitches[0]; frame->vo_frame.pitches[1] = frame->xv_pitches[2]; @@ -411,7 +418,7 @@ static void xv_deinterlace_frame (xv_driver_t *this) { if(this->deinterlace_frame.image) dispose_ximage(this, &this->deinterlace_frame); - + create_ximage(this, &this->deinterlace_frame, frame->width, frame->height / xvscaling, frame->format); this->deinterlace_frame.width = frame->width; this->deinterlace_frame.height = frame->height; @@ -432,7 +439,7 @@ static void xv_deinterlace_frame (xv_driver_t *this) { for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image + frame->width*frame->height; + recent_bitmaps[i] = this->recent_frames[i]->image + this->deinterlace_frame.xv_width*frame->height; else recent_bitmaps[i] = NULL; @@ -532,12 +539,12 @@ static void xv_clean_output_area (xv_driver_t *this) { this->sc.output_width, this->sc.output_height }; xcb_poly_fill_rectangle(this->connection, this->window, this->gc, 1, &rectangle); } - + if (this->xoverlay) { xcbosd_resize(this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + pthread_mutex_unlock(&this->main_mutex); } @@ -568,7 +575,7 @@ static void xv_compute_output_size (xv_driver_t *this) { } } -static void xv_overlay_begin (vo_driver_t *this_gen, +static void xv_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -579,7 +586,7 @@ static void xv_overlay_begin (vo_driver_t *this_gen, xcbosd_clear(this->xoverlay); pthread_mutex_unlock(&this->main_mutex); } - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -596,7 +603,7 @@ static void xv_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { this->ovl_changed = 0; } -static void xv_overlay_blend (vo_driver_t *this_gen, +static void xv_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; @@ -610,11 +617,11 @@ static void xv_overlay_blend (vo_driver_t *this_gen, } } else { if (frame->format == XINE_IMGFMT_YV12) - _x_blend_yuv(frame->vo_frame.base, overlay, + _x_blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); else - _x_blend_yuy2(frame->vo_frame.base[0], overlay, + _x_blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0], &this->alphablend_extra_data); } @@ -658,7 +665,7 @@ static int xv_redraw_needed (vo_driver_t *this_gen) { this->sc.delivered_height = this->cur_frame->height; this->sc.delivered_width = this->cur_frame->width; this->sc.delivered_ratio = this->cur_frame->ratio; - + this->sc.crop_left = this->cur_frame->vo_frame.crop_left; this->sc.crop_right = this->cur_frame->vo_frame.crop_right; this->sc.crop_top = this->cur_frame->vo_frame.crop_top; @@ -687,7 +694,7 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { /* printf ("video_out_xcbxv: xv_display_frame...\n"); */ - + /* * queue frames (deinterlacing) * free old frames @@ -788,7 +795,7 @@ static int xv_get_property (vo_driver_t *this_gen, int property) { static void xv_property_callback (void *property_gen, xine_cfg_entry_t *entry) { xv_property_t *property = (xv_property_t *) property_gen; xv_driver_t *this = property->this; - + pthread_mutex_lock(&this->main_mutex); xcb_xv_set_port_attribute(this->connection, this->xv_port, property->atom, entry->num_value); @@ -822,7 +829,7 @@ static int xv_set_property (vo_driver_t *this_gen, this->props[property].entry->num_value = this->props[property].value; return this->props[property].value; - } + } else { switch (property) { @@ -836,13 +843,13 @@ static int xv_set_property (vo_driver_t *this_gen, xv_compute_output_size (this); } break; - + case VO_PROP_ASPECT_RATIO: if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->props[property].value = value; - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xcbxv: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value); this->sc.user_ratio = value; @@ -856,7 +863,7 @@ static int xv_set_property (vo_driver_t *this_gen, this->props[property].value = value; xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xcbxv: VO_PROP_ZOOM_X = %d\n", this->props[property].value); - + this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; xv_compute_ideal_size (this); @@ -948,7 +955,7 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, if(this->xoverlay) xcbosd_expose(this->xoverlay); - + xcb_flush(this->connection); pthread_mutex_unlock(&this->main_mutex); } @@ -1006,7 +1013,7 @@ static void xv_store_port_attribute(xv_driver_t *this, char *name) { xcb_xv_get_port_attribute_cookie_t get_attribute_cookie; xcb_xv_get_port_attribute_reply_t *get_attribute_reply; - + pthread_mutex_lock(&this->main_mutex); atom_cookie = xcb_intern_atom(this->connection, 0, strlen(name), name); atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); @@ -1014,7 +1021,7 @@ static void xv_store_port_attribute(xv_driver_t *this, char *name) { get_attribute_reply = xcb_xv_get_port_attribute_reply(this->connection, get_attribute_cookie, NULL); free(atom_reply); pthread_mutex_unlock(&this->main_mutex); - + if (get_attribute_reply != NULL) { xv_portattribute_t *attr; @@ -1032,26 +1039,26 @@ static void xv_restore_port_attributes(xv_driver_t *this) { xcb_intern_atom_cookie_t atom_cookie; xcb_intern_atom_reply_t *atom_reply; - + while ((ite = xine_list_front(this->port_attributes)) != NULL) { xv_portattribute_t *attr = xine_list_get_value(this->port_attributes, ite); xine_list_remove (this->port_attributes, ite); - + pthread_mutex_lock(&this->main_mutex); atom_cookie = xcb_intern_atom(this->connection, 0, strlen(attr->name), attr->name); atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, attr->value); free(atom_reply); pthread_mutex_unlock(&this->main_mutex); - + free( attr->name ); free( attr ); } - + pthread_mutex_lock(&this->main_mutex); xcb_flush(this->connection); pthread_mutex_unlock(&this->main_mutex); - + xine_list_delete( this->port_attributes ); } @@ -1061,7 +1068,7 @@ static void xv_dispose (vo_driver_t *this_gen) { /* restore port attributes to their initial values */ xv_restore_port_attributes(this); - + if (this->deinterlace_frame.image) { pthread_mutex_lock(&this->main_mutex); dispose_ximage(this, &this->deinterlace_frame); @@ -1089,7 +1096,7 @@ static void xv_dispose (vo_driver_t *this_gen) { pthread_mutex_destroy(&this->main_mutex); _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -1101,8 +1108,10 @@ static int xv_check_yv12(xcb_connection_t *connection, xcb_xv_port_t port) { list_formats_cookie = xcb_xv_list_image_formats(connection, port); list_formats_reply = xcb_xv_list_image_formats_reply(connection, list_formats_cookie, NULL); + if (!list_formats_reply) + return 1; /* no formats listed; probably due to an invalid port no. */ format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply); - + for (; format_it.rem; xcb_xv_image_format_info_next(&format_it)) if ((format_it.data->id == XINE_IMGFMT_YV12) && (! (strcmp ((char *) format_it.data->guid, "YV12")))) { @@ -1122,14 +1131,14 @@ static void xv_check_capability (xv_driver_t *this, char *config_help) { int int_default; cfg_entry_t *entry; - char *str_prop = xcb_xv_attribute_info_name(attr); + const char *str_prop = xcb_xv_attribute_info_name(attr); xcb_xv_get_port_attribute_cookie_t get_attribute_cookie; xcb_xv_get_port_attribute_reply_t *get_attribute_reply; xcb_intern_atom_cookie_t atom_cookie; xcb_intern_atom_reply_t *atom_reply; - + /* * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing. */ @@ -1159,7 +1168,7 @@ static void xv_check_capability (xv_driver_t *this, /* might be overridden using config entry */ if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) int_default = 0; - + if (config_name) { /* is this a boolean property ? */ if ((attr->min == 0) && (attr->max == 1)) { @@ -1176,12 +1185,12 @@ static void xv_check_capability (xv_driver_t *this, entry = this->config->lookup_entry (this->config, config_name); - if((entry->num_value < this->props[property].min) || + if((entry->num_value < this->props[property].min) || (entry->num_value > this->props[property].max)) { - this->config->update_num(this->config, config_name, + this->config->update_num(this->config, config_name, ((this->props[property].min + this->props[property].max) >> 1)); - + entry = this->config->lookup_entry (this->config, config_name); } @@ -1207,44 +1216,42 @@ static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { this->deinterlace_method = entry->num_value; } -static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xv_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_filter; xcb_intern_atom_cookie_t atom_cookie; xcb_intern_atom_reply_t *atom_reply; - xv_filter = entry->num_value; - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_FILTER"), "XV_FILTER"); + atom_cookie = xcb_intern_atom(this->connection, 0, strlen (atomstr), atomstr); atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_filter); + xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, entry->num_value); free(atom_reply); pthread_mutex_unlock(&this->main_mutex); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - int xv_double_buffer; - - xcb_intern_atom_cookie_t atom_cookie; - xcb_intern_atom_reply_t *atom_reply; +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - xv_double_buffer = entry->num_value; +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - pthread_mutex_lock(&this->main_mutex); - atom_cookie = xcb_intern_atom(this->connection, 0, sizeof("XV_DOUBLE_BUFFER"), "XV_DOUBLE_BUFFER"); - atom_reply = xcb_intern_atom_reply(this->connection, atom_cookie, NULL); - xcb_xv_set_port_attribute(this->connection, this->xv_port, atom_reply->atom, xv_double_buffer); - free(atom_reply); - pthread_mutex_unlock(&this->main_mutex); +static void xv_update_XV_SYNC_TO_VBLANK(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, + sync_atoms[((xv_driver_t *)this_gen)->sync_is_vsync], + "sync to vblank"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xcbxv: double buffering mode = %d\n", xv_double_buffer); +static void xv_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xv_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -1253,14 +1260,65 @@ static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry this->use_pitch_alignment = entry->num_value; } +static xcb_xv_port_t xv_open_port (xv_driver_t *this, xcb_xv_port_t port) { + xcb_xv_grab_port_cookie_t grab_port_cookie; + xcb_xv_grab_port_reply_t *grab_port_reply; + + if (xv_check_yv12 (this->connection, port)) + return 0; + + grab_port_cookie = xcb_xv_grab_port (this->connection, port, XCB_CURRENT_TIME); + grab_port_reply = xcb_xv_grab_port_reply (this->connection, grab_port_cookie, NULL); + + if (grab_port_reply && (grab_port_reply->result == XCB_GRAB_STATUS_SUCCESS)) + { + free (grab_port_reply); + return port; + } + free (grab_port_reply); + return 0; +} + +static xcb_xv_adaptor_info_iterator_t * +xv_find_adaptor_by_port (int port, xcb_xv_adaptor_info_iterator_t *adaptor_it) +{ + for (; adaptor_it->rem; xcb_xv_adaptor_info_next(adaptor_it)) + if (adaptor_it->data->type & XCB_XV_TYPE_IMAGE_MASK) + if (port >= adaptor_it->data->base_id && + port < adaptor_it->data->base_id + adaptor_it->data->num_ports) + return adaptor_it; + return NULL; /* shouldn't happen */ +} + +static xcb_xv_port_t xv_autodetect_port(xv_driver_t *this, + xcb_xv_adaptor_info_iterator_t *adaptor_it, + xcb_xv_port_t base, + xv_prefertype prefer_type) +{ + for (; adaptor_it->rem; xcb_xv_adaptor_info_next(adaptor_it)) + if (adaptor_it->data->type & XCB_XV_TYPE_IMAGE_MASK && + (prefer_type == xv_prefer_none || + strcasestr (xcb_xv_adaptor_info_name (adaptor_it->data), prefer_substrings[prefer_type]))) + { + int j; + for (j = 0; j < adaptor_it->data->num_ports; ++j) + { + xcb_xv_port_t port = adaptor_it->data->base_id + j; + if (port >= base && xv_open_port (this, port)) + return port; + } + } + return 0; +} + static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *visual_gen) { xv_class_t *class = (xv_class_t *) class_gen; config_values_t *config = class->config; xv_driver_t *this; int i; xcb_visual_t *visual = (xcb_visual_t *) visual_gen; - unsigned int j; xcb_xv_port_t xv_port; + xv_prefertype prefer_type; const xcb_query_extension_reply_t *query_extension_reply; @@ -1271,17 +1329,17 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis xcb_xv_list_image_formats_cookie_t list_formats_cookie; xcb_xv_list_image_formats_reply_t *list_formats_reply; - xcb_xv_adaptor_info_iterator_t adaptor_it; + xcb_xv_adaptor_info_iterator_t adaptor_it, adaptor_first; xcb_xv_image_format_info_iterator_t format_it; - this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t)); + this = (xv_driver_t *) calloc(1, sizeof(xv_driver_t)); if (!this) return NULL; pthread_mutex_init(&this->main_mutex, NULL); _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->connection = visual->connection; this->screen = visual->screen; this->window = visual->window; @@ -1309,44 +1367,53 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis return NULL; } - adaptor_it = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply); - - xv_port = 0; - - for (; adaptor_it.rem && !xv_port; xcb_xv_adaptor_info_next(&adaptor_it)) { - - if (adaptor_it.data->type & XCB_XV_TYPE_IMAGE_MASK) { - - for (j = 0; j < adaptor_it.data->num_ports; j++) - if (!xv_check_yv12(this->connection, adaptor_it.data->base_id + j)) { - xcb_xv_grab_port_cookie_t grab_port_cookie; - xcb_xv_grab_port_reply_t *grab_port_reply; - grab_port_cookie = xcb_xv_grab_port(this->connection, adaptor_it.data->base_id + j, XCB_CURRENT_TIME); - grab_port_reply = xcb_xv_grab_port_reply(this->connection, grab_port_cookie, NULL); - if (grab_port_reply && (grab_port_reply->result == XCB_GRAB_STATUS_SUCCESS)) { - free(grab_port_reply); - xv_port = adaptor_it.data->base_id + j; - break; - } - free(grab_port_reply); - } - } + adaptor_first = xcb_xv_query_adaptors_info_iterator(query_adaptors_reply); + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xv_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %d - autodetecting\n"), + LOG_MODULE, xv_port); + adaptor_it = adaptor_first; + xv_port = xv_autodetect_port (this, &adaptor_it, xv_port, prefer_type); + } else + xv_find_adaptor_by_port (xv_port, &adaptor_it); + } + if (!xv_port) + { + adaptor_it = adaptor_first; + xv_port = xv_autodetect_port (this, &adaptor_it, 0, prefer_type); + } + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + adaptor_it = adaptor_first; + xv_port = xv_autodetect_port (this, &adaptor_it, 0, xv_prefer_none); } if (!xv_port) { xprintf(class->xine, XINE_VERBOSITY_LOG, _("video_out_xcbxv: Xv extension is present but I couldn't find a usable yuv12 port.\n" " Looks like your graphics hardware driver doesn't support Xv?!\n")); - + /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/ return NULL; - } + } else xprintf(class->xine, XINE_VERBOSITY_LOG, _("video_out_xcbxv: using Xv port %d from adaptor %s for hardware " "colour space conversion and scaling.\n"), xv_port, xcb_xv_adaptor_info_name(adaptor_it.data)); - + this->xv_port = xv_port; _x_vo_scale_init (&this->sc, 1, 0, config ); @@ -1411,10 +1478,11 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis for (; attribute_it.rem; xcb_xv_attribute_info_next(&attribute_it)) { if ((attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_SETTABLE) && (attribute_it.data->flags & XCB_XV_ATTRIBUTE_FLAG_GETTABLE)) { + const char *const name = xcb_xv_attribute_info_name(attribute_it.data); /* store initial port attribute value */ - xv_store_port_attribute(this, xcb_xv_attribute_info_name(attribute_it.data)); - - if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_HUE")) { + xv_store_port_attribute(this, name); + + if(!strcmp(name, "XV_HUE")) { if (!strncmp(xcb_xv_adaptor_info_name(adaptor_it.data), "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xcbxv: ignoring broken XV_HUE settings on NVidia cards\n"); } else { @@ -1422,64 +1490,61 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis adaptor_it.data->base_id, NULL, NULL, NULL); } - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xv_check_capability (this, VO_PROP_SATURATION, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xv_check_capability (this, VO_PROP_BRIGHTNESS, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xv_check_capability (this, VO_PROP_CONTRAST, attribute_it.data, adaptor_it.data->base_id, NULL, NULL, NULL); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xv_check_capability (this, VO_PROP_COLORKEY, attribute_it.data, adaptor_it.data->base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xv_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attribute_it.data, adaptor_it.data->base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attribute_it.data->min, attribute_it.data->max, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xv_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(xcb_xv_attribute_info_name(attribute_it.data), "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), - 20, xv_update_XV_DOUBLE_BUFFER, this); + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, + 20, xv_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(!strcmp(name, sync_atoms[this->sync_is_vsync = 0]) || + !strcmp(name, sync_atoms[this->sync_is_vsync = 1])) { + int xv_sync_to_vblank; + xv_sync_to_vblank = + config->register_bool (config, "video.device.xv_sync_to_vblank", 1, + _("enable vblank sync"), + _("This option will synchronize the update of the video image to the " + "repainting of the entire screen (\"vertical retrace\"). This eliminates " + "flickering and tearing artifacts. On nvidia cards one may also " + "need to run \"nvidia-settings\" and choose which display device to " + "sync to under the XVideo Settings tab"), + 20, xv_update_XV_SYNC_TO_VBLANK, this); + config->update_num(config,"video.device.xv_sync_to_vblank",xv_sync_to_vblank); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xv_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -1497,10 +1562,10 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis list_formats_reply = xcb_xv_list_image_formats_reply(this->connection, list_formats_cookie, NULL); format_it = xcb_xv_list_image_formats_format_iterator(list_formats_reply); - + this->xv_format_yv12 = 0; this->xv_format_yuy2 = 0; - + for (; format_it.rem; xcb_xv_image_format_info_next(&format_it)) { lprintf ("Xv image format: 0x%x (%4.4s) %s\n", format_it.data->id, (char*)&format_it.data->id, @@ -1515,20 +1580,19 @@ static vo_driver_t *open_plugin(video_driver_class_t *class_gen, const void *vis } else if (format_it.data->id == XINE_IMGFMT_YUY2) { this->xv_format_yuy2 = format_it.data->id; this->capabilities |= VO_CAP_YUY2; - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xcbxv: this adaptor supports the yuy2 format.\n")); } } free(list_formats_reply); - this->use_pitch_alignment = + this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xv_update_xv_pitch_alignment, this); - this->deinterlace_method = + this->deinterlace_method = config->register_enum (config, "video.output.xv_deinterlace_method", 4, deinterlace_methods, _("deinterlace method (deprecated)"), @@ -1591,12 +1655,12 @@ static char* get_description (video_driver_class_t *this_gen) { static void dispose_class (video_driver_class_t *this_gen) { xv_class_t *this = (xv_class_t *) this_gen; - + free (this); } static void *init_class (xine_t *xine, void *visual_gen) { - xv_class_t *this = (xv_class_t *) xine_xmalloc (sizeof (xv_class_t)); + xv_class_t *this = (xv_class_t *) calloc(1, sizeof(xv_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 9e901821a..3d4dae3f9 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -76,7 +76,7 @@ typedef struct { int flags; vo_scale_t sc; - + XImage *image; XShmSegmentInfo shminfo; @@ -100,7 +100,7 @@ typedef struct { int depth, bpp, bytes_per_pixel, image_byte_order; int use_shm; XColor black; - + int yuv2rgb_brightness; int yuv2rgb_contrast; int yuv2rgb_saturation; @@ -108,7 +108,7 @@ typedef struct { yuv2rgb_factory_t *yuv2rgb_factory; vo_scale_t sc; - + xshm_frame_t *cur_frame; x11osd *xoverlay; int ovl_changed; @@ -164,11 +164,11 @@ static void x11_DeInstallXErrorHandler (xshm_driver_t *this) { } /* - * allocate an XImage, try XShm first but fall back to + * allocate an XImage, try XShm first but fall back to * plain X11 if XShm should fail */ /* called xlocked */ -static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, +static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, int width, int height) { XImage *myimage = NULL; @@ -177,16 +177,16 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, /* * try shm */ - + gX11Fail = 0; x11_InstallXErrorHandler (this); - myimage = XShmCreateImage(this->display, + myimage = XShmCreateImage(this->display, this->visual, this->depth, ZPixmap, NULL, shminfo, - width, + width, height); if (myimage == NULL ) { @@ -196,15 +196,15 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->use_shm = 0; goto finishShmTesting; } - + this->bpp = myimage->bits_per_pixel; this->bytes_per_pixel = this->bpp / 8; this->image_byte_order = myimage->byte_order; - + shminfo->shmid=shmget(IPC_PRIVATE, - myimage->bytes_per_line * myimage->height, + myimage->bytes_per_line * myimage->height, IPC_CREAT | 0777); - + if (shminfo->shmid < 0 ) { xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xshm: %s: allocating image\n" @@ -212,9 +212,9 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->use_shm = 0; goto finishShmTesting; } - + shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); - + if (shminfo->shmaddr == ((char *) -1)) { xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xshm: shared memory error (address error) when allocating image \n" @@ -224,12 +224,12 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->use_shm = 0; goto finishShmTesting; } - + shminfo->readOnly = False; myimage->data = shminfo->shmaddr; - + XShmAttach(this->display, shminfo); - + XSync(this->display, False); if (gX11Fail) { @@ -243,10 +243,10 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, goto finishShmTesting; } - /* + /* * Now that the Xserver has learned about and attached to the * shared memory segment, delete it. It's actually deleted by - * the kernel when all users of that segment have detached from + * the kernel when all users of that segment have detached from * it. Gives an automatic shared memory cleanup in case we crash. */ shmctl (shminfo->shmid, IPC_RMID, 0); @@ -268,7 +268,7 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->depth, ZPixmap, 0, NULL, - width, + width, height, 8, 0); @@ -276,7 +276,7 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, this->bytes_per_pixel = this->bpp / 8; this->image_byte_order = myimage->byte_order; - myimage->data = xine_xmalloc (width * this->bytes_per_pixel * height); + myimage->data = calloc (width * height, this->bytes_per_pixel); } return myimage; @@ -284,8 +284,8 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, } /* called xlocked */ -static void dispose_ximage (xshm_driver_t *this, - XShmSegmentInfo *shminfo, +static void dispose_ximage (xshm_driver_t *this, + XShmSegmentInfo *shminfo, XImage *myimage) { if (this->use_shm) { @@ -298,7 +298,7 @@ static void dispose_ximage (xshm_driver_t *this, shminfo->shmid = -1; } - } + } else XDestroyImage (myimage); } @@ -321,10 +321,10 @@ static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */ - - vo_img->proc_called = 1; - - if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + + vo_img->proc_called = 1; + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) { /* we don't support crop, so don't even waste cpu cycles. @@ -332,7 +332,7 @@ static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { */ return; } - + lprintf ("copy... (format %d)\n", frame->format); if (frame->format == XINE_IMGFMT_YV12) @@ -341,7 +341,7 @@ static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { else frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, src[0]); - + lprintf ("copy...done\n"); } @@ -387,7 +387,7 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { xshm_frame_t *frame; xshm_driver_t *this = (xshm_driver_t *) this_gen; - frame = (xshm_frame_t *) xine_xmalloc (sizeof (xshm_frame_t)); + frame = (xshm_frame_t *) calloc(1, sizeof(xshm_frame_t)); if (!frame) return NULL; @@ -398,10 +398,10 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { /* * supply required functions/fields */ - + frame->vo_frame.proc_slice = xshm_frame_proc_slice; frame->vo_frame.proc_frame = NULL; - frame->vo_frame.field = xshm_frame_field; + frame->vo_frame.field = xshm_frame_field; frame->vo_frame.dispose = xshm_frame_dispose; frame->vo_frame.driver = this_gen; @@ -461,7 +461,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, frame->sc.video_pixel_aspect, &gui_width, &gui_height, &gui_pixel_aspect); - + /* find out if we need to adapt this frame */ do_adapt = 0; @@ -486,7 +486,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, frame->sc.user_ratio = this->sc.user_ratio; xshm_compute_ideal_size (this, frame); - + /* now we have updated video_aspect_pixel we use the callback */ /* again to obtain the correct gui_width and gui_height values. */ frame->sc.dest_size_cb (frame->sc.user_data, width, height, @@ -494,20 +494,20 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, &gui_width, &gui_height, &gui_pixel_aspect); } - + if ((frame->sc.gui_width != gui_width) || (frame->sc.gui_height != gui_height) || do_adapt) { - + do_adapt = 1; frame->sc.gui_width = gui_width; frame->sc.gui_height = gui_height; - + xshm_compute_rgb_size (this, frame); - + lprintf ("gui_size has changed => adapt\n"); } - + /* ok, now do what we have to do */ @@ -564,7 +564,7 @@ static void xshm_update_frame_format (vo_driver_t *this_gen, lprintf ("stripe out_ht=%i, deliv_ht=%i\n", frame->sc.output_height, frame->sc.delivered_height); - /* + /* * set up colorspace converter */ @@ -620,7 +620,7 @@ static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overla } } -static void xshm_overlay_begin (vo_driver_t *this_gen, +static void xshm_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -628,10 +628,10 @@ static void xshm_overlay_begin (vo_driver_t *this_gen, if( this->ovl_changed && this->xoverlay ) { LOCK_DISPLAY(this); - x11osd_clear(this->xoverlay); + x11osd_clear(this->xoverlay); UNLOCK_DISPLAY(this); } - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -648,7 +648,7 @@ static void xshm_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { this->ovl_changed = 0; } -static void xshm_overlay_blend (vo_driver_t *this_gen, +static void xshm_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { xshm_driver_t *this = (xshm_driver_t *) this_gen; xshm_frame_t *frame = (xshm_frame_t *) frame_gen; @@ -658,13 +658,13 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, if( overlay->unscaled ) { if( this->ovl_changed && this->xoverlay ) { LOCK_DISPLAY(this); - x11osd_blend(this->xoverlay, overlay); + x11osd_blend(this->xoverlay, overlay); UNLOCK_DISPLAY(this); } } else { if (!overlay->rgb_clut || !overlay->hili_rgb_clut) xshm_overlay_clut_yuv2rgb (this, overlay, frame); - + switch (this->bpp) { case 16: _x_blend_rgb16 ((uint8_t *)frame->image->data, overlay, @@ -685,7 +685,7 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, &this->alphablend_extra_data); break; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "xine-lib:video_out_xshm:xshm_overlay_blend: Cannot blend bpp:%i\n", this->bpp); /* it should never get here, unless a user tries to play in bpp:8 */ break; @@ -696,12 +696,12 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) { int i; - + memcpy( this->sc.border, frame->sc.border, sizeof(this->sc.border) ); - + LOCK_DISPLAY(this); XSetForeground (this->display, this->gc, this->black.pixel); - + for( i = 0; i < 4; i++ ) { if( this->sc.border[i].w && this->sc.border[i].h ) XFillRectangle(this->display, this->drawable, this->gc, @@ -712,7 +712,7 @@ static void clean_output_area (xshm_driver_t *this, xshm_frame_t *frame) { x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + UNLOCK_DISPLAY(this); } @@ -724,15 +724,15 @@ static int xshm_redraw_needed (vo_driver_t *this_gen) { this->sc.delivered_height = this->cur_frame->sc.delivered_height; this->sc.delivered_width = this->cur_frame->sc.delivered_width; this->sc.video_pixel_aspect = this->cur_frame->sc.video_pixel_aspect; - if( _x_vo_scale_redraw_needed( &this->sc ) ) { + if( _x_vo_scale_redraw_needed( &this->sc ) ) { clean_output_area (this, this->cur_frame); ret = 1; } - } + } else ret = 1; - + return ret; } @@ -745,22 +745,22 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { frame->vo_frame.id, frame->sc.output_width, frame->sc.output_height); - /* + /* * tell gui that we are about to display a frame, * ask for offset */ - + this->sc.delivered_height = frame->sc.delivered_height; this->sc.delivered_width = frame->sc.delivered_width; this->sc.video_pixel_aspect = frame->sc.video_pixel_aspect; - if( _x_vo_scale_redraw_needed( &this->sc ) ) { + if( _x_vo_scale_redraw_needed( &this->sc ) ) { clean_output_area (this, frame); } - + if (this->cur_frame) { - if ( (this->cur_frame->sc.output_width != frame->sc.output_width) + if ( (this->cur_frame->sc.output_width != frame->sc.output_width) || (this->cur_frame->sc.output_height != frame->sc.output_height) || (this->cur_frame->sc.output_xoffset != frame->sc.output_xoffset) || (this->cur_frame->sc.output_yoffset != frame->sc.output_yoffset) ) @@ -770,10 +770,10 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { } this->cur_frame = frame; - + LOCK_DISPLAY(this); lprintf ("display locked...\n"); - + if (this->use_shm) { lprintf ("put image (shm)\n"); @@ -824,14 +824,14 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_OUTPUT_YOFFSET: return this->cur_frame->sc.output_yoffset; default: - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xshm: tried to get unsupported property %d\n", property); } return 0; } -static int xshm_set_property (vo_driver_t *this_gen, +static int xshm_set_property (vo_driver_t *this_gen, int property, int value) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -840,7 +840,7 @@ static int xshm_set_property (vo_driver_t *this_gen, if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->sc.user_ratio = value; - xprintf(this->xine, XINE_VERBOSITY_DEBUG, + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xshm: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); } else if (property == VO_PROP_BRIGHTNESS) { @@ -874,7 +874,7 @@ static int xshm_set_property (vo_driver_t *this_gen, this->sc.force_redraw = 1; } else { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xshm: tried to set unsupported property %d\n", property); } @@ -900,7 +900,7 @@ static void xshm_get_property_min_max (vo_driver_t *this_gen, } } -static int xshm_gui_data_exchange (vo_driver_t *this_gen, +static int xshm_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { xshm_driver_t *this = (xshm_driver_t *) this_gen; @@ -911,15 +911,15 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, #endif case XINE_GUI_SEND_EXPOSE_EVENT: - + lprintf ("expose event\n"); if (this->cur_frame) { XExposeEvent * xev = (XExposeEvent *) data; - + if (xev && xev->count == 0) { int i; - + LOCK_DISPLAY(this); if (this->use_shm) { XShmPutImage(this->display, @@ -929,7 +929,7 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, False); } else { - XPutImage(this->display, + XPutImage(this->display, this->drawable, this->gc, this->cur_frame->image, 0, 0, this->cur_frame->sc.output_xoffset, this->cur_frame->sc.output_yoffset, this->cur_frame->sc.output_width, this->cur_frame->sc.output_height); @@ -952,7 +952,7 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, } } break; - + case XINE_GUI_SEND_DRAWABLE_CHANGED: this->drawable = (Drawable) data; @@ -970,7 +970,7 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, if (this->cur_frame) { x11_rectangle_t *rect = data; int x1, y1, x2, y2; - + _x_vo_scale_translate_gui2video(&this->cur_frame->sc, rect->x, rect->y, &x1, &y1); @@ -993,16 +993,16 @@ static int xshm_gui_data_exchange (vo_driver_t *this_gen, static void xshm_dispose (vo_driver_t *this_gen) { xshm_driver_t *this = (xshm_driver_t *) this_gen; - + if (this->cur_frame) this->cur_frame->vo_frame.dispose (&this->cur_frame->vo_frame); this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); - + LOCK_DISPLAY(this); XFreeGC(this->display, this->gc); UNLOCK_DISPLAY(this); - + if( this->xoverlay ) { LOCK_DISPLAY(this); x11osd_destroy (this->xoverlay); @@ -1010,7 +1010,7 @@ static void xshm_dispose (vo_driver_t *this_gen) { } _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -1022,7 +1022,7 @@ static int ImlibPaletteLUTGet(xshm_driver_t *this) { int format_ret; long length; Atom to_get; - + retval = NULL; length = 0x7fffffff; to_get = XInternAtom(this->display, "_IMLIB_COLORMAP", False); @@ -1034,7 +1034,7 @@ static int ImlibPaletteLUTGet(xshm_driver_t *this) { if (format_ret == 8) { unsigned int i; unsigned long j; - + j = 1 + retval[0]*4; this->yuv2rgb_cmap = malloc(sizeof(uint8_t) * 32 * 32 * 32); for (i = 0; i < 32 * 32 * 32 && j < num_ret; i++) @@ -1082,14 +1082,14 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v int swapped; int cpu_byte_order; XColor dummy; - - this = (xshm_driver_t *) xine_xmalloc (sizeof (xshm_driver_t)); + + this = (xshm_driver_t *) calloc(1, sizeof(xshm_driver_t)); if (!this) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->display = visual->display; this->screen = visual->screen; @@ -1102,9 +1102,9 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v this->sc.frame_output_cb = visual->frame_output_cb; this->sc.dest_size_cb = visual->dest_size_cb; this->sc.user_data = visual->user_data; - + this->sc.user_ratio = XINE_VO_ASPECT_AUTO; - + this->drawable = visual->d; this->cur_frame = NULL; LOCK_DISPLAY(this); @@ -1112,7 +1112,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v UNLOCK_DISPLAY(this); this->xoverlay = NULL; this->ovl_changed = 0; - + this->x11_old_error_handler = NULL; this->xine = class->xine; @@ -1129,7 +1129,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v this->vo_driver.gui_data_exchange = xshm_gui_data_exchange; this->vo_driver.dispose = xshm_dispose; this->vo_driver.redraw_needed = xshm_redraw_needed; - + LOCK_DISPLAY(this); XAllocNamedColor (this->display, DefaultColormap (this->display, this->screen), @@ -1151,7 +1151,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v UNLOCK_DISPLAY(this); this->visual = attribs.visual; this->depth = attribs.depth; - + if (this->depth>16) xprintf(this->xine, XINE_VERBOSITY_LOG, _("\n\nWARNING: current display depth is %d. For better performance\n" @@ -1164,7 +1164,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v LOCK_DISPLAY(this); if (XShmQueryExtension(this->display)) { this->use_shm = 1; - } + } else { xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xshm: MIT shared memory extension not present on display.\n")); @@ -1186,7 +1186,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v */ cpu_byte_order = htonl(1) == 1 ? MSBFirst : LSBFirst; swapped = cpu_byte_order != this->image_byte_order; - + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xshm: video mode depth is %d (%d bpp), %s, %sswapped,\n" "\tred: %08lx, green: %08lx, blue: %08lx\n", @@ -1250,16 +1250,16 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v } if (!mode) { - xprintf (this->xine, XINE_VERBOSITY_LOG, + xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out_xshm: your video mode was not recognized, sorry :-(\n")); return NULL; } - + this->yuv2rgb_brightness = 0; this->yuv2rgb_contrast = 128; this->yuv2rgb_saturation = 128; - - this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, + + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, this->yuv2rgb_cmap); this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, this->yuv2rgb_brightness, @@ -1287,7 +1287,7 @@ static vo_driver_t *xshm_open_plugin_old (video_driver_class_t *class_gen, const visual.frame_output_cb = old_visual->frame_output_cb; visual.lock_display = NULL; visual.unlock_display = NULL; - + return xshm_open_plugin_2(class_gen, (void *)&visual); } @@ -1310,7 +1310,7 @@ static void xshm_dispose_class (video_driver_class_t *this_gen) { } static void *xshm_init_class (xine_t *xine, void *visual_gen) { - xshm_class_t *this = (xshm_class_t *) xine_xmalloc (sizeof (xshm_class_t)); + xshm_class_t *this = (xshm_class_t *) calloc(1, sizeof(xshm_class_t)); this->driver_class.open_plugin = xshm_open_plugin_old; this->driver_class.get_identifier = xshm_get_identifier; @@ -1347,7 +1347,7 @@ static const vo_info_t vo_info_xshm_2 = { */ const plugin_info_t xine_plugin_info[] EXPORTED = { - /* type, API, "name", version, special_info, init_function */ + /* type, API, "name", version, special_info, init_function */ { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class }, { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm_2, xshm_init_class_2 }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 3bb0a93dc..65cd29aa4 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * * This file is part of xine, a free video player. * @@ -70,6 +70,7 @@ #include "xineutils.h" #include "vo_scale.h" #include "x11osd.h" +#include "xv_common.h" #define LOCK_DISPLAY(this) {if(this->lock_display) this->lock_display(this->user_data); \ else XLockDisplay(this->display);} @@ -142,6 +143,8 @@ struct xv_driver_s { int use_colorkey; uint32_t colorkey; + int sync_is_vsync; + /* hold initial port attributes values to restore on exit */ xine_list_t *port_attributes; @@ -168,6 +171,10 @@ typedef struct { static int gX11Fail; +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; +VIDEO_DEVICE_XV_DECL_SYNC_ATOMS; + static uint32_t xv_get_capabilities (vo_driver_t *this_gen) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -208,10 +215,10 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { /* xv_driver_t *this = (xv_driver_t *) this_gen; */ xv_frame_t *frame ; - frame = (xv_frame_t *) xine_xmalloc (sizeof (xv_frame_t)); + frame = (xv_frame_t *) calloc(1, sizeof(xv_frame_t)); if (!frame) return NULL; - + pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* @@ -228,7 +235,7 @@ static vo_frame_t *xv_alloc_frame (vo_driver_t *this_gen) { static int HandleXError (Display *display, XErrorEvent *xevent) { char str [1024]; - + XGetErrorText (display, xevent->error_code, str, 1024); printf ("received X error event: %s\n", str); gX11Fail = 1; @@ -302,7 +309,7 @@ static XvImage *create_ximage (xv_driver_t *this, XShmSegmentInfo *shminfo, lprintf( "XvImage height %d\n", image->height ); lprintf( "XvImage data_size %d\n", image->data_size ); lprintf( "XvImage num_planes %d\n", image->num_planes ); - + for( q=0; q < image->num_planes; q++) { lprintf( "XvImage pitches[%d] %d\n", q, image->pitches[q] ); @@ -418,10 +425,10 @@ static void dispose_ximage (xv_driver_t *this, shminfo->shmid = -1; } - } + } else { free (myimage->data); - + XFree (myimage); } } @@ -459,7 +466,7 @@ static void xv_update_frame_format (vo_driver_t *this_gen, if(format == XINE_IMGFMT_YUY2) { frame->vo_frame.pitches[0] = frame->image->pitches[0]; frame->vo_frame.base[0] = frame->image->data + frame->image->offsets[0]; - } + } else { frame->vo_frame.pitches[0] = frame->image->pitches[0]; frame->vo_frame.pitches[1] = frame->image->pitches[2]; @@ -498,7 +505,7 @@ static void xv_deinterlace_frame (xv_driver_t *this) { if(this->deinterlace_frame.image) dispose_ximage (this, &this->deinterlace_frame.shminfo, this->deinterlace_frame.image); - + this->deinterlace_frame.image = create_ximage (this, &this->deinterlace_frame.shminfo, frame->width,frame->height / xvscaling, frame->format); @@ -521,7 +528,7 @@ static void xv_deinterlace_frame (xv_driver_t *this) { for( i = 0; i < VO_NUM_RECENT_FRAMES; i++ ) if( this->recent_frames[i] && this->recent_frames[i]->width == frame->width && this->recent_frames[i]->height == frame->height ) - recent_bitmaps[i] = this->recent_frames[i]->image->data + frame->width*frame->height; + recent_bitmaps[i] = this->recent_frames[i]->image->data + this->deinterlace_frame.image->width*frame->height; else recent_bitmaps[i] = NULL; @@ -614,12 +621,12 @@ static void xv_clean_output_area (xv_driver_t *this) { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height); } - + if (this->xoverlay) { x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + UNLOCK_DISPLAY(this); } @@ -650,7 +657,7 @@ static void xv_compute_output_size (xv_driver_t *this) { } } -static void xv_overlay_begin (vo_driver_t *this_gen, +static void xv_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { xv_driver_t *this = (xv_driver_t *) this_gen; @@ -658,10 +665,10 @@ static void xv_overlay_begin (vo_driver_t *this_gen, if( this->ovl_changed && this->xoverlay ) { LOCK_DISPLAY(this); - x11osd_clear(this->xoverlay); + x11osd_clear(this->xoverlay); UNLOCK_DISPLAY(this); } - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } @@ -678,7 +685,7 @@ static void xv_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { this->ovl_changed = 0; } -static void xv_overlay_blend (vo_driver_t *this_gen, +static void xv_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { xv_driver_t *this = (xv_driver_t *) this_gen; xv_frame_t *frame = (xv_frame_t *) frame_gen; @@ -687,16 +694,16 @@ static void xv_overlay_blend (vo_driver_t *this_gen, if( overlay->unscaled ) { if( this->ovl_changed && this->xoverlay ) { LOCK_DISPLAY(this); - x11osd_blend(this->xoverlay, overlay); + x11osd_blend(this->xoverlay, overlay); UNLOCK_DISPLAY(this); } } else { if (frame->format == XINE_IMGFMT_YV12) - _x_blend_yuv(frame->vo_frame.base, overlay, + _x_blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); else - _x_blend_yuy2(frame->vo_frame.base[0], overlay, + _x_blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0], &this->alphablend_extra_data); } @@ -740,7 +747,7 @@ static int xv_redraw_needed (vo_driver_t *this_gen) { this->sc.delivered_height = this->cur_frame->height; this->sc.delivered_width = this->cur_frame->width; this->sc.delivered_ratio = this->cur_frame->ratio; - + this->sc.crop_left = this->cur_frame->vo_frame.crop_left; this->sc.crop_right = this->cur_frame->vo_frame.crop_right; this->sc.crop_top = this->cur_frame->vo_frame.crop_top; @@ -779,7 +786,7 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { /* printf ("video_out_xv: xv_display_frame...\n"); */ - + /* * queue frames (deinterlacing) * free old frames @@ -852,7 +859,7 @@ static void xv_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { if( factor > 1 ) { lprintf( "%s PutImage %dX interval (%fs)\n", - log_line_prefix(), factor, elapse_time ); + LOG_MODULE, factor, elapse_time ); } } @@ -893,7 +900,7 @@ static int xv_get_property (vo_driver_t *this_gen, int property) { static void xv_property_callback (void *property_gen, xine_cfg_entry_t *entry) { xv_property_t *property = (xv_property_t *) property_gen; xv_driver_t *this = property->this; - + LOCK_DISPLAY(this); XvSetPortAttribute (this->display, this->xv_port, property->atom, @@ -923,7 +930,7 @@ static int xv_set_property (vo_driver_t *this_gen, this->props[property].entry->num_value = this->props[property].value; return this->props[property].value; - } + } else { switch (property) { @@ -937,13 +944,13 @@ static int xv_set_property (vo_driver_t *this_gen, xv_compute_output_size (this); } break; - + case VO_PROP_ASPECT_RATIO: if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->props[property].value = value; - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xv: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value); this->sc.user_ratio = value; @@ -957,7 +964,7 @@ static int xv_set_property (vo_driver_t *this_gen, this->props[property].value = value; xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xv: VO_PROP_ZOOM_X = %d\n", this->props[property].value); - + this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; xv_compute_ideal_size (this); @@ -1039,7 +1046,7 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, if(this->xoverlay) x11osd_expose(this->xoverlay); - + XSync(this->display, False); UNLOCK_DISPLAY(this); } @@ -1090,42 +1097,42 @@ static int xv_gui_data_exchange (vo_driver_t *this_gen, return 0; } -static void xv_store_port_attribute(xv_driver_t *this, char *name) { +static void xv_store_port_attribute(xv_driver_t *this, const char *name) { Atom atom; xv_portattribute_t *attr; - + attr = (xv_portattribute_t *)malloc( sizeof(xv_portattribute_t) ); attr->name = strdup(name); - + LOCK_DISPLAY(this); atom = XInternAtom (this->display, attr->name, False); XvGetPortAttribute (this->display, this->xv_port, atom, &attr->value); UNLOCK_DISPLAY(this); - + xine_list_push_back (this->port_attributes, attr); } static void xv_restore_port_attributes(xv_driver_t *this) { Atom atom; xine_list_iterator_t ite; - + while ((ite = xine_list_front(this->port_attributes)) != NULL) { xv_portattribute_t *attr = xine_list_get_value(this->port_attributes, ite); xine_list_remove (this->port_attributes, ite); - + LOCK_DISPLAY(this); atom = XInternAtom (this->display, attr->name, False); XvSetPortAttribute (this->display, this->xv_port, atom, attr->value); UNLOCK_DISPLAY(this); - + free( attr->name ); free( attr ); } - + LOCK_DISPLAY(this); XSync(this->display, False); UNLOCK_DISPLAY(this); - + xine_list_delete( this->port_attributes ); } @@ -1135,7 +1142,7 @@ static void xv_dispose (vo_driver_t *this_gen) { /* restore port attributes to their initial values */ xv_restore_port_attributes(this); - + if (this->deinterlace_frame.image) { LOCK_DISPLAY(this); dispose_ximage (this, &this->deinterlace_frame.shminfo, @@ -1165,7 +1172,7 @@ static void xv_dispose (vo_driver_t *this_gen) { } _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -1176,7 +1183,7 @@ static int xv_check_yv12 (Display *display, XvPortID port) { int i; formatValues = XvListImageFormats (display, port, &formats); - + for (i = 0; i < formats; i++) if ((formatValues[i].id == XINE_IMGFMT_YV12) && (! (strcmp (formatValues[i].guid, "YV12")))) { @@ -1190,15 +1197,14 @@ static int xv_check_yv12 (Display *display, XvPortID port) { /* called xlocked */ static void xv_check_capability (xv_driver_t *this, - int property, XvAttribute attr, - int base_id, + int property, XvAttribute attr, int base_id, char *config_name, char *config_desc, char *config_help) { int int_default; cfg_entry_t *entry; - char *str_prop = attr.name; - + const char *str_prop = attr.name; + /* * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing. */ @@ -1219,7 +1225,7 @@ static void xv_check_capability (xv_driver_t *this, /* might be overridden using config entry */ if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) int_default = 0; - + if (config_name) { /* is this a boolean property ? */ if ((attr.min_value == 0) && (attr.max_value == 1)) { @@ -1236,12 +1242,12 @@ static void xv_check_capability (xv_driver_t *this, entry = this->config->lookup_entry (this->config, config_name); - if((entry->num_value < this->props[property].min) || + if((entry->num_value < this->props[property].min) || (entry->num_value > this->props[property].max)) { - this->config->update_num(this->config, config_name, + this->config->update_num(this->config, config_name, ((this->props[property].min + this->props[property].max) >> 1)); - + entry = this->config->lookup_entry (this->config, config_name); } @@ -1267,36 +1273,38 @@ static void xv_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { this->deinterlace_method = entry->num_value; } -static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xv_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xv_driver_t *this = (xv_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); UNLOCK_DISPLAY(this); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xv_driver_t *this = (xv_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; +static void xv_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - xv_double_buffer = entry->num_value; +static void xv_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - LOCK_DISPLAY(this); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - UNLOCK_DISPLAY(this); +static void xv_update_XV_SYNC_TO_VBLANK(void *this_gen, xine_cfg_entry_t *entry) { + xv_update_attr (this_gen, entry, + sync_atoms[((xv_driver_t *)this_gen)->sync_is_vsync], + "sync to vblank"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xv: double buffering mode = %d\n", xv_double_buffer); +static void xv_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xv_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -1305,6 +1313,52 @@ static void xv_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry this->use_pitch_alignment = entry->num_value; } +static int xv_open_port (xv_driver_t *this, XvPortID port) { + int ret; + x11_InstallXErrorHandler (this); + ret = ! xv_check_yv12(this->display, port) + && XvGrabPort(this->display, port, 0) == Success; + x11_DeInstallXErrorHandler (this); + return ret; +} + +static unsigned int +xv_find_adaptor_by_port (int port, unsigned int adaptors, + XvAdaptorInfo *adaptor_info) +{ + unsigned int an; + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask) + if (port >= adaptor_info[an].base_id && + port < adaptor_info[an].base_id + adaptor_info[an].num_ports) + return an; + return 0; /* shouldn't happen */ +} + +static XvPortID xv_autodetect_port(xv_driver_t *this, + unsigned int adaptors, + XvAdaptorInfo *adaptor_info, + unsigned int *adaptor_num, + XvPortID base, + xv_prefertype prefer_type) +{ + unsigned int an, j; + + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask && + (prefer_type == xv_prefer_none || + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) + for (j = 0; j < adaptor_info[an].num_ports; j++) { + XvPortID port = adaptor_info[an].base_id + j; + if (port >= base && xv_open_port(this, port)) { + *adaptor_num = an; + return port; + } + } + + return 0; +} + /* expects XINE_VISUAL_TYPE_X11_2 with configurable locking */ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void *visual_gen) { xv_class_t *class = (xv_class_t *) class_gen; @@ -1317,19 +1371,20 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; XvImage *myimage; - unsigned int adaptors, j; + unsigned int adaptors; unsigned int ver,rel,req,ev,err; XShmSegmentInfo myshminfo; XvPortID xv_port; XvAdaptorInfo *adaptor_info; unsigned int adaptor_num; + xv_prefertype prefer_type; - this = (xv_driver_t *) xine_xmalloc (sizeof (xv_driver_t)); + this = (xv_driver_t *) calloc(1, sizeof(xv_driver_t)); if (!this) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->display = visual->display; this->screen = visual->screen; this->config = config; @@ -1360,43 +1415,50 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * return NULL; } - xv_port = 0; - - for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) { - - if (adaptor_info[adaptor_num].type & XvImageMask) { - - for (j = 0; j < adaptor_info[adaptor_num].num_ports && !xv_port; j++) - if (( !(xv_check_yv12 (this->display, - adaptor_info[adaptor_num].base_id + j))) - && (XvGrabPort (this->display, - adaptor_info[adaptor_num].base_id + j, - 0) == Success)) { - xv_port = adaptor_info[adaptor_num].base_id + j; - } - - if( xv_port ) - break; - } + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xv_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %"PRId32" - autodetecting\n"), + LOG_MODULE, xv_port); + xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type); + } else + adaptor_num = xv_find_adaptor_by_port (xv_port, adaptors, adaptor_info); + } + if (!xv_port) + xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + xv_port = xv_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); } if (!xv_port) { xprintf(class->xine, XINE_VERBOSITY_LOG, _("video_out_xv: Xv extension is present but I couldn't find a usable yuv12 port.\n" " Looks like your graphics hardware driver doesn't support Xv?!\n")); - + /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/ UNLOCK_DISPLAY(this); return NULL; - } + } else xprintf(class->xine, XINE_VERBOSITY_LOG, _("video_out_xv: using Xv port %ld from adaptor %s for hardware " "colour space conversion and scaling.\n"), xv_port, adaptor_info[adaptor_num].name); - + UNLOCK_DISPLAY(this); - + this->xv_port = xv_port; _x_vo_scale_init (&this->sc, 1, 0, config ); @@ -1469,10 +1531,11 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { + const char *const name = attr[k].name; /* store initial port attribute value */ - xv_store_port_attribute(this, attr[k].name); - - if(!strcmp(attr[k].name, "XV_HUE")) { + xv_store_port_attribute(this, name); + + if(!strcmp(name, "XV_HUE")) { if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xv: ignoring broken XV_HUE settings on NVidia cards\n"); } else { @@ -1480,64 +1543,61 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); } - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xv_check_capability (this, VO_PROP_SATURATION, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xv_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xv_check_capability (this, VO_PROP_CONTRAST, attr[k], adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xv_check_capability (this, VO_PROP_COLORKEY, attr[k], adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xv_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attr[k].min_value, attr[k].max_value, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xv_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), - 20, xv_update_XV_DOUBLE_BUFFER, this); + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, + 20, xv_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(((this->sync_is_vsync = 0), !strcmp(name, sync_atoms[0])) || + ((this->sync_is_vsync = 1), !strcmp(name, sync_atoms[1]))) { + int xv_sync_to_vblank; + xv_sync_to_vblank = + config->register_bool (config, "video.device.xv_sync_to_vblank", 1, + _("enable vblank sync"), + _("This option will synchronize the update of the video image to the " + "repainting of the entire screen (\"vertical retrace\"). This eliminates " + "flickering and tearing artifacts. On nvidia cards one may also " + "need to run \"nvidia-settings\" and choose which display device to " + "sync to under the XVideo Settings tab"), + 20, xv_update_XV_SYNC_TO_VBLANK, this); + config->update_num(config,"video.device.xv_sync_to_vblank",xv_sync_to_vblank); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xv_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -1553,10 +1613,10 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * fo = XvListImageFormats(this->display, this->xv_port, (int*)&formats); UNLOCK_DISPLAY(this); - + this->xv_format_yv12 = 0; this->xv_format_yuy2 = 0; - + for(i = 0; i < formats; i++) { lprintf ("Xv image format: 0x%x (%4.4s) %s\n", fo[i].id, (char*)&fo[i].id, @@ -1570,7 +1630,7 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * } else if (fo[i].id == XINE_IMGFMT_YUY2) { this->xv_format_yuy2 = fo[i].id; this->capabilities |= VO_CAP_YUY2; - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xv: this adaptor supports the yuy2 format.\n")); } } @@ -1591,13 +1651,12 @@ static vo_driver_t *open_plugin_2 (video_driver_class_t *class_gen, const void * dispose_ximage (this, &myshminfo, myimage); UNLOCK_DISPLAY(this); - this->use_pitch_alignment = + this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xv_update_xv_pitch_alignment, this); - this->deinterlace_method = + this->deinterlace_method = config->register_enum (config, "video.output.xv_deinterlace_method", 4, deinterlace_methods, _("deinterlace method (deprecated)"), @@ -1661,7 +1720,7 @@ static vo_driver_t *open_plugin_old (video_driver_class_t *class_gen, const void visual.frame_output_cb = old_visual->frame_output_cb; visual.lock_display = NULL; visual.unlock_display = NULL; - + return open_plugin_2(class_gen, (void *)&visual); } @@ -1679,12 +1738,12 @@ static char* get_description (video_driver_class_t *this_gen) { static void dispose_class (video_driver_class_t *this_gen) { xv_class_t *this = (xv_class_t *) this_gen; - + free (this); } static void *init_class (xine_t *xine, void *visual_gen) { - xv_class_t *this = (xv_class_t *) xine_xmalloc (sizeof (xv_class_t)); + xv_class_t *this = (xv_class_t *) calloc(1, sizeof(xv_class_t)); this->driver_class.open_plugin = open_plugin_old; this->driver_class.get_identifier = get_identifier; diff --git a/src/video_out/video_out_xvmc.c b/src/video_out/video_out_xvmc.c index a17e4d6a0..aeb536fc1 100644 --- a/src/video_out/video_out_xvmc.c +++ b/src/video_out/video_out_xvmc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * * This file is part of xine, a free video player. * @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -75,6 +75,7 @@ #include "xineutils.h" #include "vo_scale.h" +#include "xv_common.h" /* #define LOG1 */ /* #define DLOG */ @@ -92,7 +93,7 @@ typedef struct { XvMCMacroBlock *macroblockbaseptr; /* pointer to base MacroBlock in MB array */ XvMCMacroBlockArray *macro_blocks; /* pointer to memory for macroblock array */ int slices; -} xvmc_macroblocks_t; +} xvmc_macroblocks_t; typedef struct { void *xid; @@ -148,8 +149,8 @@ struct xvmc_driver_s { int max_surface_height; int num_frame_buffers; - int surface_width; - int surface_height; + int surface_width; + int surface_height; int surface_ratio; int surface_format; int surface_flags; @@ -167,7 +168,7 @@ struct xvmc_driver_s { /* display anatomy */ double display_ratio; /* given by visual parameter from init function */ - + xvmc_property_t props[VO_NUM_PROPERTIES]; uint32_t capabilities; @@ -180,7 +181,7 @@ struct xvmc_driver_s { /* size / aspect ratio calculations */ - /* + /* * "delivered" size: * frame dimension / aspect as delivered by the decoder * used (among other things) to detect frame size changes @@ -188,7 +189,7 @@ struct xvmc_driver_s { int delivered_duration; - /* + /* * "ideal" size : * displayed width/height corrected by aspect ratio */ @@ -196,19 +197,19 @@ struct xvmc_driver_s { double ratio_factor; /* output frame must fullfill: height = width * ratio_factor */ - + xvmc_frame_t deinterlace_frame; int deinterlace_method; int deinterlace_enabled; /* gui callback */ - + void (*frame_output_cb) (void *user_data, int video_width, int video_height, - int *dest_x, int *dest_y, + int *dest_x, int *dest_y, int *dest_height, int *dest_width, int *win_x, int *win_y); - + int use_colorkey; uint32_t colorkey; @@ -225,8 +226,6 @@ typedef struct { Display *display; config_values_t *config; XvPortID xv_port; - XvAdaptorInfo *adaptor_info; - unsigned int adaptor_num; int surface_type_id; unsigned int max_surface_width; @@ -246,19 +245,19 @@ static void xvmc_render_macro_blocks(vo_frame_t *current_image, /**************************************************************************/ -/* +/* * dmvector: differential motion vector * mvx, mvy: decoded mv components (always in field format) */ -static void calc_DMV(int DMV[][2], int *dmvector, +static void calc_DMV(int DMV[][2], int *dmvector, int mvx, int mvy, int picture_structure, int top_field_first) { - + if (picture_structure==VO_BOTH_FIELDS) { if (top_field_first) { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy +(mvy>0))>>1) + dmvector[1] - 1; - + /* vector for prediction of bottom field from top field */ DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1; @@ -267,7 +266,7 @@ static void calc_DMV(int DMV[][2], int *dmvector, /* vector for prediction of top field from bottom field */ DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1; - + /* vector for prediction of bottom field from top field */ DMV[1][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((mvy +(mvy>0))>>1) + dmvector[1] + 1; @@ -277,7 +276,7 @@ static void calc_DMV(int DMV[][2], int *dmvector, /* vector for prediction from field of opposite 'parity' */ DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1]; - + /* correct for vertical field shift */ if (picture_structure==VO_TOP_FIELD) DMV[0][1]--; @@ -286,11 +285,11 @@ static void calc_DMV(int DMV[][2], int *dmvector, } } -static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, - int (*mv_field_sel)[2], int *dmvector, int cbp, - int dct_type, vo_frame_t *current_frame, - vo_frame_t *forward_ref_frame, - vo_frame_t *backward_ref_frame, int picture_structure, +static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, + int (*mv_field_sel)[2], int *dmvector, int cbp, + int dct_type, vo_frame_t *current_frame, + vo_frame_t *forward_ref_frame, + vo_frame_t *backward_ref_frame, int picture_structure, int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2]) { xvmc_driver_t *this = (xvmc_driver_t *) current_frame->driver; xvmc_macroblocks_t *mbs = &this->macroblocks; @@ -299,10 +298,10 @@ static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, mbs->macroblockptr->x = x; mbs->macroblockptr->y = y; - + if(mb_type & XINE_MACROBLOCK_INTRA) { mbs->macroblockptr->macroblock_type = XVMC_MB_TYPE_INTRA; - } + } else { mbs->macroblockptr->macroblock_type = 0; /* XvMC doesn't support skips */ @@ -311,7 +310,7 @@ static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, motion_type = (picture_structure == VO_BOTH_FIELDS) ? XINE_MC_FRAME : XINE_MC_FIELD; mbs->macroblockptr->PMV[0][0][0] = 0; mbs->macroblockptr->PMV[0][0][1] = 0; - } + } else { if(mb_type & XINE_MACROBLOCK_MOTION_BACKWARD) { mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD; @@ -343,17 +342,17 @@ static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, calc_DMV(DMV,dmvector, f_mot_pmv[0][0], f_mot_pmv[0][1]>>1, picture_structure, top_field_first); - + mbs->macroblockptr->PMV[1][0][0] = DMV[0][0]; mbs->macroblockptr->PMV[1][0][1] = DMV[0][1]; mbs->macroblockptr->PMV[1][1][0] = DMV[1][0]; mbs->macroblockptr->PMV[1][1][1] = DMV[1][1]; - } + } else { calc_DMV(DMV,dmvector, f_mot_pmv[0][0], f_mot_pmv[0][1]>>1, picture_structure, top_field_first); - + mbs->macroblockptr->PMV[0][1][0] = DMV[0][0]; mbs->macroblockptr->PMV[0][1][1] = DMV[0][1]; } @@ -379,7 +378,7 @@ static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, mbs->macroblockptr->dct_type = dct_type; mbs->macroblockptr->coded_block_pattern = cbp; - while(cbp) { + while(cbp) { if(cbp & 1) mbs->macroblockptr->index--; cbp >>= 1; } @@ -447,7 +446,7 @@ static void xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, picture_structure, second_field ? XVMC_SECOND_FIELD : 0, mbs); - + mbs->num_blocks = 0; mbs->macroblockptr = mbs->macroblockbaseptr; mbs->xine_mc.blockptr = mbs->xine_mc.blockbaseptr; @@ -471,9 +470,9 @@ static void xvmc_frame_dispose (vo_frame_t *vo_img) { lprintf ("xvmc_frame_dispose\n"); - /* + /* * TODO - clean up of images/surfaces and frames - * Note this function is not really needed + * Note this function is not really needed * set_context does the work */ @@ -499,9 +498,9 @@ static void xvmc_render_macro_blocks(vo_frame_t *current_image, (long) forward_frame); /* lprintf ("slices %d 0x%08lx 0x%08lx 0x%08lx\n",macroblocks->slices, (long) current_frame->surface, (long) backward_frame->surface, - (long) forward_frame->surface); + (long) forward_frame->surface); */ - + flags = second_field; if(forward_frame) { @@ -513,7 +512,7 @@ static void xvmc_render_macro_blocks(vo_frame_t *current_image, flags, macroblocks->slices, 0, macroblocks->macro_blocks, macroblocks->blocks); - } + } else { XvMCRenderSurface(this->display, &this->context, picture_structure, ¤t_frame->surface, @@ -523,7 +522,7 @@ static void xvmc_render_macro_blocks(vo_frame_t *current_image, macroblocks->slices, 0, macroblocks->macro_blocks, macroblocks->blocks); } - } + } else { if(backward_frame) { XvMCRenderSurface(this->display, &this->context, picture_structure, @@ -533,7 +532,7 @@ static void xvmc_render_macro_blocks(vo_frame_t *current_image, flags, macroblocks->slices, 0, macroblocks->macro_blocks, macroblocks->blocks); - } + } else { XvMCRenderSurface(this->display, &this->context, picture_structure, ¤t_frame->surface, @@ -556,7 +555,7 @@ static vo_frame_t *xvmc_alloc_frame (vo_driver_t *this_gen) { lprintf ("xvmc_alloc_frame\n"); - frame = (xvmc_frame_t *) xine_xmalloc (sizeof (xvmc_frame_t)); + frame = calloc(1, sizeof (xvmc_frame_t)); if (!frame) return NULL; @@ -565,7 +564,7 @@ static vo_frame_t *xvmc_alloc_frame (vo_driver_t *this_gen) { /* keep track of frames and how many frames alocated. */ this->frames[this->num_frame_buffers++] = frame; - + pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* @@ -592,12 +591,12 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, xvmc_macroblocks_t *macroblocks = (xvmc_macroblocks_t *) macro_blocks; lprintf ("xvmc_set_context %dx%d %04x\n",width,height,format); - + /* initialize block & macro block pointers first time */ if(macroblocks->blocks == NULL || macroblocks->macro_blocks == NULL) { - macroblocks->blocks = xine_xmalloc(sizeof(XvMCBlockArray)); - macroblocks->macro_blocks = xine_xmalloc(sizeof(XvMCMacroBlockArray)); - + macroblocks->blocks = calloc(1, sizeof(XvMCBlockArray)); + macroblocks->macro_blocks = calloc(1, sizeof(XvMCMacroBlockArray)); + lprintf("macroblocks->blocks %lx ->macro_blocks %lx\n", macroblocks->blocks,macroblocks->macro_blocks); } @@ -613,11 +612,11 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, return(&this->context_id); - } - else { + } + else { if(this->context_id.xid != NULL) { - /* + /* * flush any drawing and wait till we are done with the old stuff * blow away the old stuff */ @@ -640,8 +639,8 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, width,height, this->surface_type_id, (int)this->xv_port); /* now create a new context */ - result = XvMCCreateContext(this->display, this->xv_port, - this->surface_type_id, + result = XvMCCreateContext(this->display, this->xv_port, + this->surface_type_id, width, height, XVMC_DIRECT, &this->context); if(result != Success) { @@ -669,7 +668,7 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, slices = (slices * width/16); lprintf("CreateBlocks slices %d\n",slices); - + result = XvMCCreateBlocks(this->display, &this->context, slices * 6, macroblocks->blocks); if(result != Success) { @@ -700,6 +699,7 @@ static cxid_t *xvmc_set_context (xvmc_driver_t *this, return NULL; } +#if 0 static XvImage *create_ximage (xvmc_driver_t *this, XShmSegmentInfo *shminfo, int width, int height, int format) { unsigned int xvmc_format; @@ -751,10 +751,11 @@ static XvImage *create_ximage (xvmc_driver_t *this, XShmSegmentInfo *shminfo, static void dispose_ximage (xvmc_driver_t *this, XShmSegmentInfo *shminfo, XvImage *myimage) { - + lprintf ("dispose_ximage\n"); XFree(myimage); } +#endif static void xvmc_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, @@ -778,9 +779,9 @@ static void xvmc_update_frame_format (vo_driver_t *this_gen, lprintf ("updating frame to %d x %d (ratio=%f, format=%08x)\n", width, height, ratio, format); - /* Note that since we are rendering in hardware, we do not need to + /* Note that since we are rendering in hardware, we do not need to * allocate any ximage's for the software rendering buffers. - */ + */ frame->width = width; frame->height = height; frame->format = format; @@ -790,7 +791,7 @@ static void xvmc_update_frame_format (vo_driver_t *this_gen, xvmc->macroblocks = (xine_macroblocks_t *)&this->macroblocks; this->macroblocks.num_blocks = 0; this->macroblocks.macroblockptr = this->macroblocks.macroblockbaseptr; - this->macroblocks.xine_mc.blockptr = + this->macroblocks.xine_mc.blockptr = this->macroblocks.xine_mc.blockbaseptr; if( flags & VO_NEW_SEQUENCE_FLAG ) { xvmc_set_context (this, width, height, ratio, format, flags, @@ -805,14 +806,14 @@ static void xvmc_clean_output_area (xvmc_driver_t *this) { XSetForeground (this->display, this->gc, this->black.pixel); XFillRectangle (this->display, this->drawable, this->gc, this->sc.gui_x, this->sc.gui_y, this->sc.gui_width, this->sc.gui_height); - + if (this->use_colorkey) { XSetForeground (this->display, this->gc, this->colorkey); XFillRectangle (this->display, this->drawable, this->gc, - this->sc.output_xoffset, this->sc.output_yoffset, + this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height); } - + XUnlockDisplay (this->display); } @@ -833,27 +834,27 @@ static void xvmc_compute_output_size (xvmc_driver_t *this) { _x_vo_scale_compute_output_size( &this->sc ); } -static void xvmc_overlay_blend (vo_driver_t *this_gen, +static void xvmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { xvmc_driver_t *this = (xvmc_driver_t *) this_gen; xvmc_frame_t *frame = (xvmc_frame_t *) frame_gen; lprintf ("xvmc_overlay_blend\n"); - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; /* Alpha Blend here * As XV drivers improve to support Hardware overlay, we will change this function. */ - + if (overlay->rle) { if (frame->format == XINE_IMGFMT_YV12) - _x_blend_yuv(frame->vo_frame.base, overlay, + _x_blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); else if (frame->format != XINE_IMGFMT_XVMC) - _x_blend_yuy2(frame->vo_frame.base[0], overlay, + _x_blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0], &this->alphablend_extra_data); else @@ -898,16 +899,16 @@ static int xvmc_redraw_needed (vo_driver_t *this_gen) { int ret = 0; if(this->cur_frame) { - + this->sc.delivered_height = this->cur_frame->height; this->sc.delivered_width = this->cur_frame->width; this->sc.delivered_ratio = this->cur_frame->ratio; - + this->sc.crop_left = this->cur_frame->vo_frame.crop_left; this->sc.crop_right = this->cur_frame->vo_frame.crop_right; this->sc.crop_top = this->cur_frame->vo_frame.crop_top; this->sc.crop_bottom = this->cur_frame->vo_frame.crop_bottom; - + xvmc_compute_ideal_size(this); if(_x_vo_scale_redraw_needed(&this->sc)) { @@ -928,49 +929,49 @@ static void xvmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { lprintf ("xvmc_display_frame %d %x\n",frame_gen->id,frame_gen); - /* + /* * queue frames (deinterlacing) * free old frames */ - + xvmc_add_recent_frame (this, frame); /* deinterlacing */ - + this->cur_frame = frame; - + /* * let's see if this frame is different in size / aspect * ratio from the previous one */ - + if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { lprintf("frame format changed\n"); - - /* + + /* this->delivered_width = frame->width; this->delivered_height = frame->height; this->delivered_ratio = frame->ratio; this->delivered_duration = frame->vo_frame.duration; - + xvmc_compute_ideal_size (this); */ /* this->gui_width = 0; */ /* trigger re-calc of output size */ this->sc.force_redraw = 1; /* trigger re-calc of output size */ } - - /* + + /* * tell gui that we are about to display a frame, * ask for offset and output size */ xvmc_redraw_needed (this_gen); - + XLockDisplay (this->display); - /* Make sure the surface has finished rendering before we display */ + /* Make sure the surface has finished rendering before we display */ XvMCSyncSurface(this->display, &this->cur_frame->surface); - + if (this->deinterlace_enabled && (this->deinterlace_method == DEINTERLACE_ONEFIELD)) { XvMCPutSurface(this->display, &this->cur_frame->surface, @@ -989,9 +990,9 @@ static void xvmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { this->sc.output_width, this->sc.output_height, XVMC_FRAME_PICTURE); } - + XUnlockDisplay (this->display); - + /* printf ("video_out_xvmc: xvmc_display_frame... done\n"); */ @@ -1001,7 +1002,7 @@ static int xvmc_get_property (vo_driver_t *this_gen, int property) { xvmc_driver_t *this = (xvmc_driver_t *) this_gen; lprintf ("xvmc_get_property\n"); - + switch (property) { case VO_PROP_WINDOW_WIDTH: this->props[property].value = this->sc.gui_width; @@ -1022,7 +1023,7 @@ static int xvmc_get_property (vo_driver_t *this_gen, int property) { this->props[property].value = this->sc.output_yoffset; break; } - + return this->props[property].value; } @@ -1031,7 +1032,7 @@ static void xvmc_property_callback (void *property_gen, xine_cfg_entry_t *entry) xvmc_driver_t *this = property->this; lprintf ("xvmc_property_callback\n"); - + XLockDisplay(this->display); XvSetPortAttribute (this->display, this->xv_port, property->atom, entry->num_value); @@ -1043,7 +1044,7 @@ static int xvmc_set_property (vo_driver_t *this_gen, xvmc_driver_t *this = (xvmc_driver_t *) this_gen; lprintf ("xvmc_set_property %d value %d\n",property,value); - + if (this->props[property].atom != None) { /* value is out of bound */ if((value < this->props[property].min) || (value > this->props[property].max)) @@ -1059,9 +1060,9 @@ static int xvmc_set_property (vo_driver_t *this_gen, if (this->props[property].entry) this->props[property].entry->num_value = this->props[property].value; - + return this->props[property].value; - } + } else { switch (property) { case VO_PROP_INTERLACED: @@ -1080,7 +1081,7 @@ static int xvmc_set_property (vo_driver_t *this_gen, this->props[property].value = value; lprintf("VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value); - + xvmc_compute_ideal_size (this); xvmc_compute_output_size (this); xvmc_clean_output_area (this); @@ -1090,7 +1091,7 @@ static int xvmc_set_property (vo_driver_t *this_gen, case VO_PROP_ZOOM_X: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->props[property].value = value; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xvmc: VO_PROP_ZOOM_X = %d\n", this->props[property].value); this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; @@ -1102,7 +1103,7 @@ static int xvmc_set_property (vo_driver_t *this_gen, case VO_PROP_ZOOM_Y: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->props[property].value = value; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xvmc: VO_PROP_ZOOM_Y = %d\n", this->props[property].value); this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; @@ -1110,7 +1111,7 @@ static int xvmc_set_property (vo_driver_t *this_gen, this->sc.force_redraw = 1; /* trigger re-calc of output size */ } break; - } + } } return value; @@ -1119,9 +1120,9 @@ static int xvmc_set_property (vo_driver_t *this_gen, static void xvmc_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) { xvmc_driver_t *this = (xvmc_driver_t *) this_gen; - + lprintf ("xvmc_get_property_min_max\n"); - + *min = this->props[property].min; *max = this->props[property].max; } @@ -1131,32 +1132,32 @@ static int xvmc_gui_data_exchange (vo_driver_t *this_gen, xvmc_driver_t *this = (xvmc_driver_t *) this_gen; lprintf ("xvmc_gui_data_exchange\n"); - + switch (data_type) { case XINE_GUI_SEND_EXPOSE_EVENT: { /* XExposeEvent * xev = (XExposeEvent *) data; */ /* FIXME : take care of completion events */ lprintf ("XINE_GUI_SEND_EXPOSE_EVENT\n"); - + if (this->cur_frame) { int i; - + XLockDisplay (this->display); - + XSetForeground (this->display, this->gc, this->black.pixel); - + for( i = 0; i < 4; i++ ) { if( this->sc.border[i].w && this->sc.border[i].h ) XFillRectangle(this->display, this->drawable, this->gc, this->sc.border[i].x, this->sc.border[i].y, this->sc.border[i].w, this->sc.border[i].h); } - + if (this->use_colorkey) { XSetForeground (this->display, this->gc, this->colorkey); XFillRectangle (this->display, this->drawable, this->gc, - this->sc.output_xoffset, this->sc.output_yoffset, + this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height); } @@ -1167,7 +1168,7 @@ static int xvmc_gui_data_exchange (vo_driver_t *this_gen, this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_width, this->sc.output_height, XVMC_FRAME_PICTURE); - + XSync(this->display, False); XUnlockDisplay (this->display); } @@ -1186,18 +1187,18 @@ static int xvmc_gui_data_exchange (vo_driver_t *this_gen, int x1, y1, x2, y2; x11_rectangle_t *rect = data; - /* + /* xvmc_translate_gui2video(this, rect->x, rect->y, - &x1, &y1); + &x1, &y1); xvmc_translate_gui2video(this, rect->x + rect->w, rect->y + rect->h, - &x2, &y2); + &x2, &y2); */ - + _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, &x1, &y1); _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, &x2, &y2); - + rect->x = x1; rect->y = y1; rect->w = x2-x1; @@ -1215,9 +1216,9 @@ static int xvmc_gui_data_exchange (vo_driver_t *this_gen, static void xvmc_dispose (vo_driver_t *this_gen) { xvmc_driver_t *this = (xvmc_driver_t *) this_gen; int i; - + lprintf ("xvmc_dispose\n"); - + if(this->context_id.xid) { XLockDisplay(this->display); for(i = 0; i < this->num_frame_buffers; i++) { @@ -1227,7 +1228,7 @@ static void xvmc_dispose (vo_driver_t *this_gen) { } /* XvMCDestroyBlocks(this->display, ¯oblocks->blocks); */ /* XvMCDestroyMacroBlocks(this->display, ¯oblocks->macro_blocks); */ - XvMCDestroyContext(this->display, &this->context); + XvMCDestroyContext(this->display, &this->context); XUnlockDisplay(this->display); } @@ -1252,13 +1253,13 @@ static void xvmc_dispose (vo_driver_t *this_gen) { /* called xlocked */ static void xvmc_check_capability (xvmc_driver_t *this, - int property, XvAttribute attr, - int base_id, char *str_prop, - char *config_name, - char *config_desc, - char *config_help) { + int property, XvAttribute attr, int base_id, + const char *config_name, + const char *config_desc, + const char *config_help) { int int_default; cfg_entry_t *entry; + const char *str_prop = attr.name; /* * some Xv drivers (Gatos ATI) report some ~0 as max values, this is confusing. @@ -1273,21 +1274,21 @@ static void xvmc_check_capability (xvmc_driver_t *this, XvGetPortAttribute (this->display, this->xv_port, this->props[property].atom, &int_default); - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xvmc: port attribute %s (%d) value is %d\n", str_prop, property, int_default); - + if (config_name) { /* is this a boolean property ? */ if ((attr.min_value == 0) && (attr.max_value == 1)) { this->config->register_bool (this->config, config_name, int_default, config_desc, - NULL, 20, xvmc_property_callback, &this->props[property]); - + config_help, 20, xvmc_property_callback, &this->props[property]); + } else { this->config->register_range (this->config, config_name, int_default, this->props[property].min, this->props[property].max, config_desc, - NULL, 20, xvmc_property_callback, &this->props[property]); + config_help, 20, xvmc_property_callback, &this->props[property]); } entry = this->config->lookup_entry (this->config, config_name); @@ -1300,7 +1301,7 @@ static void xvmc_check_capability (xvmc_driver_t *this, this->use_colorkey = 1; this->colorkey = entry->num_value; } - } + } else this->props[property].value = int_default; } @@ -1309,7 +1310,7 @@ static void xvmc_update_deinterlace(void *this_gen, xine_cfg_entry_t *entry) { xvmc_driver_t *this = (xvmc_driver_t *) this_gen; lprintf ("xvmc_update_deinterlace method = %d\n",entry->num_value); - + this->deinterlace_method = entry->num_value; } @@ -1318,7 +1319,7 @@ static void xvmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry xvmc_driver_t *this = (xvmc_driver_t *) this_gen; Atom atom; int xvmc_double_buffer; - + xvmc_double_buffer = entry->num_value; XLockDisplay(this->display); @@ -1333,7 +1334,6 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi xvmc_class_t *class = (xvmc_class_t *) class_gen; config_values_t *config = class->config; xvmc_driver_t *this = NULL; - Display *display = NULL; unsigned int i, formats; XvPortID xv_port = class->xv_port; XvAttribute *attr; @@ -1341,15 +1341,14 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi int nattr; x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; + XvAdaptorInfo *adaptor_info; + unsigned int adaptor_num; /* XvImage *myimage; */ - + lprintf ("open_plugin\n"); - - display = visual->display; - - /* TODO ??? */ - this = (xvmc_driver_t *) xine_xmalloc (sizeof (xvmc_driver_t)); - + + this = calloc(1, sizeof (xvmc_driver_t)); + if (!this) return NULL; @@ -1426,66 +1425,57 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi /* * check this adaptor's capabilities */ - if(this->acceleration&XINE_VO_IDCT_ACCEL) + if(this->acceleration&XINE_VO_IDCT_ACCEL) this->capabilities |= VO_CAP_XVMC_IDCT; - + XLockDisplay(this->display); - attr = XvQueryPortAttributes(display, xv_port, &nattr); + attr = XvQueryPortAttributes(this->display, xv_port, &nattr); if(attr && nattr) { int k; for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { - if(!strcmp(attr[k].name, "XV_HUE")) { - xvmc_check_capability (this, VO_PROP_HUE, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_HUE", - NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + const char *const name = attr[k].name; + if(!strcmp(name, "XV_HUE")) { + if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { + xprintf (this->xine, XINE_VERBOSITY_NONE, LOG_MODULE ": ignoring broken XV_HUE settings on NVidia cards\n"); + } else { + xvmc_check_capability (this, VO_PROP_HUE, attr[k], + adaptor_info[adaptor_num].base_id, + NULL, NULL, NULL); + } + } else if(!strcmp(name, "XV_SATURATION")) { xvmc_check_capability (this, VO_PROP_SATURATION, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_SATURATION", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { xvmc_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_BRIGHTNESS", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xvmc_check_capability (this, VO_PROP_CONTRAST, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_CONTRAST", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xvmc_check_capability (this, VO_PROP_COLORKEY, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xvmc_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], - class->adaptor_info[class->adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xvmc_double_buffer; - xvmc_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), - 20, xvmc_update_XV_DOUBLE_BUFFER, this); + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xvmc_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, + 20, xvmc_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xvmc_double_buffer); } } } XFree(attr); - } + } else { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out_xvmc: no port attributes defined.\n"); } @@ -1494,17 +1484,17 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi /* * check supported image formats */ - fo = XvListImageFormats(display, this->xv_port, (int*)&formats); + fo = XvListImageFormats(this->display, this->xv_port, (int*)&formats); XUnlockDisplay(this->display); this->xvmc_format_yv12 = 0; this->xvmc_format_yuy2 = 0; - + for(i = 0; i < formats; i++) { lprintf ("XvMC image format: 0x%x (%4.4s) %s\n", fo[i].id, (char*)&fo[i].id, (fo[i].format == XvPacked) ? "packed" : "planar"); - + if (fo[i].id == XINE_IMGFMT_YV12) { this->xvmc_format_yv12 = fo[i].id; this->capabilities |= VO_CAP_YV12; @@ -1529,15 +1519,15 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi */ /* XLockDisplay(this->display); - myimage = create_ximage (this, &myshminfo, 100, 100, + myimage = create_ximage (this, &myshminfo, 100, 100, (this->xvmc_format_yv12 != 0) ? XINE_IMGFMT_YV12 : IMGFMT_YUY2); dispose_ximage (this, &myshminfo, myimage); XUnLockDisplay(this->display); */ - + this->deinterlace_method = config->register_enum (config, "video.output.xv_deinterlace_method", 4, - deinterlace_methods, + deinterlace_methods, _("deinterlace method (deprecated)"), _("This config setting is deprecated. You should use the new deinterlacing " "post processing settings instead.\n\n" @@ -1571,26 +1561,26 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi lprintf("deinterlace_methods %d ",this->deinterlace_method); switch(this->deinterlace_method) { - case DEINTERLACE_NONE: - lprintf("NONE\n"); + case DEINTERLACE_NONE: + lprintf("NONE\n"); break; - case DEINTERLACE_BOB: - lprintf("BOB\n"); + case DEINTERLACE_BOB: + lprintf("BOB\n"); break; - case DEINTERLACE_WEAVE: + case DEINTERLACE_WEAVE: lprintf("WEAVE\n"); break; - case DEINTERLACE_GREEDY: + case DEINTERLACE_GREEDY: lprintf("GREEDY\n"); break; - case DEINTERLACE_ONEFIELD: + case DEINTERLACE_ONEFIELD: lprintf("ONEFIELD\n"); break; - case DEINTERLACE_ONEFIELDXV: + case DEINTERLACE_ONEFIELDXV: lprintf("ONEFIELDXV\n"); break; - case DEINTERLACE_LINEARBLEND: - lprintf("LINEARBLEND\n"); + case DEINTERLACE_LINEARBLEND: + lprintf("LINEARBLEND\n"); break; } @@ -1613,10 +1603,6 @@ static char* get_description (video_driver_class_t *this_gen) { static void dispose_class (video_driver_class_t *this_gen) { xvmc_class_t *this = (xvmc_class_t *) this_gen; - XLockDisplay(this->display); - XvFreeAdaptorInfo (this->adaptor_info); - XUnlockDisplay(this->display); - free (this); } @@ -1639,7 +1625,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { int surface_type = 0; display = visual->display; - + /* * check for Xv and XvMC video support */ @@ -1680,20 +1666,20 @@ static void *init_class (xine_t *xine, void *visual_gen) { for(surface_num = 0; surface_num < types; surface_num++) { if((surfaceInfo[surface_num].chroma_format == XVMC_CHROMA_FORMAT_420) && (surfaceInfo[surface_num].mc_type == (XVMC_IDCT | XVMC_MPEG_2))) { - + max_width = surfaceInfo[surface_num].max_width; max_height = surfaceInfo[surface_num].max_height; - + for(j = 0; j < adaptor_info[adaptor_num].num_ports; j++) { /* try to grab a port */ - if(Success == XvGrabPort(display, - adaptor_info[adaptor_num].base_id + j, CurrentTime)) { + if(Success == XvGrabPort(display, + adaptor_info[adaptor_num].base_id + j, CurrentTime)) { xv_port = adaptor_info[adaptor_num].base_id + j; surface_type = surfaceInfo[surface_num].surface_type_id; break; } } - + if(xv_port) break; } @@ -1705,22 +1691,22 @@ static void *init_class (xine_t *xine, void *visual_gen) { for(surface_num = 0; surface_num < types; surface_num++) { if((surfaceInfo[surface_num].chroma_format == XVMC_CHROMA_FORMAT_420) && ((surfaceInfo[surface_num].mc_type == (XVMC_MOCOMP | XVMC_MPEG_2)))) { - + xprintf (xine, XINE_VERBOSITY_DEBUG, "Found XVMC_MOCOMP\n"); max_width = surfaceInfo[surface_num].max_width; max_height = surfaceInfo[surface_num].max_height; for(j = 0; j < adaptor_info[adaptor_num].num_ports; j++) { /* try to grab a port */ - if(Success == XvGrabPort(display, - adaptor_info[adaptor_num].base_id + j, CurrentTime)) { + if(Success == XvGrabPort(display, + adaptor_info[adaptor_num].base_id + j, CurrentTime)) { xv_port = adaptor_info[adaptor_num].base_id + j; surface_type = surfaceInfo[surface_num].surface_type_id; break; } } - if(xv_port) + if(xv_port) break; } } @@ -1728,7 +1714,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { if(xv_port) { lprintf ("port %ld surface %d\n",xv_port,j); - IDCTaccel = 0; + IDCTaccel = 0; if(surfaceInfo[surface_num].flags & XVMC_OVERLAID_SURFACE) useOverlay = 1; if(surfaceInfo[surface_num].flags & XVMC_INTRA_UNSIGNED) @@ -1747,7 +1733,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { } } } /* outer for adaptor_num loop */ - + if (!xv_port) { xprintf (xine, XINE_VERBOSITY_LOG, @@ -1757,13 +1743,13 @@ static void *init_class (xine_t *xine, void *visual_gen) { /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/ XUnlockDisplay(display); return NULL; - } + } else { - xprintf (xine, XINE_VERBOSITY_LOG, + xprintf (xine, XINE_VERBOSITY_LOG, _("video_out_xvmc: using Xv port %ld from adaptor %s\n" " for hardware colour space conversion and scaling\n"), xv_port, adaptor_info[adaptor_num].name); - + if(IDCTaccel&XINE_VO_IDCT_ACCEL) xprintf (xine, XINE_VERBOSITY_LOG, _(" idct and motion compensation acceleration \n")); else if (IDCTaccel&XINE_VO_MOTION_ACCEL) @@ -1775,7 +1761,7 @@ static void *init_class (xine_t *xine, void *visual_gen) { } XUnlockDisplay(display); - + this = (xvmc_class_t *) malloc (sizeof (xvmc_class_t)); if (!this) @@ -1789,8 +1775,6 @@ static void *init_class (xine_t *xine, void *visual_gen) { this->display = display; this->config = xine->config; this->xv_port = xv_port; - this->adaptor_info = adaptor_info; - this->adaptor_num = adaptor_num; this->surface_type_id = surface_type; this->max_surface_width = max_width; this->max_surface_height = max_height; diff --git a/src/video_out/video_out_xxmc.c b/src/video_out/video_out_xxmc.c index 28679e95d..256e2f5a8 100644 --- a/src/video_out/video_out_xxmc.c +++ b/src/video_out/video_out_xxmc.c @@ -1,10 +1,10 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2004, 2008 the xine project * Copyright (C) 2004 the Unichrome project * * This file is part of xine, a free video player. * - * xine is free software; you can redistribute it and/or modify it + * xine is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. @@ -34,17 +34,19 @@ */ - #include "xxmc.h" #include <unistd.h> +#include "xv_common.h" static int gX11Fail; -static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, +static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc_frame_t *frame, int init_macroblocks); static void dispose_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, XvImage *myimage); +VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES; +VIDEO_DEVICE_XV_DECL_PREFER_TYPES; /* * Acceleration level priority. Static for now. It may well turn out that IDCT @@ -67,7 +69,7 @@ static const unsigned int accel_priority[] = { * Additional thread safety, since the plugin may decide to destroy a context * while it's surfaces are still active in the video-out loop. * When / If XvMC libs are reasonably thread-safe, the locks can be made - * more efficient by allowing multiple threads in that do not destroy + * more efficient by allowing multiple threads in that do not destroy * the context or surfaces that may be active in other threads. */ @@ -90,7 +92,7 @@ void xvmc_context_reader_lock(context_lock_t *c) #ifdef XVMC_THREAD_SAFE c->num_readers++; pthread_mutex_unlock(&c->mutex); -#endif +#endif } void xvmc_context_reader_unlock(context_lock_t *c) @@ -101,9 +103,9 @@ void xvmc_context_reader_unlock(context_lock_t *c) if (--(c->num_readers) == 0) { pthread_cond_broadcast(&c->cond); } - } + } #endif - pthread_mutex_unlock(&c->mutex); + pthread_mutex_unlock(&c->mutex); } static void xvmc_context_writer_lock(context_lock_t *c) @@ -113,7 +115,7 @@ static void xvmc_context_writer_lock(context_lock_t *c) while(c->num_readers) { pthread_cond_wait(&c->cond, &c->mutex); } -#endif +#endif } static void xvmc_context_writer_unlock(context_lock_t *c) @@ -129,47 +131,42 @@ static void xvmc_context_writer_unlock(context_lock_t *c) -static void xxmc_xvmc_dump_surfaces(xxmc_driver_t *this ) +static void xxmc_xvmc_dump_surfaces(xxmc_driver_t *this ) { int i; xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; for (i=0; i<XVMC_MAX_SURFACES; ++i) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "%d %d;",handler->surfInUse[i], + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "%d %d;",handler->surfInUse[i], handler->surfValid[i]); } - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "\n"); + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "\n"); } -static void xxmc_xvmc_dump_subpictures(xxmc_driver_t *this) +static void xxmc_xvmc_dump_subpictures(xxmc_driver_t *this) { int i; xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "%d %d;",handler->subInUse[i], + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "%d %d;",handler->subInUse[i], handler->subValid[i]); } - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "\n"); + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "\n"); } -static void xxmc_xvmc_surface_handler_construct(xxmc_driver_t *this) +static void xxmc_xvmc_surface_handler_construct(xxmc_driver_t *this) { - int i; xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; pthread_mutex_init(&handler->mutex,NULL); - for (i=0; i<XVMC_MAX_SURFACES; ++i) { - handler->surfInUse[i] = 0; - handler->surfValid[i] = 0; - } - for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) { - handler->subInUse[i] = 0; - handler->subValid[i] = 0; - } + memset(handler->surfInUse, 0, sizeof(handler->surfInUse)); + memset(handler->surfValid, 0, sizeof(handler->surfValid)); + memset(handler->subInUse, 0, sizeof(handler->subInUse)); + memset(handler->subValid, 0, sizeof(handler->subValid)); } static void xxmc_xvmc_destroy_surfaces(xxmc_driver_t *this) @@ -211,11 +208,11 @@ static void xxmc_xvmc_destroy_subpictures(xxmc_driver_t *this) } pthread_mutex_unlock(&handler->mutex); } - -static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this, + +static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this, XvMCContext *context) { - xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; + xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; int i; pthread_mutex_lock(&handler->mutex); @@ -231,7 +228,7 @@ static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this, for (i=0; i<XVMC_MAX_SURFACES; ++i) { if (!handler->surfInUse[i]) { XVMCLOCKDISPLAY( this->display ); - if (Success != XvMCCreateSurface( this->display, context, + if (Success != XvMCCreateSurface( this->display, context, handler->surfaces + i)) { XVMCUNLOCKDISPLAY( this->display ); pthread_mutex_unlock(&handler->mutex); @@ -250,13 +247,13 @@ static XvMCSurface *xxmc_xvmc_alloc_surface(xxmc_driver_t *this, return NULL; } -static void xxmc_xvmc_free_surface(xxmc_driver_t *this, XvMCSurface *surf) +static void xxmc_xvmc_free_surface(xxmc_driver_t *this, XvMCSurface *surf) { xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; unsigned index = surf - handler->surfaces; - if (index >= XVMC_MAX_SURFACES) return; + if (index >= XVMC_MAX_SURFACES) return; pthread_mutex_lock(&handler->mutex); xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Disposing of surface %d\n",index); @@ -280,7 +277,7 @@ int xxmc_xvmc_surface_valid(xxmc_driver_t *this, XvMCSurface *surf) } static XvMCSubpicture *xxmc_xvmc_alloc_subpicture - (xxmc_driver_t *this, + (xxmc_driver_t *this, XvMCContext *context, unsigned short width, unsigned short height, int xvimage_id) { @@ -293,7 +290,7 @@ static XvMCSubpicture *xxmc_xvmc_alloc_subpicture for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) { if (handler->subValid[i] && !handler->subInUse[i]) { XVMCLOCKDISPLAY( this->display ); - if (XvMCGetSubpictureStatus( this->display, handler->subpictures + i, + if (XvMCGetSubpictureStatus( this->display, handler->subpictures + i, &status)) { XVMCUNLOCKDISPLAY( this->display ); continue; @@ -310,7 +307,7 @@ static XvMCSubpicture *xxmc_xvmc_alloc_subpicture for (i=0; i<XVMC_MAX_SUBPICTURES; ++i) { if (!handler->subInUse[i]) { XVMCLOCKDISPLAY( this->display ); - if (Success != XvMCCreateSubpicture( this->display, context, + if (Success != XvMCCreateSubpicture( this->display, context, handler->subpictures + i, width, height, xvimage_id)) { XVMCUNLOCKDISPLAY( this->display ); @@ -330,14 +327,14 @@ static XvMCSubpicture *xxmc_xvmc_alloc_subpicture return NULL; } -static void xxmc_xvmc_free_subpicture(xxmc_driver_t *this, XvMCSubpicture *sub) +static void xxmc_xvmc_free_subpicture(xxmc_driver_t *this, XvMCSubpicture *sub) { xvmc_surface_handler_t *handler = &this->xvmc_surf_handler; unsigned index = sub - handler->subpictures; - if (index >= XVMC_MAX_SUBPICTURES) return; + if (index >= XVMC_MAX_SUBPICTURES) return; pthread_mutex_lock(&handler->mutex); xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Disposing of subpicture %d\n",index); @@ -349,7 +346,7 @@ static void xxmc_xvmc_free_subpicture(xxmc_driver_t *this, XvMCSubpicture *sub) /* * Callback used by decoder to check that surfaces are still valid, - * and to lock the context so that it won't get destroyed during + * and to lock the context so that it won't get destroyed during * decoding. */ @@ -359,9 +356,9 @@ static int xxmc_lock_and_validate_surfaces(vo_frame_t *cur_frame, vo_frame_t *bw_frame, unsigned pc_type) { - xxmc_driver_t + xxmc_driver_t *driver = (xxmc_driver_t *) cur_frame->driver; - xxmc_frame_t + xxmc_frame_t *frame; xvmc_context_reader_lock( &driver->xvmc_lock ); @@ -380,7 +377,7 @@ static int xxmc_lock_and_validate_surfaces(vo_frame_t *cur_frame, if (!xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) break; return 0; } - + xvmc_context_reader_unlock( &driver->xvmc_lock ); return -1; } @@ -391,19 +388,19 @@ static int xxmc_lock_and_validate_surfaces(vo_frame_t *cur_frame, static void xxmc_unlock_surfaces(vo_driver_t *this_gen) { - xxmc_driver_t + xxmc_driver_t *driver = (xxmc_driver_t *) this_gen; - + xvmc_context_reader_unlock( &driver->xvmc_lock ); } /* - * Callback for decoder. - * Check that the surface is vaid and + * Callback for decoder. + * Check that the surface is vaid and * flush outstanding rendering requests on this surface. */ -static void xvmc_flush(vo_frame_t *this_gen) +static void xvmc_flush(vo_frame_t *this_gen) { xxmc_frame_t @@ -415,7 +412,7 @@ static void xvmc_flush(vo_frame_t *this_gen) if ( ! xxmc_xvmc_surface_valid( driver, frame->xvmc_surf)) { frame->xxmc_data.result = 128; - xvmc_context_reader_unlock( &driver->xvmc_lock ); + xvmc_context_reader_unlock( &driver->xvmc_lock ); return; } @@ -435,10 +432,10 @@ static void xvmc_flush(vo_frame_t *this_gen) * using a call to XvMCBlendSubpicture2 with a blank subpicture. */ -static void xxmc_duplicate_frame_data(vo_frame_t *this_gen, - vo_frame_t *original) +static void xxmc_duplicate_frame_data(vo_frame_t *this_gen, + vo_frame_t *original) { - xxmc_frame_t *this = (xxmc_frame_t *) this_gen, + xxmc_frame_t *this = (xxmc_frame_t *) this_gen, *orig = (xxmc_frame_t *) original; xxmc_driver_t *driver = (xxmc_driver_t *) this_gen->driver; xine_t *xine = driver->xine; @@ -453,25 +450,25 @@ static void xxmc_duplicate_frame_data(vo_frame_t *this_gen, if (!xxmc_xvmc_surface_valid(driver,orig->xvmc_surf)) { xvmc_context_writer_unlock( &driver->xvmc_lock ); return; - } + } this->xxmc_data = *xxmc; this->width = original->width; this->height = original->height; this->format = original->format; this->ratio = original->ratio; - - xxmc_frame_updates(driver,this,0); + + xxmc_frame_updates(driver,this,0); /* - * Allocate a dummy subpicture and copy using - * XvMCBlendsubpicture2. VLD implementations can do blending with a + * Allocate a dummy subpicture and copy using + * XvMCBlendsubpicture2. VLD implementations can do blending with a * NULL subpicture. Use that if possible. */ need_dummy = (xxmc->acceleration != XINE_XVMC_ACCEL_VLD); tmp = NULL; if (need_dummy) { - tmp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, + tmp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, this->width, this->height, driver->xvmc_cap [driver->xvmc_cur_cap].subPicType.id); @@ -480,20 +477,20 @@ static void xxmc_duplicate_frame_data(vo_frame_t *this_gen, XVMCLOCKDISPLAY( driver->display ); if (tmp) XvMCClearSubpicture(driver->display, tmp , 0,0, this->width, this->height, 0); - if (Success == XvMCBlendSubpicture2( driver->display, orig->xvmc_surf, + if (Success == XvMCBlendSubpicture2( driver->display, orig->xvmc_surf, this->xvmc_surf, tmp, - 0,0,this->width, this->height, + 0,0,this->width, this->height, 0,0,this->width, this->height)) { this->xxmc_data.decoded = 1; } XVMCUNLOCKDISPLAY( driver->display ); if (tmp) xxmc_xvmc_free_subpicture( driver, tmp); } - + xvmc_context_writer_unlock( &driver->xvmc_lock ); xprintf(xine, XINE_VERBOSITY_DEBUG, "Duplicated XvMC frame %d %d.\n", this->width,this->height); -} +} static uint32_t xxmc_get_capabilities (vo_driver_t *this_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; @@ -502,7 +499,7 @@ static uint32_t xxmc_get_capabilities (vo_driver_t *this_gen) { } -static void xxmc_frame_field (vo_frame_t *vo_img, int which_field) +static void xxmc_frame_field (vo_frame_t *vo_img, int which_field) { lprintf ("xvmc_frame_field\n"); } @@ -547,13 +544,13 @@ static void xxmc_frame_dispose (vo_frame_t *vo_img) { */ static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) { - xxmc_driver_t *this = (xxmc_driver_t *) this_gen; + xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame ; - frame = (xxmc_frame_t *) xine_xmalloc (sizeof (xxmc_frame_t)); + frame = calloc(1, sizeof (xxmc_frame_t)); if (!frame) return NULL; - + pthread_mutex_init (&frame->vo_frame.mutex, NULL); frame->xvmc_surf = NULL; @@ -578,7 +575,7 @@ static vo_frame_t *xxmc_alloc_frame (vo_driver_t *this_gen) { static int HandleXError (Display *display, XErrorEvent *xevent) { char str [1024]; - + XGetErrorText (display, xevent->error_code, str, 1024); printf ("received X error event: %s\n", str); gX11Fail = 1; @@ -610,7 +607,7 @@ static XvImage *create_ximage (xxmc_driver_t *this, XShmSegmentInfo *shminfo, } switch (format) { - case XINE_IMGFMT_YV12: + case XINE_IMGFMT_YV12: xv_format = this->xv_format_yv12; break; case XINE_IMGFMT_YUY2: @@ -756,7 +753,7 @@ static void xxmc_dispose_context(xxmc_driver_t *driver) XvMCDestroyMacroBlocks( driver->display, ¯oblocks->macro_blocks ); XvMCDestroyBlocks( driver->display , ¯oblocks->blocks ); } - + xprintf(driver->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: Freeing up XvMC Surfaces and subpictures.\n"); if (driver->xvmc_palette) free(driver->xvmc_palette); @@ -766,15 +763,15 @@ static void xxmc_dispose_context(xxmc_driver_t *driver) xprintf(driver->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: Freeing up XvMC Context.\n"); XLockDisplay (driver->display); - if (driver->subImage) - dispose_ximage(driver, &driver->subShmInfo, driver->subImage); + if (driver->subImage) + dispose_ximage(driver, &driver->subShmInfo, driver->subImage); driver->subImage = NULL; XUnlockDisplay (driver->display); XVMCLOCKDISPLAY( driver->display ); XvMCDestroyContext( driver->display, &driver->context); XVMCUNLOCKDISPLAY( driver->display ); driver->contextActive = 0; - driver->hwSubpictures = 0; + driver->hwSubpictures = 0; driver->xvmc_accel = 0; } } @@ -782,7 +779,7 @@ static void xxmc_dispose_context(xxmc_driver_t *driver) /* * Find a suitable XvMC Context according to the acceleration request * passed to us in the xxmc variable, and to the acceleration type - * priority set up in this plugin. Result is returned in + * priority set up in this plugin. Result is returned in * driver->xvmc_cur_cap. */ @@ -796,7 +793,7 @@ static int xxmc_find_context(xxmc_driver_t *driver, xine_xxmc_t *xxmc, request_mpeg_flags = xxmc->mpeg; found = 0; curCap = NULL; - + for (k = 0; k < NUM_ACCEL_PRIORITY; ++k) { request_accel_flags = xxmc->acceleration & accel_priority[k]; if (!request_accel_flags) continue; @@ -830,7 +827,7 @@ static int xxmc_find_context(xxmc_driver_t *driver, xine_xxmc_t *xxmc, } driver->xvmc_accel = 0; return 0; -} +} static int xxmc_create_context(xxmc_driver_t *driver, unsigned width, unsigned height) { @@ -840,9 +837,9 @@ static int xxmc_create_context(xxmc_driver_t *driver, unsigned width, unsigned h xprintf(driver->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: Creating new XvMC Context %d\n",curCap->type_id); XVMCLOCKDISPLAY( driver->display ); - if (Success == XvMCCreateContext( driver->display, driver->xv_port, + if (Success == XvMCCreateContext( driver->display, driver->xv_port, curCap->type_id, width, - height, driver->context_flags, + height, driver->context_flags, &driver->context)) { driver->xvmc_mpeg = curCap->mpeg_flags; driver->xvmc_width = width; @@ -863,26 +860,26 @@ static void xxmc_setup_subpictures(xxmc_driver_t *driver, unsigned width, unsign /* * Determine if we can use hardware subpictures, and in that case, set up an * XvImage that we can use for blending. - */ + */ curCap = driver->xvmc_cap + driver->xvmc_cur_cap; - if ((width > curCap->sub_max_width) || + if ((width > curCap->sub_max_width) || (height > curCap->sub_max_height)) return; - if ((driver->xvmc_backend_subpic = (curCap->flags & XVMC_BACKEND_SUBPICTURE))) + if ((driver->xvmc_backend_subpic = (curCap->flags & XVMC_BACKEND_SUBPICTURE))) xprintf(driver->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: Using Backend subpictures.\n"); - + if (!driver->subImage) { /* * Note: If other image formats than xx44 are to be used here, they must be - * translated to XINE_IMGFMT_XXX, since that is what create_ximage + * translated to XINE_IMGFMT_XXX, since that is what create_ximage * expects. */ XLockDisplay (driver->display); - driver->subImage = + driver->subImage = create_ximage(driver, &driver->subShmInfo, width, height, curCap->subPicType.id); XUnlockDisplay (driver->display); if (NULL == driver->subImage) { @@ -892,15 +889,15 @@ static void xxmc_setup_subpictures(xxmc_driver_t *driver, unsigned width, unsign } } - sp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, width, + sp = xxmc_xvmc_alloc_subpicture( driver, &driver->context, width, height, curCap->subPicType.id); if (sp == NULL) return; _x_init_xx44_palette( &driver->palette, sp->num_palette_entries); - driver->xvmc_palette = (char *) xine_xmalloc(sp->num_palette_entries + driver->xvmc_palette = (char *) xine_xmalloc(sp->num_palette_entries * sp->entry_bytes); xxmc_xvmc_free_subpicture( driver, sp); - if (driver->xvmc_palette == NULL) return; + if (driver->xvmc_palette == NULL) return; driver->hwSubpictures = 1; } } @@ -930,8 +927,8 @@ static int xxmc_mocomp_create_macroblocks(xxmc_driver_t *driver, xxmc->xvmc.macroblocks = (xine_macroblocks_t *)macroblocks; return 1; -} - +} + static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) { int num,i; @@ -946,7 +943,7 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) driver->have_xvmc_autopaint = 0; if (driver->context_flags & XVMC_OVERLAID_SURFACE) { XVMCLOCKDISPLAY( driver->display ); - xvmc_attributes = XvMCQueryAttributes( driver->display, + xvmc_attributes = XvMCQueryAttributes( driver->display, &driver->context, &num); if (xvmc_attributes) { @@ -956,7 +953,7 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) XvMCSetAttribute(driver->display, &driver->context,ap, driver->props[VO_PROP_AUTOPAINT_COLORKEY].value); driver->have_xvmc_autopaint = 1; - } + } } } XFree(xvmc_attributes); @@ -969,16 +966,16 @@ static void xvmc_check_colorkey_properties(xxmc_driver_t *driver) static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame, - uint32_t width, uint32_t height, int frame_format_xxmc) + uint32_t width, uint32_t height, int frame_format_xxmc) { xine_xxmc_t *xxmc = &frame->xxmc_data; /* * Are we at all capable of doing XvMC ? - */ + */ + - - if (driver->xvmc_cap == 0) + if (driver->xvmc_cap == 0) return 0; xprintf(driver->xine, XINE_VERBOSITY_LOG, @@ -989,18 +986,18 @@ static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame, " mpeg: %d acceleration: %d", xxmc->mpeg, xxmc->acceleration); } xprintf(driver->xine, XINE_VERBOSITY_LOG, "\n"); - + if (frame->xvmc_surf) xxmc_xvmc_free_surface( driver , frame->xvmc_surf); frame->xvmc_surf = NULL; xxmc_dispose_context( driver ); - + if (frame_format_xxmc && xxmc_find_context( driver, xxmc, width, height )) { xxmc_create_context( driver, width, height); xvmc_check_colorkey_properties( driver ); xxmc_setup_subpictures(driver, width, height); - if ((driver->xvmc_accel & + if ((driver->xvmc_accel & (XINE_XVMC_ACCEL_MOCOMP | XINE_XVMC_ACCEL_IDCT))) { if (!xxmc_mocomp_create_macroblocks(driver, frame, 1)) { lprintf("video_out_xxmc: ERROR: Macroblock allocation failed\n"); @@ -1015,15 +1012,15 @@ static int xxmc_xvmc_update_context(xxmc_driver_t *driver, xxmc_frame_t *frame, } else { printf("video_out_xxmc: Using hardware decoding for this stream.\n"); } - + driver->xvmc_mpeg = xxmc->mpeg; driver->xvmc_width = width; driver->xvmc_height = height; return driver->contextActive; } -static void xxmc_frame_updates(xxmc_driver_t *driver, - xxmc_frame_t *frame, +static void xxmc_frame_updates(xxmc_driver_t *driver, + xxmc_frame_t *frame, int init_macroblocks) { xine_xxmc_t *xxmc = &frame->xxmc_data; @@ -1044,10 +1041,10 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, /* * If it is NULL create a new surface. - */ + */ if (frame->xvmc_surf == NULL) { - if (NULL == (frame->xvmc_surf = + if (NULL == (frame->xvmc_surf = xxmc_xvmc_alloc_surface( driver, &driver->context))) { fprintf(stderr, "video_out_xxmc: ERROR: Accelerated surface allocation failed.\n" "video_out_xxmc: You are probably out of framebuffer memory.\n" @@ -1055,7 +1052,7 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, driver->xvmc_accel = 0; xxmc_dispose_context( driver ); return; - } + } xxmc->xvmc.macroblocks = (xine_macroblocks_t *) &driver->macroblocks; xxmc->xvmc.macroblocks->xvmc_accel = (driver->unsigned_intra) ? 0 : XINE_VO_SIGNED_INTRA; @@ -1074,7 +1071,7 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, xxmc->proc_xxmc_flush = xvmc_flush; xxmc->proc_xxmc_lock_valid = xxmc_lock_and_validate_surfaces; xxmc->proc_xxmc_unlock = xxmc_unlock_surfaces; - + xxmc->xvmc.proc_macro_block = xxmc_xvmc_proc_macro_block; frame->vo_frame.proc_duplicate_frame_data = xxmc_duplicate_frame_data; #ifdef HAVE_VLDXVMC @@ -1086,7 +1083,7 @@ static void xxmc_frame_updates(xxmc_driver_t *driver, if (init_macroblocks) { driver->macroblocks.num_blocks = 0; driver->macroblocks.macroblockptr = driver->macroblocks.macroblockbaseptr; - driver->macroblocks.xine_mc.blockptr = + driver->macroblocks.xine_mc.blockptr = driver->macroblocks.xine_mc.blockbaseptr; } xxmc->acceleration = driver->xvmc_accel; @@ -1108,7 +1105,7 @@ static void dispose_ximage (xxmc_driver_t *this, shminfo->shmid = -1; } - } + } else { if (myimage->data) free(myimage->data); XFree (myimage); @@ -1128,29 +1125,29 @@ static void xxmc_do_update_frame_xv(vo_driver_t *this_gen, if (this->use_pitch_alignment) { width = (width + 7) & ~0x7; } - + if ((frame->width != width) || (frame->height != height) || (frame->last_sw_format != format)) { - + frame->last_sw_format = format; XLockDisplay (this->display); - + /* * (re-) allocate xvimage */ - + if (frame->image) { dispose_ximage (this, &frame->shminfo, frame->image); frame->image = NULL; } - + frame->image = create_ximage (this, &frame->shminfo, width, height, format); - + if(format == XINE_IMGFMT_YUY2) { frame->vo_frame.pitches[0] = frame->image->pitches[0]; frame->vo_frame.base[0] = frame->image->data + frame->image->offsets[0]; - } + } else { frame->vo_frame.pitches[0] = frame->image->pitches[0]; frame->vo_frame.pitches[1] = frame->image->pitches[2]; @@ -1159,14 +1156,14 @@ static void xxmc_do_update_frame_xv(vo_driver_t *this_gen, frame->vo_frame.base[1] = frame->image->data + frame->image->offsets[2]; frame->vo_frame.base[2] = frame->image->data + frame->image->offsets[1]; } - + XUnlockDisplay (this->display); } frame->ratio = ratio; frame->width = width; frame->height = height; - frame->format = format; + frame->format = format; frame->vo_frame.format = frame->format; } @@ -1183,7 +1180,7 @@ static int xxmc_accel_update(xxmc_driver_t *driver, /* * Same acceleration request. No need to change. - */ + */ if (last_request == new_request) return 0; @@ -1202,7 +1199,7 @@ static int xxmc_accel_update(xxmc_driver_t *driver, if (new_request & accel_priority[k]) return 1; } - /* + /* * Should never get here. */ @@ -1232,10 +1229,10 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen, this->last_accel_request = xxmc->acceleration; } - if (this->contextActive) + if (this->contextActive) xxmc_frame_updates(this, frame, 1); - xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio, + xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio, xxmc->fallback_format, flags); if (!this->contextActive) { @@ -1248,7 +1245,7 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen, } xvmc_context_writer_unlock( &this->xvmc_lock); - + } else { /* switch back to an unaccelerated context */ if (this->last_accel_request != 0xFFFFFFFF) { @@ -1256,7 +1253,7 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen, xxmc_xvmc_update_context(this, frame, width, height, 0); } frame->vo_frame.proc_duplicate_frame_data = NULL; - xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio, + xxmc_do_update_frame_xv(this_gen, frame_gen, width, height, ratio, format, flags); } } @@ -1264,7 +1261,7 @@ static void xxmc_do_update_frame(vo_driver_t *this_gen, static void xxmc_update_frame_format(vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, - double ratio, int format, int flags) + double ratio, int format, int flags) { if (format != XINE_IMGFMT_XXMC) { @@ -1282,7 +1279,7 @@ static void xxmc_update_frame_format(vo_driver_t *this_gen, xine_xxmc_t *xxmc = (xine_xxmc_t *)frame_gen->accel_data; xxmc->decoded = 0; xxmc->proc_xxmc_update_frame = xxmc_do_update_frame; - frame_gen->proc_duplicate_frame_data = xxmc_duplicate_frame_data; + frame_gen->proc_duplicate_frame_data = xxmc_duplicate_frame_data; } } @@ -1304,16 +1301,16 @@ static int xxmc_clean_output_area (xxmc_driver_t *this, int xvmc_active) { this->sc.border[i].w, this->sc.border[i].h); } } - + /* * XvMC does not support autopainting regardless of whether there's an - * Xv attribute for it. However, if there is an XvMC attribute for - * autopainting, we should be able to assume it is supported. + * Xv attribute for it. However, if there is an XvMC attribute for + * autopainting, we should be able to assume it is supported. * That support is checked whenever a context is changed. */ - autopainting = (this->props[VO_PROP_AUTOPAINT_COLORKEY].value == 1); - if ((xvmc_active && + autopainting = (this->props[VO_PROP_AUTOPAINT_COLORKEY].value == 1); + if ((xvmc_active && (this->context_flags & XVMC_OVERLAID_SURFACE) && (! this->have_xvmc_autopaint || ! autopainting)) || @@ -1326,12 +1323,12 @@ static int xxmc_clean_output_area (xxmc_driver_t *this, int xvmc_active) { } else { ret = 0; } - + if (this->xoverlay) { x11osd_resize (this->xoverlay, this->sc.gui_width, this->sc.gui_height); this->ovl_changed = 1; } - + XUnlockDisplay (this->display); return ret; } @@ -1357,11 +1354,11 @@ static void xxmc_compute_output_size (xxmc_driver_t *this) { } -static void xxmc_check_xoverlay_type(xxmc_driver_t *driver, xxmc_frame_t *frame) +static void xxmc_check_xoverlay_type(xxmc_driver_t *driver, xxmc_frame_t *frame) { int - new_overlay_type = (frame->format == XINE_IMGFMT_XXMC) ? + new_overlay_type = (frame->format == XINE_IMGFMT_XXMC) ? driver->xvmc_xoverlay_type : driver->xv_xoverlay_type; if (driver->xoverlay_type != new_overlay_type) { printf("Warning! Changing xoverlay\n"); @@ -1374,40 +1371,40 @@ static void xxmc_check_xoverlay_type(xxmc_driver_t *driver, xxmc_frame_t *frame) } -static void xxmc_overlay_begin (vo_driver_t *this_gen, +static void xxmc_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; this->ovl_changed += changed; - + xvmc_context_reader_lock( &this->xvmc_lock ); - if ((frame->format == XINE_IMGFMT_XXMC) && + if ((frame->format == XINE_IMGFMT_XXMC) && !xxmc_xvmc_surface_valid(this, frame->xvmc_surf)) { xvmc_context_reader_unlock( &this->xvmc_lock ); return; } if( this->ovl_changed && this->xoverlay ) { - + XLockDisplay (this->display); xxmc_check_xoverlay_type(this, frame); - x11osd_clear(this->xoverlay); + x11osd_clear(this->xoverlay); XUnlockDisplay (this->display); - } - if (this->ovl_changed && (frame->format == XINE_IMGFMT_XXMC) && + } + if (this->ovl_changed && (frame->format == XINE_IMGFMT_XXMC) && this->hwSubpictures ) { this->new_subpic = xxmc_xvmc_alloc_subpicture - ( this, &this->context, this->xvmc_width, - this->xvmc_height, + ( this, &this->context, this->xvmc_width, + this->xvmc_height, this->xvmc_cap[this->xvmc_cur_cap].subPicType.id); if (this->new_subpic) { this->first_overlay = 1; XVMCLOCKDISPLAY( this->display ); - XvMCClearSubpicture(this->display, this->new_subpic, 0,0, + XvMCClearSubpicture(this->display, this->new_subpic, 0,0, this->xvmc_width, this->xvmc_height, 0x00); XVMCUNLOCKDISPLAY( this->display ); @@ -1415,22 +1412,22 @@ static void xxmc_overlay_begin (vo_driver_t *this_gen, } } xvmc_context_reader_unlock( &this->xvmc_lock ); - + this->alphablend_extra_data.offset_x = frame_gen->overlay_offset_x; this->alphablend_extra_data.offset_y = frame_gen->overlay_offset_y; } -static void xxmc_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) +static void xxmc_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame = (xxmc_frame_t *) vo_img; - + if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); x11osd_expose(this->xoverlay); XUnlockDisplay (this->display); - } + } if ((frame->format == XINE_IMGFMT_XXMC) && this->hwSubpictures) { LOCK_AND_SURFACE_VALID( this, frame->xvmc_surf ); if (this->ovl_changed) { @@ -1447,7 +1444,7 @@ static void xxmc_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) this->reverse_nvidia_palette ? "YVU" : this->old_subpic->component_order); XVMCLOCKDISPLAY( this->display ); - XvMCSetSubpicturePalette( this->display, this->old_subpic, + XvMCSetSubpicturePalette( this->display, this->old_subpic, this->xvmc_palette); XvMCFlushSubpicture( this->display , this->old_subpic); XvMCSyncSubpicture( this->display, this->old_subpic ); @@ -1458,14 +1455,14 @@ static void xxmc_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) XVMCLOCKDISPLAY( this->display ); if (this->xvmc_backend_subpic ) { XvMCBlendSubpicture( this->display, frame->xvmc_surf, - this->old_subpic,0,0,this->xvmc_width, + this->old_subpic,0,0,this->xvmc_width, this->xvmc_height, 0, 0, this->xvmc_width, this->xvmc_height ); } else { - XvMCBlendSubpicture2( this->display, frame->xvmc_surf, + XvMCBlendSubpicture2( this->display, frame->xvmc_surf, frame->xvmc_surf, - this->old_subpic, 0,0,this->xvmc_width, - this->xvmc_height,0,0,this->xvmc_width, + this->old_subpic, 0,0,this->xvmc_width, + this->xvmc_height,0,0,this->xvmc_width, this->xvmc_height); } XVMCUNLOCKDISPLAY( this->display ); @@ -1476,8 +1473,8 @@ static void xxmc_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) } -static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, - vo_overlay_t *overlay) +static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, + vo_overlay_t *overlay) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; @@ -1487,7 +1484,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, if( overlay->unscaled ) { if( this->ovl_changed && this->xoverlay ) { XLockDisplay (this->display); - x11osd_blend(this->xoverlay, overlay); + x11osd_blend(this->xoverlay, overlay); XUnlockDisplay (this->display); } } else if (frame->format == XINE_IMGFMT_XXMC) { @@ -1500,7 +1497,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, this->subImage->height); this->first_overlay = 0; } - _x_blend_xx44(this->subImage->data, overlay, this->subImage->width, + _x_blend_xx44(this->subImage->data, overlay, this->subImage->width, this->subImage->height, this->subImage->width, &this->alphablend_extra_data, &this->palette, (this->subImage->id == FOURCC_IA44)); @@ -1512,7 +1509,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, y1 = y0 + overlay->height; w = this->subImage->width; h = this->subImage->height; - + x0 = (x0 < 0) ? 0 : ((x0 > w) ? w : x0); y0 = (y0 < 0) ? 0 : ((y0 > h) ? h : y0); x1 = (x1 < 0) ? 0 : ((x1 > w) ? w : x1); @@ -1521,22 +1518,22 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, /* anything left after clipping? */ if (x0 != x1 && y0 != y1) { XVMCLOCKDISPLAY( this->display ); - XvMCCompositeSubpicture( this->display, this->new_subpic, - this->subImage, + XvMCCompositeSubpicture( this->display, this->new_subpic, + this->subImage, x0, y0, x1 - x0, y1 - y0, x0, y0); XVMCUNLOCKDISPLAY( this->display ); } - xvmc_context_reader_unlock( &this->xvmc_lock ); + xvmc_context_reader_unlock( &this->xvmc_lock ); } } - } else { + } else { if (frame->format == XINE_IMGFMT_YV12) { - _x_blend_yuv(frame->vo_frame.base, overlay, + _x_blend_yuv(frame->vo_frame.base, overlay, frame->width, frame->height, frame->vo_frame.pitches, &this->alphablend_extra_data); } else { - _x_blend_yuy2(frame->vo_frame.base[0], overlay, + _x_blend_yuy2(frame->vo_frame.base[0], overlay, frame->width, frame->height, frame->vo_frame.pitches[0], &this->alphablend_extra_data); } @@ -1544,7 +1541,7 @@ static void xxmc_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, } } -static void xxmc_add_recent_frame (xxmc_driver_t *this, xxmc_frame_t *frame) +static void xxmc_add_recent_frame (xxmc_driver_t *this, xxmc_frame_t *frame) { int i; i = VO_NUM_RECENT_FRAMES-1; @@ -1558,11 +1555,11 @@ static void xxmc_add_recent_frame (xxmc_driver_t *this, xxmc_frame_t *frame) this->recent_frames[0] = frame; } -static int xxmc_redraw_needed (vo_driver_t *this_gen) +static int xxmc_redraw_needed (vo_driver_t *this_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; int ret = 0; - + if( this->cur_frame ) { this->sc.delivered_height = this->cur_frame->height; @@ -1579,8 +1576,8 @@ static int xxmc_redraw_needed (vo_driver_t *this_gen) if( _x_vo_scale_redraw_needed( &this->sc ) ) { xxmc_compute_output_size (this); - - xxmc_clean_output_area + + xxmc_clean_output_area (this, (this->cur_frame->format == XINE_IMGFMT_XXMC)); ret = 1; @@ -1592,7 +1589,7 @@ static int xxmc_redraw_needed (vo_driver_t *this_gen) return ret; } -static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) +static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; xxmc_frame_t *frame = (xxmc_frame_t *) frame_gen; @@ -1611,8 +1608,8 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) * other than 100 %, so let's disable deinterlacing at all for this frame */ if (this->deinterlace_enabled && this->bob) { - disable_deinterlace = this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame - || this->disable_bob_for_scaled_osd && this->scaled_osd_active + disable_deinterlace = (this->disable_bob_for_progressive_frames && frame->vo_frame.progressive_frame) + || (this->disable_bob_for_scaled_osd && this->scaled_osd_active) || !frame->vo_frame.stream || xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) != XINE_FINE_SPEED_NORMAL; if (!disable_deinterlace) { @@ -1626,7 +1623,7 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) * reset this flag now -- it will be set again before the next call to * xxmc_display_frame() as long as there is a scaled OSD active on screen. */ - this->scaled_osd_active = 0; + this->scaled_osd_active = 0; /* * queue frames (deinterlacing) @@ -1684,7 +1681,7 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height, + this->sc.output_width, this->sc.output_height, this->cur_field); XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XVMCUNLOCKDISPLAY( this->display ); @@ -1720,12 +1717,12 @@ static void xxmc_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height, + this->sc.output_width, this->sc.output_height, this->cur_field); XUnlockDisplay( this->display ); /* unblocks XINE_GUI_SEND_DRAWABLE_CHANGED from changing drawable */ XVMCUNLOCKDISPLAY( this->display ); } - } + } } else { XLockDisplay (this->display); if (this->use_shm) { @@ -1792,7 +1789,7 @@ static void xxmc_property_callback (void *property_gen, xine_cfg_entry_t *entry) if (this->contextActive) { XVMCLOCKDISPLAY( this->display ); XvMCSetAttribute(this->display, &this->context, - property->atom, + property->atom, entry->num_value); XVMCUNLOCKDISPLAY( this->display ); } @@ -1812,7 +1809,7 @@ static int xxmc_set_property (vo_driver_t *this_gen, if (this->contextActive) { XVMCLOCKDISPLAY( this->display ); XvMCSetAttribute(this->display, &this->context, - this->props[property].atom, + this->props[property].atom, value); XVMCUNLOCKDISPLAY( this->display ); } @@ -1830,7 +1827,7 @@ static int xxmc_set_property (vo_driver_t *this_gen, this->props[property].entry->num_value = this->props[property].value; return this->props[property].value; - } + } else { switch (property) { @@ -1846,7 +1843,7 @@ static int xxmc_set_property (vo_driver_t *this_gen, value = XINE_VO_ASPECT_AUTO; this->props[property].value = value; - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: VO_PROP_ASPECT_RATIO(%d)\n", this->props[property].value); this->sc.user_ratio = value; @@ -1860,7 +1857,7 @@ static int xxmc_set_property (vo_driver_t *this_gen, this->props[property].value = value; xprintf(this->xine, XINE_VERBOSITY_LOG, "video_out_xxmc: VO_PROP_ZOOM_X = %d\n", this->props[property].value); - + this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; xxmc_compute_ideal_size (this); @@ -1905,7 +1902,7 @@ static int xxmc_gui_data_exchange (vo_driver_t *this_gen, case XINE_GUI_SEND_COMPLETION_EVENT: break; #endif - + case XINE_GUI_SEND_EXPOSE_EVENT: { /* XExposeEvent * xev = (XExposeEvent *) data; */ @@ -1917,7 +1914,7 @@ static int xxmc_gui_data_exchange (vo_driver_t *this_gen, if ((frame->format == XINE_IMGFMT_XXMC) && (!xxmc->decoded || !xxmc_xvmc_surface_valid(this, frame->xvmc_surf))) { xvmc_context_reader_unlock( &this->xvmc_lock ); - if (! xxmc_redraw_needed (this_gen)) + if (! xxmc_redraw_needed (this_gen)) xxmc_clean_output_area(this, (frame->format == XINE_IMGFMT_XXMC)); break; } @@ -1931,8 +1928,8 @@ static int xxmc_gui_data_exchange (vo_driver_t *this_gen, this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width, this->sc.displayed_height, this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height, - this->cur_field); + this->sc.output_width, this->sc.output_height, + this->cur_field); XVMCUNLOCKDISPLAY( this->display ); } else { XLockDisplay (this->display); @@ -1957,10 +1954,10 @@ static int xxmc_gui_data_exchange (vo_driver_t *this_gen, xvmc_context_reader_unlock( &this->xvmc_lock ); } if(this->xoverlay) - x11osd_expose(this->xoverlay); - + x11osd_expose(this->xoverlay); + } - + break; case XINE_GUI_SEND_DRAWABLE_CHANGED: @@ -2003,7 +2000,7 @@ static void xxmc_dispose (vo_driver_t *this_gen) { xxmc_driver_t *this = (xxmc_driver_t *) this_gen; int i; - + if (this->xvmc_cap) { xvmc_context_writer_lock( &this->xvmc_lock ); xxmc_dispose_context( this ); @@ -2040,7 +2037,7 @@ static void xxmc_dispose (vo_driver_t *this_gen) { free_context_lock(&this->xvmc_lock); _x_alphablend_free(&this->alphablend_extra_data); - + free (this); } @@ -2051,7 +2048,7 @@ static int xxmc_check_yv12 (Display *display, XvPortID port) { int i; formatValues = XvListImageFormats (display, port, &formats); - + for (i = 0; i < formats; i++) if ((formatValues[i].id == XINE_IMGFMT_YV12) && (! (strcmp (formatValues[i].guid, "YV12")))) { @@ -2065,14 +2062,14 @@ static int xxmc_check_yv12 (Display *display, XvPortID port) { /* called xlocked */ static void xxmc_check_capability (xxmc_driver_t *this, - int property, XvAttribute attr, - int base_id, char *str_prop, - char *config_name, - char *config_desc, - char *config_help) { + int property, XvAttribute attr, int base_id, + const char *config_name, + const char *config_desc, + const char *config_help) { int int_default; cfg_entry_t *entry; - + const char *str_prop = attr.name; + if (VO_PROP_COLORKEY && (attr.max_value == ~0)) attr.max_value = 2147483615; @@ -2091,7 +2088,7 @@ static void xxmc_check_capability (xxmc_driver_t *this, */ if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) int_default = 1; - + if (config_name) { /* is this a boolean property ? */ if ((attr.min_value == 0) && (attr.max_value == 1)) { @@ -2108,12 +2105,12 @@ static void xxmc_check_capability (xxmc_driver_t *this, entry = this->config->lookup_entry (this->config, config_name); - if((entry->num_value < this->props[property].min) || + if((entry->num_value < this->props[property].min) || (entry->num_value > this->props[property].max)) { - this->config->update_num(this->config, config_name, + this->config->update_num(this->config, config_name, ((this->props[property].min + this->props[property].max) >> 1)); - + entry = this->config->lookup_entry (this->config, config_name); } @@ -2121,48 +2118,44 @@ static void xxmc_check_capability (xxmc_driver_t *this, xxmc_set_property (&this->vo_driver, property, entry->num_value); - + if (strcmp(str_prop, "XV_COLORKEY") == 0) { this->use_colorkey |= 1; this->colorkey = entry->num_value; } else if(strcmp(str_prop, "XV_AUTOPAINT_COLORKEY") == 0) { if(entry->num_value==1) - this->use_colorkey |= 2; + this->use_colorkey |= 2; } } else this->props[property].value = int_default; } -static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { +static void xxmc_update_attr (void *this_gen, xine_cfg_entry_t *entry, + const char *atomstr, const char *debugstr) +{ xxmc_driver_t *this = (xxmc_driver_t *) this_gen; Atom atom; - int xv_filter; - - xv_filter = entry->num_value; XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_FILTER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_filter); + atom = XInternAtom (this->display, atomstr, False); + XvSetPortAttribute (this->display, this->xv_port, atom, entry->num_value); XUnlockDisplay(this->display); xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: bilinear scaling mode (XV_FILTER) = %d\n",xv_filter); + LOG_MODULE ": %s = %d\n", debugstr, entry->num_value); } -static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { - xxmc_driver_t *this = (xxmc_driver_t *) this_gen; - Atom atom; - int xv_double_buffer; - - xv_double_buffer = entry->num_value; +static void xxmc_update_XV_FILTER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_FILTER", "bilinear scaling mode"); +} - XLockDisplay(this->display); - atom = XInternAtom (this->display, "XV_DOUBLE_BUFFER", False); - XvSetPortAttribute (this->display, this->xv_port, atom, xv_double_buffer); - XUnlockDisplay(this->display); +static void xxmc_update_XV_DOUBLE_BUFFER(void *this_gen, xine_cfg_entry_t *entry) { + xxmc_update_attr (this_gen, entry, "XV_DOUBLE_BUFFER", "double buffering mode"); +} - xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xxmc: double buffering mode = %d\n", xv_double_buffer); +static void xxmc_update_XV_BICUBIC(void *this_gen, xine_cfg_entry_t *entry) +{ + xxmc_update_attr (this_gen, entry, "XV_BICUBIC", "bicubic filtering mode"); } static void xxmc_update_xv_pitch_alignment(void *this_gen, xine_cfg_entry_t *entry) { @@ -2201,14 +2194,60 @@ static void xxmc_update_disable_bob_for_scaled_osd(void *this_gen, xine_cfg_entr this->disable_bob_for_scaled_osd = entry->num_value; } +static int xxmc_open_port (xxmc_driver_t *this, XvPortID port) { + int ret; + x11_InstallXErrorHandler (this); + ret = ! xxmc_check_yv12(this->display, port) + && XvGrabPort(this->display, port, 0) == Success; + x11_DeInstallXErrorHandler (this); + return ret; +} + +static unsigned int +xxmc_find_adaptor_by_port (int port, unsigned int adaptors, + XvAdaptorInfo *adaptor_info) +{ + unsigned int an; + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask) + if (port >= adaptor_info[an].base_id && + port < adaptor_info[an].base_id + adaptor_info[an].num_ports) + return an; + return 0; /* shouldn't happen */ +} + +static XvPortID xxmc_autodetect_port(xxmc_driver_t *this, + unsigned int adaptors, + XvAdaptorInfo *adaptor_info, + unsigned int *adaptor_num, + XvPortID base, + xv_prefertype prefer_type) +{ + unsigned int an, j; + + for (an = 0; an < adaptors; an++) + if (adaptor_info[an].type & XvImageMask && + (prefer_type == xv_prefer_none || + strcasestr (adaptor_info[an].name, prefer_substrings[prefer_type]))) + for (j = 0; j < adaptor_info[an].num_ports; j++) { + XvPortID port = adaptor_info[an].base_id + j; + if (port >= base && xxmc_open_port(this, port)) { + *adaptor_num = an; + return port; + } + } + + return 0; +} + -static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) +static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) { int numSurf,numSub,i,j; XvMCSurfaceInfo *surfaceInfo,*curInfo; - XvMCContext + XvMCContext c; xvmc_capabilities_t *curCap; @@ -2227,13 +2266,13 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) XVMCLOCKDISPLAY( this->display ); - if ( !XvMCQueryExtension(this->display, &this->xvmc_eventbase, + if ( !XvMCQueryExtension(this->display, &this->xvmc_eventbase, &this->xvmc_errbase)) { XVMCUNLOCKDISPLAY( this->display ); xvmc_context_writer_unlock( &this->xvmc_lock ); return; } - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: XvMC extension present.\n"); surfaceInfo = XvMCListSurfaceTypes(this->display, xv_port, &numSurf); @@ -2249,56 +2288,56 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) curInfo = surfaceInfo; curCap = this->xvmc_cap; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Found %d XvMC surface types\n",numSurf); for (i=0; i< numSurf; ++i) { curCap->mpeg_flags = 0; curCap->accel_flags = 0; if (curInfo->chroma_format == XVMC_CHROMA_FORMAT_420) { - curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_1) ? - XINE_XVMC_MPEG_1 : 0); - curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_2) ? + curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_1) ? + XINE_XVMC_MPEG_1 : 0); + curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_2) ? XINE_XVMC_MPEG_2 : 0); - curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_4) ? + curCap->mpeg_flags |= ((curInfo->mc_type & XVMC_MPEG_4) ? XINE_XVMC_MPEG_4 : 0); - curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ? + curCap->accel_flags |= ((curInfo->mc_type & XVMC_VLD) ? XINE_XVMC_ACCEL_VLD : 0); - curCap->accel_flags |= ((curInfo->mc_type & XVMC_IDCT) ? + curCap->accel_flags |= ((curInfo->mc_type & XVMC_IDCT) ? XINE_XVMC_ACCEL_IDCT : 0); - curCap->accel_flags |= ((curInfo->mc_type & (XVMC_VLD | XVMC_IDCT)) ? + curCap->accel_flags |= ((curInfo->mc_type & (XVMC_VLD | XVMC_IDCT)) ? 0 : XINE_XVMC_ACCEL_MOCOMP); curCap->max_width = curInfo->max_width; curCap->max_height = curInfo->max_height; curCap->sub_max_width = curInfo->subpicture_max_width; curCap->sub_max_height = curInfo->subpicture_max_height; curCap->flags = curInfo->flags; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Surface type %d: Max size: %d %d.\n", i,curCap->max_width,curCap->max_height); - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Surface type %d: Max subpic size: %d %d.\n", i,curCap->sub_max_width,curCap->sub_max_height); - + curCap->type_id = curInfo->surface_type_id; - formatValues = XvMCListSubpictureTypes( this->display, xv_port, + formatValues = XvMCListSubpictureTypes( this->display, xv_port, curCap->type_id, &numSub); curCap->subPicType.id = 0; if (formatValues) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Surface type %d: Found %d XvMC subpicture " "types\n",i,numSub); for (j = 0; j<numSub; ++j) { if (formatValues[j].id == FOURCC_IA44) { curCap->subPicType = formatValues[j]; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Surface type %d: Detected and using " "IA44 subpicture type.\n",i); /* Prefer IA44 */ break; } else if (formatValues[j].id == FOURCC_AI44) { curCap->subPicType = formatValues[j]; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Surface type %d: Detected AI44 " "subpicture type.\n",i); } @@ -2308,7 +2347,7 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) XFree(formatValues); curInfo++; - curCap++; + curCap++; } } XFree(surfaceInfo); @@ -2317,7 +2356,7 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) * Try to create a direct rendering context. This will fail if we are not * on the displaying computer or an indirect context is not available. */ - + curCap = this->xvmc_cap; if (Success == XvMCCreateContext( this->display, xv_port, curCap->type_id, curCap->max_width,curCap->max_height, @@ -2330,7 +2369,7 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) } else { free(this->xvmc_cap); this->xvmc_cap = 0; - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out_xxmc: Apparent attempt to use a direct XvMC " "context\nvideo_out_xxmc: on a remote display. " "Falling back to XV.\n"); @@ -2348,8 +2387,8 @@ static void checkXvMCCap( xxmc_driver_t *this, XvPortID xv_port) return; } - - + + static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { @@ -2363,22 +2402,23 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi x11_visual_t *visual = (x11_visual_t *) visual_gen; XColor dummy; XvImage *myimage; - unsigned int adaptors, j; + unsigned int adaptors; unsigned int ver,rel,req,ev,err; XShmSegmentInfo myshminfo; XvPortID xv_port; XvAdaptorInfo *adaptor_info; unsigned int adaptor_num; - cfg_entry_t *entry; + xv_prefertype prefer_type; + cfg_entry_t *entry; int use_more_frames; int use_unscaled; - this = (xxmc_driver_t *) xine_xmalloc (sizeof (xxmc_driver_t)); + this = calloc(1, sizeof (xxmc_driver_t)); if (!this) return NULL; _x_alphablend_init(&this->alphablend_extra_data, class->xine); - + this->display = visual->display; this->screen = visual->screen; this->config = config; @@ -2404,43 +2444,50 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi return NULL; } - xv_port = 0; - - for ( adaptor_num = 0; (adaptor_num < adaptors) && !xv_port; adaptor_num++ ) { - - if (adaptor_info[adaptor_num].type & XvImageMask) { - - for (j = 0; j < adaptor_info[adaptor_num].num_ports && !xv_port; j++) - if (( !(xxmc_check_yv12 (this->display, - adaptor_info[adaptor_num].base_id + j))) - && (XvGrabPort (this->display, - adaptor_info[adaptor_num].base_id + j, - 0) == Success)) { - xv_port = adaptor_info[adaptor_num].base_id + j; - } - - if( xv_port ) - break; - } + xv_port = config->register_num (config, "video.device.xv_port", 0, + VIDEO_DEVICE_XV_PORT_HELP, + 20, NULL, NULL); + prefer_type = config->register_enum (config, "video.device.xv_preferred_method", 0, + prefer_labels, VIDEO_DEVICE_XV_PREFER_TYPE_HELP, + 10, NULL, NULL); + + if (xv_port != 0) { + if (! xxmc_open_port(this, xv_port)) { + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: could not open Xv port %d - autodetecting\n"), + LOG_MODULE, xv_port); + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, xv_port, prefer_type); + } else + adaptor_num = xxmc_find_adaptor_by_port (xv_port, adaptors, adaptor_info); + } + if (!xv_port) + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, prefer_type); + if (!xv_port) + { + if (prefer_type) + xprintf(class->xine, XINE_VERBOSITY_NONE, + _("%s: no available ports of type \"%s\", defaulting...\n"), + LOG_MODULE, prefer_labels[prefer_type]); + xv_port = xxmc_autodetect_port(this, adaptors, adaptor_info, &adaptor_num, 0, xv_prefer_none); } if (!xv_port) { xprintf(class->xine, XINE_VERBOSITY_LOG, _("video_out_xxmc: Xv extension is present but I couldn't find a usable yuv12 port.\n" " Looks like your graphics hardware driver doesn't support Xv?!\n")); - + /* XvFreeAdaptorInfo (adaptor_info); this crashed on me (gb)*/ XUnlockDisplay(this->display); return NULL; - } + } else xprintf(class->xine, XINE_VERBOSITY_LOG, _("video_out_xxmc: using Xv port %ld from adaptor %s for hardware " "colour space conversion and scaling.\n"), xv_port, adaptor_info[adaptor_num].name); - + XUnlockDisplay(this->display); - + this->xv_port = xv_port; _x_vo_scale_init (&this->sc, 1, 0, config ); @@ -2510,72 +2557,60 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi for(k = 0; k < nattr; k++) { if((attr[k].flags & XvSettable) && (attr[k].flags & XvGettable)) { - if(!strcmp(attr[k].name, "XV_HUE")) { + const char *const name = attr[k].name; + if(!strcmp(name, "XV_HUE")) { if (!strncmp(adaptor_info[adaptor_num].name, "NV", 2)) { xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out_xxmc: ignoring broken XV_HUE settings on NVidia cards\n"); } else { xxmc_check_capability (this, VO_PROP_HUE, attr[k], - adaptor_info[adaptor_num].base_id, "XV_HUE", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); } - } else if(!strcmp(attr[k].name, "XV_SATURATION")) { + } else if(!strcmp(name, "XV_SATURATION")) { xxmc_check_capability (this, VO_PROP_SATURATION, attr[k], - adaptor_info[adaptor_num].base_id, "XV_SATURATION", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_BRIGHTNESS")) { + } else if(!strcmp(name, "XV_BRIGHTNESS")) { xxmc_check_capability (this, VO_PROP_BRIGHTNESS, attr[k], - adaptor_info[adaptor_num].base_id, "XV_BRIGHTNESS", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_CONTRAST")) { + } else if(!strcmp(name, "XV_CONTRAST")) { xxmc_check_capability (this, VO_PROP_CONTRAST, attr[k], - adaptor_info[adaptor_num].base_id, "XV_CONTRAST", + adaptor_info[adaptor_num].base_id, NULL, NULL, NULL); - } else if(!strcmp(attr[k].name, "XV_COLORKEY")) { + } else if(!strcmp(name, "XV_COLORKEY")) { xxmc_check_capability (this, VO_PROP_COLORKEY, attr[k], - adaptor_info[adaptor_num].base_id, "XV_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_colorkey", - _("video overlay colour key"), - _("The colour key is used to tell the graphics card where to " - "overlay the video image. Try different values, if you experience " - "windows becoming transparent.")); - - } else if(!strcmp(attr[k].name, "XV_AUTOPAINT_COLORKEY")) { + VIDEO_DEVICE_XV_COLORKEY_HELP); + } else if(!strcmp(name, "XV_AUTOPAINT_COLORKEY")) { xxmc_check_capability (this, VO_PROP_AUTOPAINT_COLORKEY, attr[k], - adaptor_info[adaptor_num].base_id, "XV_AUTOPAINT_COLORKEY", + adaptor_info[adaptor_num].base_id, "video.device.xv_autopaint_colorkey", - _("autopaint colour key"), - _("Make Xv autopaint its colour key.")); - - } else if(!strcmp(attr[k].name, "XV_FILTER")) { + VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP); + } else if(!strcmp(name, "XV_FILTER")) { int xv_filter; /* This setting is specific to Permedia 2/3 cards. */ xv_filter = config->register_range (config, "video.device.xv_filter", 0, attr[k].min_value, attr[k].max_value, - _("bilinear scaling mode"), - _("Selects the bilinear scaling mode for Permedia cards. " - "The individual values are:\n\n" - "Permedia 2\n" - "0 - disable bilinear filtering\n" - "1 - enable bilinear filtering\n\n" - "Permedia 3\n" - "0 - disable bilinear filtering\n" - "1 - horizontal linear filtering\n" - "2 - enable full bilinear filtering"), + VIDEO_DEVICE_XV_FILTER_HELP, 20, xxmc_update_XV_FILTER, this); config->update_num(config,"video.device.xv_filter",xv_filter); - } else if(!strcmp(attr[k].name, "XV_DOUBLE_BUFFER")) { - int xv_double_buffer; - xv_double_buffer = + } else if(!strcmp(name, "XV_DOUBLE_BUFFER")) { + int xv_double_buffer = config->register_bool (config, "video.device.xv_double_buffer", 1, - _("enable double buffering"), - _("Double buffering will synchronize the update of the video image to the " - "repainting of the entire screen (\"vertical retrace\"). This eliminates " - "flickering and tearing artifacts, but will use more graphics memory."), + VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP, 20, xxmc_update_XV_DOUBLE_BUFFER, this); config->update_num(config,"video.device.xv_double_buffer",xv_double_buffer); + } else if(!strcmp(name, "XV_BICUBIC")) { + int xv_bicubic = + config->register_enum (config, "video.device.xv_bicubic", 2, + bicubic_types, VIDEO_DEVICE_XV_BICUBIC_HELP, + 20, xxmc_update_XV_BICUBIC, this); + config->update_num(config,"video.device.xv_bicubic",xv_bicubic); } } } @@ -2598,10 +2633,10 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi fo = XvListImageFormats(this->display, this->xv_port, (int*)&formats); XUnlockDisplay (this->display); - + this->xv_format_yv12 = 0; this->xv_format_yuy2 = 0; - + for(i = 0; i < formats; i++) { lprintf ("Xv image format: 0x%x (%4.4s) %s\n", fo[i].id, (char*)&fo[i].id, @@ -2615,7 +2650,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi } else if (fo[i].id == XINE_IMGFMT_YUY2) { this->xv_format_yuy2 = fo[i].id; this->capabilities |= VO_CAP_YUY2; - xprintf(this->xine, XINE_VERBOSITY_LOG, + xprintf(this->xine, XINE_VERBOSITY_LOG, _("video_out_xxmc: this adaptor supports the yuy2 format.\n")); } } @@ -2637,20 +2672,19 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi dispose_ximage (this, &myshminfo, myimage); XUnlockDisplay (this->display); - this->use_pitch_alignment = + this->use_pitch_alignment = config->register_bool (config, "video.device.xv_pitch_alignment", 0, - _("pitch alignment workaround"), - _("Some buggy video drivers need a workaround to function properly."), + VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP, 10, xxmc_update_xv_pitch_alignment, this); - use_more_frames= + use_more_frames= config->register_bool (config, "video.device.xvmc_more_frames", 0, _("Make XvMC allocate more frames for better buffering."), _("Some XvMC implementations allow more than 8 frames.\n" "This option, when turned on, makes the driver try to\n" "allocate 15 frames. A must for unichrome and live VDR.\n"), 10, NULL, this); - this->cpu_save_enabled = + this->cpu_save_enabled = config->register_bool (config, "video.device.unichrome_cpu_save", 0, _("Unichrome cpu save"), _("Saves CPU time by sleeping while decoder works.\n" @@ -2689,7 +2723,7 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi #ifdef HAVE_VLDXVMC printf("video_out_xxmc: Unichrome CPU saving is %s.\n", - (this->cpu_save_enabled) ? "on":"off"); + (this->cpu_save_enabled) ? "on":"off"); #else printf("video_out_xxmc: warning - compiled with no vld extensions.\n"); #endif @@ -2718,10 +2752,10 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *vi } XUnlockDisplay (this->display); } - + if( this->xoverlay ) { this->capabilities |= VO_CAP_UNSCALED_OVERLAY; - } + } return &this->vo_driver; } @@ -2739,12 +2773,12 @@ static char* get_description (video_driver_class_t *this_gen) { static void dispose_class (video_driver_class_t *this_gen) { xxmc_class_t *this = (xxmc_class_t *) this_gen; - + free (this); } static void *init_class (xine_t *xine, void *visual_gen) { - xxmc_class_t *this = (xxmc_class_t *) xine_xmalloc (sizeof (xxmc_class_t)); + xxmc_class_t *this = calloc(1, sizeof (xxmc_class_t)); this->driver_class.open_plugin = open_plugin; this->driver_class.get_identifier = get_identifier; @@ -2774,4 +2808,4 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_VIDEO_OUT, 21, "xxmc", XINE_VERSION_CODE, &vo_info_xxmc, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; - + diff --git a/src/video_out/vidix/drivers/Makefile.am b/src/video_out/vidix/drivers/Makefile.am index f438dde36..2a90f8591 100644 --- a/src/video_out/vidix/drivers/Makefile.am +++ b/src/video_out/vidix/drivers/Makefile.am @@ -15,7 +15,7 @@ vidix_drivers = \ unichrome_vid.la \ nvidia_vid.la \ sis_vid.la \ - savage_vid.la + savage_vid.la endif vidix_LTLIBRARIES = $(vidix_drivers) diff --git a/src/video_out/x11osd.c b/src/video_out/x11osd.c index e0cb6f1f6..d6354a6e5 100644 --- a/src/video_out/x11osd.c +++ b/src/video_out/x11osd.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003 the xine project * * This file is part of xine, a free video player. @@ -96,7 +96,7 @@ x11osd_expose (x11osd * osd) assert (osd); lprintf("expose (state:%d)\n", osd->clean ); - + switch (osd->mode) { case X11OSD_SHAPED: XShapeCombineMask (osd->display, osd->u.shaped.window, ShapeBounding, 0, 0, @@ -106,7 +106,7 @@ x11osd_expose (x11osd * osd) if( !osd->u.shaped.mapped ) XMapRaised (osd->display, osd->u.shaped.window); osd->u.shaped.mapped = 1; - + XCopyArea (osd->display, osd->bitmap, osd->u.shaped.window, osd->gc, 0, 0, osd->width, osd->height, 0, 0); } else { @@ -129,7 +129,7 @@ x11osd_resize (x11osd * osd, int width, int height) assert (osd); assert (width); assert (height); - + lprintf("resize old:%dx%d new:%dx%d\n", osd->width, osd->height, width, height ); osd->width = width; @@ -153,7 +153,7 @@ x11osd_resize (x11osd * osd, int width, int height) osd->width, osd->height, osd->depth); break; } - + osd->clean = UNDEFINED; x11osd_clear(osd); } @@ -165,7 +165,7 @@ x11osd_drawable_changed (x11osd * osd, Window window) XWindowAttributes getattr; assert (osd); - + lprintf("drawable changed\n"); /* @@ -183,14 +183,14 @@ x11osd_drawable_changed (x11osd * osd, Window window) XSync (osd->display, False); osd->window = window; - + XGetWindowAttributes (osd->display, osd->window, &getattr); osd->width = getattr.width; osd->height = getattr.height; - + assert(osd->width); assert(osd->height); - + switch(osd->mode) { case X11OSD_SHAPED: XFreePixmap (osd->display, osd->u.shaped.mask_bitmap); @@ -199,8 +199,8 @@ x11osd_drawable_changed (x11osd * osd, Window window) attr.override_redirect = True; attr.background_pixel = BlackPixel (osd->display, osd->screen); osd->u.shaped.window = XCreateWindow(osd->display, osd->window, - 0, 0, osd->width, osd->height, 0, - CopyFromParent, CopyFromParent, CopyFromParent, + 0, 0, osd->width, osd->height, 0, + CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel | CWOverrideRedirect, &attr); XSelectInput (osd->display, osd->u.shaped.window, ExposureMask); @@ -212,18 +212,18 @@ x11osd_drawable_changed (x11osd * osd, Window window) osd->bitmap = XCreatePixmap (osd->display, osd->u.shaped.window, osd->width, osd->height, osd->depth); - osd->cmap = XCreateColormap(osd->display, osd->u.shaped.window, + osd->cmap = XCreateColormap(osd->display, osd->u.shaped.window, osd->visual, AllocNone); break; case X11OSD_COLORKEY: osd->bitmap = XCreatePixmap (osd->display, osd->window, osd->width, osd->height, osd->depth); - osd->cmap = XCreateColormap(osd->display, osd->window, + osd->cmap = XCreateColormap(osd->display, osd->window, osd->visual, AllocNone); break; } - + osd->clean = UNDEFINED; /* do not x11osd_clear() here: osd->u.colorkey.sc has not being updated yet */ } @@ -245,7 +245,7 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x XSetWindowAttributes attr; XWindowAttributes getattr; - osd = xine_xmalloc (sizeof (x11osd)); + osd = calloc(1, sizeof(x11osd)); if (!osd) return NULL; @@ -260,11 +260,11 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x osd->visual = DefaultVisual (osd->display, osd->screen); osd->depth = DefaultDepth (osd->display, osd->screen); - + XGetWindowAttributes (osd->display, osd->window, &getattr); osd->width = getattr.width; osd->height = getattr.height; - + assert(osd->width); assert(osd->height); @@ -278,8 +278,8 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x attr.override_redirect = True; attr.background_pixel = BlackPixel (osd->display, osd->screen); osd->u.shaped.window = XCreateWindow(osd->display, osd->window, - 0, 0, osd->width, osd->height, 0, - CopyFromParent, CopyFromParent, CopyFromParent, + 0, 0, osd->width, osd->height, 0, + CopyFromParent, CopyFromParent, CopyFromParent, CWBackPixel | CWOverrideRedirect, &attr); XSync(osd->display, False); @@ -288,7 +288,7 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x goto error_window; } - osd->u.shaped.mask_bitmap = XCreatePixmap (osd->display, osd->u.shaped.window, osd->width, + osd->u.shaped.mask_bitmap = XCreatePixmap (osd->display, osd->u.shaped.window, osd->width, osd->height, 1); XSync(osd->display, False); if( x11_error ) { @@ -296,7 +296,7 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x goto error_aftermaskbitmap; } - osd->bitmap = XCreatePixmap (osd->display, osd->u.shaped.window, osd->width, + osd->bitmap = XCreatePixmap (osd->display, osd->u.shaped.window, osd->width, osd->height, osd->depth); osd->gc = XCreateGC (osd->display, osd->u.shaped.window, 0, NULL); @@ -315,14 +315,14 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x XSelectInput (osd->display, osd->u.shaped.window, ExposureMask); osd->u.shaped.mapped = 0; - osd->cmap = XCreateColormap(osd->display, osd->u.shaped.window, + osd->cmap = XCreateColormap(osd->display, osd->u.shaped.window, osd->visual, AllocNone); break; case X11OSD_COLORKEY: - osd->bitmap = XCreatePixmap (osd->display, osd->window, osd->width, + osd->bitmap = XCreatePixmap (osd->display, osd->window, osd->width, osd->height, osd->depth); osd->gc = XCreateGC (osd->display, osd->window, 0, NULL); - osd->cmap = XCreateColormap(osd->display, osd->window, + osd->cmap = XCreateColormap(osd->display, osd->window, osd->visual, AllocNone); /* FIXME: the expose event doesn't seem to happen? */ /*XSelectInput (osd->display, osd->window, ExposureMask);*/ @@ -342,8 +342,8 @@ x11osd_create (xine_t *xine, Display *display, int screen, Window window, enum x XSetErrorHandler(old_handler); - xprintf(osd->xine, XINE_VERBOSITY_DEBUG, - _("x11osd: unscaled overlay created (%s mode).\n"), + xprintf(osd->xine, XINE_VERBOSITY_DEBUG, + _("x11osd: unscaled overlay created (%s mode).\n"), (mode==X11OSD_SHAPED) ? "XShape" : "Colorkey" ); return osd; @@ -402,9 +402,9 @@ x11osd_destroy (x11osd * osd) void x11osd_clear(x11osd *osd) { int i; - + lprintf("clear (state:%d)\n", osd->clean ); - + if( osd->clean != WIPED ) switch (osd->mode) { case X11OSD_SHAPED: @@ -442,7 +442,7 @@ void x11osd_blend(x11osd *osd, vo_overlay_t *overlay) { if (osd->clean==UNDEFINED) x11osd_clear(osd); /* Workaround. Colorkey mode needs sc data before the clear. */ - + if (overlay->rle) { int i, x, y, len, width; int use_clip_palette, max_palette_colour[2]; @@ -474,7 +474,7 @@ void x11osd_blend(x11osd *osd, vo_overlay_t *overlay) if (x + width - 1 > overlay->hili_right) { width -= overlay->hili_right - x; len += overlay->hili_right - x; - } + } } } @@ -482,7 +482,7 @@ void x11osd_blend(x11osd *osd, vo_overlay_t *overlay) int j; clut_t *src_clut; uint8_t *src_trans; - + if (use_clip_palette) { src_clut = (clut_t *)&overlay->hili_color; src_trans = (uint8_t *)&overlay->hili_trans; @@ -507,7 +507,7 @@ void x11osd_blend(x11osd *osd, vo_overlay_t *overlay) xcolor.green = (65536 * saturate(g, 0, 255)) / 256; b = y + 2 * u - 274; xcolor.blue = (65536 * saturate(b, 0, 255)) / 256; - + xcolor.flags = DoRed | DoBlue | DoGreen; XAllocColor(osd->display, osd->cmap, &xcolor); diff --git a/src/video_out/x11osd.h b/src/video_out/x11osd.h index fe0bf6208..b7726e144 100644 --- a/src/video_out/x11osd.h +++ b/src/video_out/x11osd.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003 the xine project * * This file is part of xine, a free video player. diff --git a/src/video_out/xcbosd.c b/src/video_out/xcbosd.c index 4bb2b60af..ca51664a2 100644 --- a/src/video_out/xcbosd.c +++ b/src/video_out/xcbosd.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003, 2007 the xine project * * This file is part of xine, a free video player. @@ -93,7 +93,7 @@ void xcbosd_expose(xcbosd *osd) assert (osd); lprintf("expose (state:%d)\n", osd->clean ); - + switch (osd->mode) { case XCBOSD_SHAPED: xcb_shape_mask(osd->connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_BOUNDING, @@ -106,7 +106,7 @@ void xcbosd_expose(xcbosd *osd) xcb_map_window(osd->connection, osd->u.shaped.window); } osd->u.shaped.mapped = 1; - + xcb_copy_area(osd->connection, osd->bitmap, osd->u.shaped.window, osd->gc, 0, 0, 0, 0, osd->width, osd->height); } else { @@ -128,7 +128,7 @@ void xcbosd_resize(xcbosd *osd, int width, int height) assert (osd); assert (width); assert (height); - + lprintf("resize old:%dx%d new:%dx%d\n", osd->width, osd->height, width, height ); osd->width = width; @@ -151,7 +151,7 @@ void xcbosd_resize(xcbosd *osd, int width, int height) xcb_create_pixmap(osd->connection, osd->depth, osd->bitmap, osd->window, osd->width, osd->height); break; } - + osd->clean = UNDEFINED; xcbosd_clear(osd); } @@ -162,7 +162,7 @@ void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window) xcb_get_geometry_reply_t *get_geometry_reply; assert (osd); - + lprintf("drawable changed\n"); /* @@ -180,17 +180,17 @@ void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window) /* XSync (osd->display, False); FIXME don't think that we need that --pfister */ osd->window = window; - + get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window); get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL); osd->depth = get_geometry_reply->depth; osd->width = get_geometry_reply->width; osd->height = get_geometry_reply->height; free(get_geometry_reply); - + assert(osd->width); assert(osd->height); - + switch(osd->mode) { case XCBOSD_SHAPED: { xcb_free_pixmap(osd->connection, osd->u.shaped.mask_bitmap); @@ -223,7 +223,7 @@ void xcbosd_drawable_changed(xcbosd *osd, xcb_window_t window) break; } - + osd->clean = UNDEFINED; /* do not xcbosd_clear() here: osd->u.colorkey.sc has not being updated yet */ } @@ -238,7 +238,7 @@ xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t * xcb_void_cookie_t generic_cookie; xcb_generic_error_t *generic_error; - osd = xine_xmalloc (sizeof (xcbosd)); + osd = calloc(1, sizeof(xcbosd)); if (!osd) return NULL; @@ -249,14 +249,14 @@ xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t * osd->window = window; osd->visual = osd->screen->root_visual; - + get_geometry_cookie = xcb_get_geometry(osd->connection, osd->window); get_geometry_reply = xcb_get_geometry_reply(osd->connection, get_geometry_cookie, NULL); osd->depth = get_geometry_reply->depth; osd->width = get_geometry_reply->width; osd->height = get_geometry_reply->height; free(get_geometry_reply); - + assert(osd->width); assert(osd->height); @@ -326,8 +326,8 @@ xcbosd *xcbosd_create(xine_t *xine, xcb_connection_t *connection, xcb_screen_t * osd->clean = UNDEFINED; xcbosd_expose(osd); - xprintf(osd->xine, XINE_VERBOSITY_DEBUG, - _("x11osd: unscaled overlay created (%s mode).\n"), + xprintf(osd->xine, XINE_VERBOSITY_DEBUG, + _("x11osd: unscaled overlay created (%s mode).\n"), (mode==XCBOSD_SHAPED) ? "XShape" : "Colorkey" ); return osd; @@ -382,9 +382,9 @@ void xcbosd_destroy(xcbosd *osd) void xcbosd_clear(xcbosd *osd) { int i; - + lprintf("clear (state:%d)\n", osd->clean ); - + if( osd->clean != WIPED ) switch (osd->mode) { case XCBOSD_SHAPED: { @@ -435,7 +435,7 @@ void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay) if (osd->clean==UNDEFINED) xcbosd_clear(osd); /* Workaround. Colorkey mode needs sc data before the clear. */ - + if (overlay->rle) { int i, x, y, len, width; int use_clip_palette, max_palette_colour[2]; @@ -467,7 +467,7 @@ void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay) if (x + width - 1 > overlay->hili_right) { width -= overlay->hili_right - x; len += overlay->hili_right - x; - } + } } } @@ -475,7 +475,7 @@ void xcbosd_blend(xcbosd *osd, vo_overlay_t *overlay) int j; clut_t *src_clut; uint8_t *src_trans; - + if (use_clip_palette) { src_clut = (clut_t *)&overlay->hili_color; src_trans = (uint8_t *)&overlay->hili_trans; diff --git a/src/video_out/xcbosd.h b/src/video_out/xcbosd.h index 32af4965e..8b91b1b6e 100644 --- a/src/video_out/xcbosd.h +++ b/src/video_out/xcbosd.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2003, 2007 the xine project * * This file is part of xine, a free video player. diff --git a/src/video_out/xv_common.h b/src/video_out/xv_common.h new file mode 100644 index 000000000..ff49286f0 --- /dev/null +++ b/src/video_out/xv_common.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * xv_common.h: X11 Xv common bits + */ + +#define VIDEO_DEVICE_XV_COLORKEY_HELP \ + _("video overlay colour key"), \ + _("The colour key is used to tell the graphics card where to " \ + "overlay the video image. Try different values, if you "\ + "experience windows becoming transparent.") + +#define VIDEO_DEVICE_XV_AUTOPAINT_COLORKEY_HELP \ + _("autopaint colour key"), \ + _("Make Xv autopaint its colour key.") + +#define VIDEO_DEVICE_XV_FILTER_HELP \ + _("bilinear scaling mode"), \ + _("Selects the bilinear scaling mode for Permedia cards. " \ + "The individual values are:\n\n" \ + "Permedia 2\n" \ + "0 - disable bilinear filtering\n" \ + "1 - enable bilinear filtering\n\n" \ + "Permedia 3\n" \ + "0 - disable bilinear filtering\n" \ + "1 - horizontal linear filtering\n" \ + "2 - enable full bilinear filtering") + +#define VIDEO_DEVICE_XV_DOUBLE_BUFFER_HELP \ + _("enable double buffering"), \ + _("Double buffering will synchronize the update of the video " \ + "image to the repainting of the entire screen (\"vertical " \ + "retrace\"). This eliminates flickering and tearing artifacts, " \ + "but will use more graphics memory.") + +#define VIDEO_DEVICE_XV_PORT_HELP \ + _("Xv port number"), \ + _("Selects the Xv port number to use (0 to autodetect).") + +#define VIDEO_DEVICE_XV_PITCH_ALIGNMENT_HELP \ + _("pitch alignment workaround"), \ + _("Some buggy video drivers need a workaround to function properly.") + +#define VIDEO_DEVICE_XV_DECL_SYNC_ATOMS \ + static const char *const sync_atoms[] = \ + { "XV_SYNC_TO_VBLANK", "XV_VSYNC" }; + +#define VIDEO_DEVICE_XV_DECL_PREFER_TYPES \ + typedef enum { \ + xv_prefer_none, xv_prefer_overlay, xv_prefer_textured, xv_prefer_blitter, \ + } xv_prefertype; \ + static const char *const prefer_labels[] = \ + { "Any", "Overlay", "Textured Video", "Blitter", NULL }; \ + static const char prefer_substrings[][8] = \ + { "", "Overlay", "Texture", "Blitter" }; +#define VIDEO_DEVICE_XV_PREFER_TYPE_HELP \ + _("video display method preference"), \ + _("Selects which video output method is preferred. " \ + "Detection is done using the reported Xv adaptor names.\n" \ + "(Only applies when auto-detecting which Xv port to use.)") + +#define VIDEO_DEVICE_XV_DECL_BICUBIC_TYPES \ + static const char *const bicubic_types[] = { "Off", "On", "Auto", NULL }; +#define VIDEO_DEVICE_XV_BICUBIC_HELP \ + _("bicubic filtering"), \ + _("This option controls bicubic filtering of the video image. " \ + "It may be used instead of, or as well as, xine's deinterlacers.") diff --git a/src/video_out/xvmc_mocomp.c b/src/video_out/xvmc_mocomp.c index faa2b0010..197037206 100644 --- a/src/video_out/xvmc_mocomp.c +++ b/src/video_out/xvmc_mocomp.c @@ -23,15 +23,15 @@ #include "xxmc.h" -static void calc_DMV(int DMV[][2], int *dmvector, +static void calc_DMV(int DMV[][2], int *dmvector, int mvx, int mvy, int picture_structure, int top_field_first) { - + if (picture_structure==VO_BOTH_FIELDS) { if (top_field_first) { /* vector for prediction of top field from bottom field */ DMV[0][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy +(mvy>0))>>1) + dmvector[1] - 1; - + /* vector for prediction of bottom field from top field */ DMV[1][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] + 1; @@ -40,7 +40,7 @@ static void calc_DMV(int DMV[][2], int *dmvector, /* vector for prediction of top field from bottom field */ DMV[0][0] = ((3*mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((3*mvy+(mvy>0))>>1) + dmvector[1] - 1; - + /* vector for prediction of bottom field from top field */ DMV[1][0] = ((mvx +(mvx>0))>>1) + dmvector[0]; DMV[1][1] = ((mvy +(mvy>0))>>1) + dmvector[1] + 1; @@ -50,13 +50,13 @@ static void calc_DMV(int DMV[][2], int *dmvector, /* vector for prediction from field of opposite 'parity' */ DMV[0][0] = ((mvx+(mvx>0))>>1) + dmvector[0]; DMV[0][1] = ((mvy+(mvy>0))>>1) + dmvector[1]; - + /* correct for vertical field shift */ if (picture_structure==VO_TOP_FIELD) DMV[0][1]--; else DMV[0][1]++; - + } } @@ -96,12 +96,12 @@ static void xvmc_render_macro_blocks(vo_frame_t *current_image, -void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, - int (*mv_field_sel)[2], int *dmvector, int cbp, - int dct_type, vo_frame_t *current_frame, - vo_frame_t *forward_ref_frame, - vo_frame_t *backward_ref_frame, int picture_structure, - int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2]) +void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, + int (*mv_field_sel)[2], int *dmvector, int cbp, + int dct_type, vo_frame_t *current_frame, + vo_frame_t *forward_ref_frame, + vo_frame_t *backward_ref_frame, int picture_structure, + int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2]) { xxmc_driver_t *this = (xxmc_driver_t *) current_frame->driver; xvmc_macroblocks_t *mbs = &this->macroblocks; @@ -110,10 +110,10 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, mbs->macroblockptr->x = x; mbs->macroblockptr->y = y; - + if(mb_type & XINE_MACROBLOCK_INTRA) { mbs->macroblockptr->macroblock_type = XVMC_MB_TYPE_INTRA; - } + } else { mbs->macroblockptr->macroblock_type = 0; /* XvMC doesn't support skips */ @@ -122,7 +122,7 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, motion_type = (picture_structure == VO_BOTH_FIELDS) ? XINE_MC_FRAME : XINE_MC_FIELD; mbs->macroblockptr->PMV[0][0][0] = 0; mbs->macroblockptr->PMV[0][0][1] = 0; - } + } else { if(mb_type & XINE_MACROBLOCK_MOTION_BACKWARD) { mbs->macroblockptr->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD; @@ -154,17 +154,17 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, calc_DMV(DMV,dmvector, f_mot_pmv[0][0], f_mot_pmv[0][1]>>1, picture_structure, top_field_first); - + mbs->macroblockptr->PMV[1][0][0] = DMV[0][0]; mbs->macroblockptr->PMV[1][0][1] = DMV[0][1]; mbs->macroblockptr->PMV[1][1][0] = DMV[1][0]; mbs->macroblockptr->PMV[1][1][1] = DMV[1][1]; - } + } else { calc_DMV(DMV,dmvector, f_mot_pmv[0][0], f_mot_pmv[0][1]>>1, picture_structure, top_field_first); - + mbs->macroblockptr->PMV[0][1][0] = DMV[0][0]; mbs->macroblockptr->PMV[0][1][1] = DMV[0][1]; } @@ -185,14 +185,14 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, mbs->macroblockptr->index = ((unsigned long)mbs->xine_mc.blockptr - (unsigned long)mbs->xine_mc.blockbaseptr) >> 7; - + mbs->macroblockptr->dct_type = dct_type; mbs->macroblockptr->coded_block_pattern = cbp; cbp &= 0x3F; mbs->macroblockptr->coded_block_pattern = cbp; - while(cbp) { + while(cbp) { if(cbp & 1) mbs->macroblockptr->index--; cbp >>= 1; } @@ -238,9 +238,9 @@ void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, xvmc_render_macro_blocks( current_frame, - (picture_coding_type == XINE_PICT_B_TYPE) ? + (picture_coding_type == XINE_PICT_B_TYPE) ? backward_ref_frame : NULL, - (picture_coding_type != XINE_PICT_I_TYPE) ? + (picture_coding_type != XINE_PICT_I_TYPE) ? forward_ref_frame : NULL, picture_structure, second_field ? XVMC_SECOND_FIELD : 0, diff --git a/src/video_out/xvmc_vld.c b/src/video_out/xvmc_vld.c index b81578276..9eb68972f 100644 --- a/src/video_out/xvmc_vld.c +++ b/src/video_out/xvmc_vld.c @@ -39,7 +39,7 @@ void xvmc_vld_frame(struct vo_frame_s *this_gen) *ff = (xxmc_frame_t *) vft->forward_reference_frame, *bf = (xxmc_frame_t *) vft->backward_reference_frame; XvMCMpegControl ctl; - xxmc_driver_t + xxmc_driver_t *driver = (xxmc_driver_t *) cf->vo_frame.driver; XvMCSurface *fs=0, *bs=0; XvMCQMatrix qmx; @@ -53,21 +53,21 @@ void xvmc_vld_frame(struct vo_frame_s *this_gen) ctl.picture_coding_type = vft->picture_coding_type; ctl.mpeg_coding = (vft->mpeg_coding == 0) ? XVMC_MPEG_1 : XVMC_MPEG_2; ctl.flags = 0; - ctl.flags |= (vft->progressive_sequence) ? + ctl.flags |= (vft->progressive_sequence) ? XVMC_PROGRESSIVE_SEQUENCE : 0 ; - ctl.flags |= (vft->scan) ? + ctl.flags |= (vft->scan) ? XVMC_ALTERNATE_SCAN : XVMC_ZIG_ZAG_SCAN; - ctl.flags |= (vft->pred_dct_frame) ? + ctl.flags |= (vft->pred_dct_frame) ? XVMC_PRED_DCT_FRAME : XVMC_PRED_DCT_FIELD; - ctl.flags |= (this->top_field_first) ? + ctl.flags |= (this->top_field_first) ? XVMC_TOP_FIELD_FIRST : XVMC_BOTTOM_FIELD_FIRST; - ctl.flags |= (vft->concealment_motion_vectors) ? - XVMC_CONCEALMENT_MOTION_VECTORS : 0 ; - ctl.flags |= (vft->q_scale_type) ? + ctl.flags |= (vft->concealment_motion_vectors) ? + XVMC_CONCEALMENT_MOTION_VECTORS : 0 ; + ctl.flags |= (vft->q_scale_type) ? XVMC_Q_SCALE_TYPE : 0; - ctl.flags |= (vft->intra_vlc_format) ? + ctl.flags |= (vft->intra_vlc_format) ? XVMC_INTRA_VLC_FORMAT : 0; - ctl.flags |= (vft->second_field) ? + ctl.flags |= (vft->second_field) ? XVMC_SECOND_FIELD : 0 ; if (ff) fs=ff->xvmc_surf; @@ -79,7 +79,7 @@ void xvmc_vld_frame(struct vo_frame_s *this_gen) if (ctl.picture_coding_type == XVMC_P_PICTURE) bs = cf->xvmc_surf; - + if ((qmx.load_intra_quantiser_matrix = vft->load_intra_quantizer_matrix)) { memcpy(qmx.intra_quantiser_matrix,vft->intra_quantizer_matrix, sizeof(qmx.intra_quantiser_matrix)); @@ -87,13 +87,13 @@ void xvmc_vld_frame(struct vo_frame_s *this_gen) if ((qmx.load_non_intra_quantiser_matrix = vft->load_non_intra_quantizer_matrix)) { memcpy(qmx.non_intra_quantiser_matrix,vft->non_intra_quantizer_matrix, sizeof(qmx.non_intra_quantiser_matrix)); - } - qmx.load_chroma_intra_quantiser_matrix = 0; + } + qmx.load_chroma_intra_quantiser_matrix = 0; qmx.load_chroma_non_intra_quantiser_matrix = 0; XVMCLOCKDISPLAY( driver->display ); - XvMCLoadQMatrix(driver->display, &driver->context, &qmx); - + XvMCLoadQMatrix(driver->display, &driver->context, &qmx); + while((cf->xxmc_data.result = XvMCBeginSurface(driver->display, &driver->context, cf->xvmc_surf, fs, bs, &ctl))); @@ -101,9 +101,9 @@ void xvmc_vld_frame(struct vo_frame_s *this_gen) driver->cpu_saver = 0.; } -void xvmc_vld_slice(vo_frame_t *this_gen) +void xvmc_vld_slice(vo_frame_t *this_gen) { - xxmc_frame_t + xxmc_frame_t *cf = (xxmc_frame_t *) this_gen; xxmc_driver_t *driver = (xxmc_driver_t *) cf->vo_frame.driver; @@ -115,7 +115,7 @@ void xvmc_vld_slice(vo_frame_t *this_gen) /* * If CPU-saving mode is enabled, sleep after every xxmc->sleep slice. This will free * up the cpu while the decoder is working on the slice. The value of xxmc->sleep is calculated - * so that the decoder thread sleeps at most 50% of the frame delay, + * so that the decoder thread sleeps at most 50% of the frame delay, * assuming a 2.6 kernel clock of 1000 Hz. */ @@ -123,7 +123,7 @@ void xvmc_vld_slice(vo_frame_t *this_gen) if (driver->cpu_save_enabled) { driver->cpu_saver += 1.; if (driver->cpu_saver >= cf->xxmc_data.sleep) { - usleep(1); + usleep(1); driver->cpu_saver -= cf->xxmc_data.sleep; } } diff --git a/src/video_out/xxmc.h b/src/video_out/xxmc.h index 1c24991be..6110978d1 100644 --- a/src/video_out/xxmc.h +++ b/src/video_out/xxmc.h @@ -37,6 +37,14 @@ #define XVMC_THREAD_SAFE +/* + * some implementations are not aware of the display having been locked + * already before calling the xvmc function and may therefore deadlock. + */ +/* +#define XVMC_LOCKDISPLAY_SAFE +*/ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -106,7 +114,7 @@ typedef struct { XvMCMacroBlock *macroblockbaseptr; /* pointer to base MacroBlock in MB array */ XvMCMacroBlockArray macro_blocks; /* pointer to memory for macroblock array */ int slices; -} xvmc_macroblocks_t; +} xvmc_macroblocks_t; typedef struct { @@ -130,7 +138,7 @@ typedef struct { XShmSegmentInfo shminfo; /* XvMC specific stuff */ - + XvMCSurface *xvmc_surf; xine_xxmc_t xxmc_data; int last_sw_format; @@ -147,7 +155,7 @@ typedef struct{ XvImageFormatValues subPicType; int flags; } xvmc_capabilities_t; - + typedef struct xvmc_surface_handler_s { XvMCSurface surfaces[XVMC_MAX_SURFACES]; int surfInUse[XVMC_MAX_SURFACES]; @@ -171,13 +179,13 @@ typedef struct context_lock_s { return; \ } -#ifdef XVMC_THREAD_SAFE -#define XVMCLOCKDISPLAY(display) -#define XVMCUNLOCKDISPLAY(display) +#if defined(XVMC_THREAD_SAFE) && defined(XVMC_LOCKDISPLAY_SAFE) +#define XVMCLOCKDISPLAY(display) +#define XVMCUNLOCKDISPLAY(display) #else -#define XVMCLOCKDISPLAY(display) XLockDisplay(display) +#define XVMCLOCKDISPLAY(display) XLockDisplay(display) #define XVMCUNLOCKDISPLAY(display) XUnlockDisplay(display) -#endif +#endif struct xxmc_driver_s { vo_driver_t vo_driver; @@ -219,7 +227,7 @@ struct xxmc_driver_s { int (*x11_old_error_handler) (Display *, XErrorEvent *); xine_t *xine; - /* XvMC related stuff here */ + /* XvMC related stuff here */ xvmc_macroblocks_t macroblocks; xvmc_capabilities_t *xvmc_cap; unsigned xvmc_num_cap; @@ -264,8 +272,8 @@ struct xxmc_driver_s { /* * The mutex below is needed since XlockDisplay wasn't really enough - * to protect the XvMC Calls. - */ + * to protect the XvMC Calls. + */ context_lock_t xvmc_lock; alphablend_t alphablend_extra_data; @@ -285,14 +293,14 @@ extern int xxmc_xvmc_surface_valid(xxmc_driver_t *this, XvMCSurface *surf); extern void xvmc_vld_slice(vo_frame_t *this_gen); extern void xvmc_vld_frame(struct vo_frame_s *this_gen); -extern void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, - int (*mv_field_sel)[2], int *dmvector, - int cbp, - int dct_type, vo_frame_t *current_frame, - vo_frame_t *forward_ref_frame, - vo_frame_t *backward_ref_frame, - int picture_structure, - int second_field, int (*f_mot_pmv)[2], +extern void xxmc_xvmc_proc_macro_block(int x, int y, int mb_type, int motion_type, + int (*mv_field_sel)[2], int *dmvector, + int cbp, + int dct_type, vo_frame_t *current_frame, + vo_frame_t *forward_ref_frame, + vo_frame_t *backward_ref_frame, + int picture_structure, + int second_field, int (*f_mot_pmv)[2], int (*b_mot_pmv)[2]); #endif diff --git a/src/video_out/yuv2rgb.c b/src/video_out/yuv2rgb.c index c98dd518f..b237bfafa 100644 --- a/src/video_out/yuv2rgb.c +++ b/src/video_out/yuv2rgb.c @@ -110,15 +110,15 @@ static void yuv2rgb_dispose (yuv2rgb_t *this) free (this); } -static int yuv2rgb_configure (yuv2rgb_t *this, +static int yuv2rgb_configure (yuv2rgb_t *this, int source_width, int source_height, int y_stride, int uv_stride, int dest_width, int dest_height, int rgb_stride) { -/* +/* printf ("yuv2rgb setup (%d x %d => %d x %d)\n", source_width, source_height, dest_width, dest_height); -*/ +*/ if (prof_scale_line == -1) prof_scale_line = xine_profiler_allocate_slot("xshm scale line"); @@ -161,7 +161,7 @@ static int yuv2rgb_configure (yuv2rgb_t *this, /* printf("yuv2rgb config: src_ht=%i, dst_ht=%i\n",source_height, dest_height); printf("yuv2rgb config: step_dy=%i %f\n",this->step_dy, (float)this->step_dy / 32768.0); -*/ +*/ this->scale_line = find_scale_line_func(this->step_dx); if ((source_width == dest_width) && (source_height == dest_height)) { @@ -183,7 +183,7 @@ static int yuv2rgb_configure (yuv2rgb_t *this, } else { this->do_scale = 1; - + /* * space for two y-lines (for yuv2rgb_mlib) * u,v subsampled 2:1 @@ -209,7 +209,7 @@ static int yuv2rgb_configure (yuv2rgb_t *this, if (!this->mlib_resize_buffer) return 0; } -#endif +#endif } return 1; } @@ -257,7 +257,7 @@ static void scale_line_gen (uint8_t *source, uint8_t *dest, p1 = p2; p2 = *source++; } - + dest ++; width --; } @@ -275,7 +275,7 @@ static void scale_line_gen (uint8_t *source, uint8_t *dest, p1 = p2; p2 = *source++; } - + dest ++; width --; } @@ -1242,7 +1242,7 @@ static void scale_line_1_2 (uint8_t *source, uint8_t *dest, xine_profiler_stop_count(prof_scale_line); } - + /* * Scale line with no horizontal scaling. For NTSC mpeg2 dvd input in * 4:3 output format (720x480 -> 720x540) @@ -1255,7 +1255,7 @@ static void scale_line_1_1 (uint8_t *source, uint8_t *dest, xine_profiler_stop_count(prof_scale_line); } - + static scale_line_func_t find_scale_line_func(int step) { static struct { int src_step; @@ -1400,7 +1400,7 @@ static void scale_line_4 (uint8_t *source, uint8_t *dest, dst_2[6*i+3] = b[Y]; dst_2[6*i+4] = g[Y]; dst_2[6*i+5] = r[Y]; #define DST1CMAP(i) \ - Y = py_1[2*i]; \ + Y = py_1[2*i]; \ dst_1[2*i] = this->cmap[r[Y] + g[Y] + b[Y]]; \ Y = py_1[2*i+1]; \ dst_1[2*i+1] = this->cmap[r[Y] + g[Y] + b[Y]]; @@ -1428,7 +1428,7 @@ static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); dy = 0; @@ -1448,7 +1448,7 @@ static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, X_RGB(1); DST1(1); - + X_RGB(2); DST1(2); @@ -1466,7 +1466,7 @@ static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4); + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4); dy += this->step_dy; _dst += this->rgb_stride; @@ -1479,18 +1479,18 @@ static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, dy -= 32768; _py += this->y_stride; - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { _pu += this->uv_stride; _pv += this->uv_stride; - + scale_line (_pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768); @@ -1522,7 +1522,7 @@ static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, X_RGB(3); DST2(3); DST1(3); - + pu += 4; pv += 4; py_1 += 8; @@ -1531,7 +1531,7 @@ static void yuv2rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, dst_2 += 8; } while (--width); - _dst += 2 * this->rgb_stride; + _dst += 2 * this->rgb_stride; _py += 2 * this->y_stride; _pu += this->uv_stride; _pv += this->uv_stride; @@ -1559,7 +1559,7 @@ static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); dy = 0; @@ -1579,7 +1579,7 @@ static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, X_RGB(1); DST1RGB(1); - + X_RGB(2); DST1RGB(2); @@ -1597,7 +1597,7 @@ static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3); + xine_fast_memcpy (_dst, _dst-this->rgb_stride, this->dest_width*3); dy += this->step_dy; _dst += this->rgb_stride; @@ -1610,18 +1610,18 @@ static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, dy -= 32768; _py += this->y_stride; - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { _pu += this->uv_stride; _pv += this->uv_stride; - + scale_line (_pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while (dy>=32768); @@ -1662,11 +1662,11 @@ static void yuv2rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, dst_2 += 24; } while (--width); - _dst += 2 * this->rgb_stride; + _dst += 2 * this->rgb_stride; _py += 2 * this->y_stride; _pu += this->uv_stride; _pv += this->uv_stride; - + } while (--height); } } @@ -1690,7 +1690,7 @@ static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); dy = 0; @@ -1710,7 +1710,7 @@ static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, X_RGB(1); DST1BGR(1); - + X_RGB(2); DST1BGR(2); @@ -1741,18 +1741,18 @@ static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, dy -= 32768; _py += this->y_stride; - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { _pu += this->uv_stride; _pv += this->uv_stride; - + scale_line (_pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768 ); @@ -1793,7 +1793,7 @@ static void yuv2rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, dst_2 += 24; } while (--width); - _dst += 2 * this->rgb_stride; + _dst += 2 * this->rgb_stride; _py += 2 * this->y_stride; _pu += this->uv_stride; _pv += this->uv_stride; @@ -1821,7 +1821,7 @@ static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); dy = 0; @@ -1841,7 +1841,7 @@ static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, X_RGB(1); DST1(1); - + X_RGB(2); DST1(2); @@ -1859,7 +1859,7 @@ static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); dy += this->step_dy; _dst += this->rgb_stride; @@ -1872,18 +1872,18 @@ static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, dy -= 32768; _py += this->y_stride; - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { _pu += this->uv_stride; _pv += this->uv_stride; - + scale_line (_pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768); @@ -1923,7 +1923,7 @@ static void yuv2rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, dst_2 += 8; } while (--width); - _dst += 2 * this->rgb_stride; + _dst += 2 * this->rgb_stride; _py += 2 * this->y_stride; _pu += this->uv_stride; _pv += this->uv_stride; @@ -1951,7 +1951,7 @@ static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); dy = 0; @@ -1971,7 +1971,7 @@ static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, X_RGB(1); DST1(1); - + X_RGB(2); DST1(2); @@ -1989,7 +1989,7 @@ static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); dy += this->step_dy; _dst += this->rgb_stride; @@ -2002,18 +2002,18 @@ static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, dy -= 32768; _py += this->y_stride; - scale_line (_py, this->y_buffer, + scale_line (_py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { _pu += this->uv_stride; _pv += this->uv_stride; - + scale_line (_pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768 ); @@ -2045,7 +2045,7 @@ static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, X_RGB(3); DST2(3); DST1(3); - + pu += 4; pv += 4; py_1 += 8; @@ -2054,7 +2054,7 @@ static void yuv2rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, dst_2 += 8; } while (--width); - _dst += 2 * this->rgb_stride; + _dst += 2 * this->rgb_stride; _py += 2 * this->y_stride; _pu += this->uv_stride; _pv += this->uv_stride; @@ -2084,7 +2084,7 @@ static void yuv2rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); dy += this->step_dy; _dst += this->rgb_stride; @@ -2095,7 +2095,7 @@ static void yuv2rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, _py += this->y_stride*(dy>>15); dy &= 32767; - /* dy -= 32768; + /* dy -= 32768; _py += this->y_stride; */ } @@ -2146,7 +2146,7 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, X_RGB(1); DST1CMAP(1); - + X_RGB(2); DST1CMAP(2); @@ -2164,7 +2164,7 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); dy += this->step_dy; _dst += this->rgb_stride; @@ -2183,12 +2183,12 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, if (height & 1) { _pu += this->uv_stride; _pv += this->uv_stride; - + scale_line (_pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (_pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768 ); @@ -2228,7 +2228,7 @@ static void yuv2rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, dst_2 += 8; } while (--width); - _dst += 2 * this->rgb_stride; + _dst += 2 * this->rgb_stride; _py += 2 * this->y_stride; _pu += this->uv_stride; _pv += this->uv_stride; @@ -2424,7 +2424,7 @@ static void yuv2rgb_set_csc_levels (yuv2rgb_factory_t *this, lprintf ("mode %d not supported by yuv2rgb\n", mode); _x_abort(); } - + for (i = 0; i < 256; i++) { this->table_rV[i] = (((uint8_t *) table_r) + entry_size * div_round (crv * (i-128), 76309)); @@ -2437,7 +2437,7 @@ static void yuv2rgb_set_csc_levels (yuv2rgb_factory_t *this, #if defined(ARCH_X86) || defined(ARCH_X86_64) mmx_yuv2rgb_set_csc_levels (this, brightness, contrast, saturation); -#endif +#endif } static uint32_t yuv2rgb_single_pixel_32 (yuv2rgb_t *this, uint8_t y, uint8_t u, uint8_t v) @@ -2623,10 +2623,10 @@ static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) this->dest_width >> 1, this->step_dx); scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); - + dy = 0; height = this->next_slice (this, &_dst); - + for (;;) { dst_1 = (uint32_t*)_dst; py_1 = this->y_buffer; @@ -2642,10 +2642,10 @@ static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) X_RGB(1); DST1(1); - + X_RGB(2); DST1(2); - + X_RGB(3); DST1(3); @@ -2654,18 +2654,18 @@ static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) py_1 += 8; dst_1 += 8; } while (--width); - + dy += this->step_dy; _dst += this->rgb_stride; - + while (--height > 0 && dy < 32768) { - + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*4); - + dy += this->step_dy; _dst += this->rgb_stride; } - + if (height <= 0) break; @@ -2675,12 +2675,12 @@ static void yuy22rgb_c_32 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) dy -= 32768; _p += this->y_stride*2; */ - + scale_line_4 (_p+1, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line_2 (_p, this->y_buffer, + scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); } } @@ -2700,30 +2700,30 @@ static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line_2 (_p, this->y_buffer, + scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); dy = 0; height = this->next_slice (this, &_dst); - + for (;;) { dst_1 = _dst; py_1 = this->y_buffer; pu = this->u_buffer; pv = this->v_buffer; - + width = this->dest_width >> 3; - + do { X_RGB(0); DST1RGB(0); - + X_RGB(1); DST1RGB(1); - + X_RGB(2); DST1RGB(2); - + X_RGB(3); DST1RGB(3); @@ -2735,15 +2735,15 @@ static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) dy += this->step_dy; _dst += this->rgb_stride; - + while (--height > 0 && dy < 32768) { xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3); - + dy += this->step_dy; _dst += this->rgb_stride; } - + if (height <= 0) break; @@ -2753,7 +2753,7 @@ static void yuy22rgb_c_24_rgb (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) dy -= 32768; _p += this->y_stride*2; */ - + scale_line_4 (_p+1, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, @@ -2778,50 +2778,50 @@ static void yuy22rgb_c_24_bgr (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line_2 (_p, this->y_buffer, + scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); dy = 0; height = this->next_slice (this, &_dst); - + for (;;) { dst_1 = _dst; py_1 = this->y_buffer; pu = this->u_buffer; pv = this->v_buffer; - + width = this->dest_width >> 3; - + do { X_RGB(0); DST1BGR(0); - + X_RGB(1); DST1BGR(1); - + X_RGB(2); DST1BGR(2); X_RGB(3); DST1BGR(3); - + pu += 4; pv += 4; py_1 += 8; dst_1 += 24; } while (--width); - + dy += this->step_dy; _dst += this->rgb_stride; - + while (--height > 0 && dy < 32768) { xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*3); - + dy += this->step_dy; _dst += this->rgb_stride; } - + if (height <= 0) break; @@ -2852,9 +2852,9 @@ static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line_2 (_p, this->y_buffer, + scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); - + dy = 0; height = this->next_slice (this, &_dst); @@ -2863,19 +2863,19 @@ static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) py_1 = this->y_buffer; pu = this->u_buffer; pv = this->v_buffer; - + width = this->dest_width >> 3; - + do { X_RGB(0); DST1(0); X_RGB(1); DST1(1); - + X_RGB(2); DST1(2); - + X_RGB(3); DST1(3); @@ -2884,24 +2884,24 @@ static void yuy22rgb_c_16 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) py_1 += 8; dst_1 += 8; } while (--width); - + dy += this->step_dy; _dst += this->rgb_stride; while (--height > 0 && dy < 32768) { - - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); + + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); dy += this->step_dy; _dst += this->rgb_stride; } - + if (height <= 0) break; _p += this->y_stride*(dy>>15); dy &= 32767; - + scale_line_4 (_p+1, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, @@ -2928,28 +2928,28 @@ static void yuy22rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) this->dest_width >> 1, this->step_dx); scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); - + dy = 0; height = this->next_slice (this, &_dst); - + for (;;) { dst_1 = _dst; py_1 = this->y_buffer; pu = this->u_buffer; pv = this->v_buffer; - + width = this->dest_width >> 3; - + do { X_RGB(0); DST1(0); - + X_RGB(1); DST1(1); X_RGB(2); DST1(2); - + X_RGB(3); DST1(3); @@ -2958,29 +2958,29 @@ static void yuy22rgb_c_8 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) py_1 += 8; dst_1 += 8; } while (--width); - + dy += this->step_dy; _dst += this->rgb_stride; - + while (--height > 0 && dy < 32768) { - - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); - + + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + dy += this->step_dy; _dst += this->rgb_stride; } - + if (height <= 0) break; _p += this->y_stride*(dy>>15); dy &= 32767; - + scale_line_4 (_p+1, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line_2 (_p, this->y_buffer, + scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); } } @@ -2995,21 +2995,21 @@ static void yuy22rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) if (this->do_scale) { dy = 0; height = this->next_slice (this, &_dst); - + for (;;) { scale_line_2 (_p, _dst, this->dest_width, this->step_dx); - + dy += this->step_dy; _dst += this->rgb_stride; - + while (--height > 0 && dy < 32768) { - - xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); - + + xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width); + dy += this->step_dy; _dst += this->rgb_stride; } - + if (height <= 0) break; @@ -3017,7 +3017,7 @@ static void yuy22rgb_c_gray (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) dy &= 32767; } } else { - for (height = this->next_slice (this, &_dst); --height >= 0; ) { + for (height = this->next_slice (this, &_dst); --height >= 0; ) { dst = _dst; y = _p; for (width = this->source_width; --width >= 0; ) { @@ -3038,25 +3038,25 @@ static void yuy22rgb_c_palette (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _p) uint8_t * dst_1; int width, height; int dy; - + scale_line_4 (_p+1, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line_4 (_p+3, this->v_buffer, this->dest_width >> 1, this->step_dx); scale_line_2 (_p, this->y_buffer, this->dest_width, this->step_dx); - + dy = 0; height = this->next_slice (this, &_dst); - + for (;;) { dst_1 = _dst; py_1 = this->y_buffer; pu = this->u_buffer; pv = this->v_buffer; - + width = this->dest_width >> 3; - + do { X_RGB(0); DST1CMAP(0); @@ -3144,7 +3144,7 @@ static void yuy22rgb_c_init (yuv2rgb_factory_t *this) static yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) { - yuv2rgb_t *this = xine_xmalloc (sizeof (yuv2rgb_t)); + yuv2rgb_t *this = calloc(1, sizeof(yuv2rgb_t)); this->swapped = factory->swapped; this->cmap = factory->cmap; @@ -3176,7 +3176,7 @@ static yuv2rgb_t *yuv2rgb_create_converter (yuv2rgb_factory_t *factory) { } /* - * factory functions + * factory functions */ static void yuv2rgb_factory_dispose (yuv2rgb_factory_t *this) { @@ -3186,7 +3186,7 @@ static void yuv2rgb_factory_dispose (yuv2rgb_factory_t *this) { free (this); } -yuv2rgb_factory_t* yuv2rgb_factory_init (int mode, int swapped, +yuv2rgb_factory_t* yuv2rgb_factory_init (int mode, int swapped, uint8_t *cmap) { yuv2rgb_factory_t *this; diff --git a/src/video_out/yuv2rgb.h b/src/video_out/yuv2rgb.h index dce0ade18..1a1252f40 100644 --- a/src/video_out/yuv2rgb.h +++ b/src/video_out/yuv2rgb.h @@ -114,7 +114,7 @@ struct yuv2rgb_s { void *table_mmx; uint8_t *cmap; - scale_line_func_t scale_line; + scale_line_func_t scale_line; } ; /* @@ -124,7 +124,7 @@ struct yuv2rgb_s { struct yuv2rgb_factory_s { yuv2rgb_t* (*create_converter) (yuv2rgb_factory_t *this); - /* + /* * set color space conversion levels * for all converters produced by this factory */ @@ -160,7 +160,7 @@ struct yuv2rgb_factory_s { yuv2rgb_factory_t *yuv2rgb_factory_init (int mode, int swapped, uint8_t *colormap); - + /* * internal stuff below this line */ diff --git a/src/video_out/yuv2rgb_mlib.c b/src/video_out/yuv2rgb_mlib.c index 8635526ed..a10503d55 100644 --- a/src/video_out/yuv2rgb_mlib.c +++ b/src/video_out/yuv2rgb_mlib.c @@ -38,8 +38,6 @@ #include "xineutils.h" #include "yuv2rgb.h" -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - static void mlib_yuv420_rgb24(yuv2rgb_t *this, uint8_t * image, uint8_t * py, uint8_t * pu, uint8_t * pv) @@ -53,7 +51,7 @@ static void mlib_yuv420_rgb24(yuv2rgb_t *this, mlib_s32 resize_stride = this->dest_width << 2; mlib_VideoColorYUV420seq_to_ARGBint((mlib_u32*)this->mlib_buffer, - py, pu, pv, py, 0, + py, pu, pv, py, 0, this->source_width, src_height, this->source_width<<2, @@ -90,7 +88,7 @@ static void mlib_yuv420_argb32(yuv2rgb_t *this, dst_height = this->next_slice(this, &image); if (this->do_scale) { mlib_VideoColorYUV420seq_to_ARGBint((mlib_u32*)this->mlib_buffer, - py, pu, pv, py, 0, + py, pu, pv, py, 0, this->source_width, src_height, this->source_width<<2, @@ -103,7 +101,7 @@ static void mlib_yuv420_argb32(yuv2rgb_t *this, this->mlib_filter_type); } else { mlib_VideoColorYUV420seq_to_ARGBint((mlib_u32*)image, - py, pu, pv, py, 0, + py, pu, pv, py, 0, this->source_width, dst_height, this->rgb_stride, @@ -129,7 +127,7 @@ static void mlib_yuv420_abgr32(yuv2rgb_t *this, dst_height = this->next_slice (this, &image); if (this->do_scale) { mlib_VideoColorYUV420seq_to_ABGRint((mlib_u32*)this->mlib_buffer, - py, pu, pv, py, 0, + py, pu, pv, py, 0, this->source_width, src_height, this->source_width<<2, @@ -143,7 +141,7 @@ static void mlib_yuv420_abgr32(yuv2rgb_t *this, } else { mlib_VideoColorYUV420seq_to_ABGRint((mlib_u32*)image, - py, pu, pv, py, 0, + py, pu, pv, py, 0, this->source_width, dst_height, this->rgb_stride, diff --git a/src/video_out/yuv2rgb_mmx.c b/src/video_out/yuv2rgb_mmx.c index 20a9b5a00..46db48179 100644 --- a/src/video_out/yuv2rgb_mmx.c +++ b/src/video_out/yuv2rgb_mmx.c @@ -175,7 +175,7 @@ static inline void mmx_yuv2rgb (uint8_t * py, uint8_t * pu, uint8_t * pv, mmx_cs pmulhw_m2r (csc->V_green, mm4); // mm4 = v * v_green - + // slot @@ -399,7 +399,7 @@ static inline void mmx_unpack_24rgb (uint8_t * image, int cpu) pand_m2r (mmx_lorgb, mm6); psrlq_i2r (8, mm5); por_r2r(mm6, mm5); /* mm5 = 0x0000R1G1B1R0G0B0 */ - + movq_r2r (mm0, mm6); punpcklbw_r2r (mm2, mm6); punpckhwd_r2r (mm7, mm6); /* mm6 = 0x??R3G3B3??R2G2B2 */ @@ -474,13 +474,13 @@ static inline void yuv420_rgb16 (yuv2rgb_t *this, i = width; img = image; do { mmx_yuv2rgb (py, pu, pv, this->table_mmx); - mmx_unpack_16rgb (img, cpu); + mmx_unpack_16rgb (img, cpu); py += 8; pu += 4; pv += 4; img += 16; } while (--i); - + py += y_stride; image += rgb_stride; if (height & 1) { @@ -502,7 +502,7 @@ static inline void yuv420_rgb16 (yuv2rgb_t *this, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); dst_height = this->next_slice (this, &image); @@ -518,19 +518,19 @@ static inline void yuv420_rgb16 (yuv2rgb_t *this, /* printf ("i : %d\n",i); */ mmx_yuv2rgb (y_buf, u_buf, v_buf, this->table_mmx); - mmx_unpack_16rgb (img, cpu); + mmx_unpack_16rgb (img, cpu); y_buf += 8; u_buf += 4; v_buf += 4; img += 16; } while (--i); - + dy += this->step_dy; image += rgb_stride; while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (image, image-rgb_stride, this->dest_width*2); + xine_fast_memcpy (image, image-rgb_stride, this->dest_width*2); dy += this->step_dy; image += rgb_stride; @@ -544,23 +544,23 @@ static inline void yuv420_rgb16 (yuv2rgb_t *this, py += y_stride; - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { pu += uv_stride; pv += uv_stride; - + scale_line (pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768); } - } + } } static inline void yuv420_rgb15 (yuv2rgb_t *this, @@ -587,13 +587,13 @@ static inline void yuv420_rgb15 (yuv2rgb_t *this, i = width; img = image; do { mmx_yuv2rgb (py, pu, pv, this->table_mmx); - mmx_unpack_15rgb (img, cpu); + mmx_unpack_15rgb (img, cpu); py += 8; pu += 4; pv += 4; img += 16; } while (--i); - + py += y_stride; image += rgb_stride; if (height & 1) { @@ -615,11 +615,11 @@ static inline void yuv420_rgb15 (yuv2rgb_t *this, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); - + dst_height = this->next_slice (this, &image); - + for (height = 0;; ) { y_buf = this->y_buffer; @@ -631,19 +631,19 @@ static inline void yuv420_rgb15 (yuv2rgb_t *this, /* printf ("i : %d\n",i); */ mmx_yuv2rgb (y_buf, u_buf, v_buf, this->table_mmx); - mmx_unpack_15rgb (img, cpu); + mmx_unpack_15rgb (img, cpu); y_buf += 8; u_buf += 4; v_buf += 4; img += 16; } while (--i); - + dy += this->step_dy; image += rgb_stride; while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (image, image-rgb_stride, this->dest_width*2); + xine_fast_memcpy (image, image-rgb_stride, this->dest_width*2); dy += this->step_dy; image += rgb_stride; @@ -656,23 +656,23 @@ static inline void yuv420_rgb15 (yuv2rgb_t *this, dy -= 32768; py += y_stride; - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { pu += uv_stride; pv += uv_stride; - + scale_line (pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - + } height++; } while( dy>=32768 ); } - } + } } static inline void yuv420_rgb24 (yuv2rgb_t *this, @@ -725,7 +725,7 @@ static inline void yuv420_rgb24 (yuv2rgb_t *this, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); dst_height = this->next_slice (this, &image); @@ -742,13 +742,13 @@ static inline void yuv420_rgb24 (yuv2rgb_t *this, /* printf ("i : %d\n",i); */ mmx_yuv2rgb (y_buf, u_buf, v_buf, this->table_mmx); - mmx_unpack_24rgb (img, cpu); + mmx_unpack_24rgb (img, cpu); y_buf += 8; u_buf += 4; v_buf += 4; img += 24; } while (--i); - + dy += this->step_dy; image += rgb_stride; @@ -766,14 +766,14 @@ static inline void yuv420_rgb24 (yuv2rgb_t *this, do { dy -= 32768; py += y_stride; - - scale_line (py, this->y_buffer, + + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { pu += uv_stride; pv += uv_stride; - + scale_line (pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, @@ -783,7 +783,7 @@ static inline void yuv420_rgb24 (yuv2rgb_t *this, } while( dy>=32768 ); } - + } } @@ -837,11 +837,11 @@ static inline void yuv420_argb32 (yuv2rgb_t *this, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); dst_height = this->next_slice (this, &image); - + for (height = 0;; ) { y_buf = this->y_buffer; @@ -854,19 +854,19 @@ static inline void yuv420_argb32 (yuv2rgb_t *this, /* printf ("i : %d\n",i); */ mmx_yuv2rgb (y_buf, u_buf, v_buf, this->table_mmx); - mmx_unpack_32rgb (img, cpu); + mmx_unpack_32rgb (img, cpu); y_buf += 8; u_buf += 4; v_buf += 4; img += 32; } while (--i); - + dy += this->step_dy; image += rgb_stride; while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (image, image-rgb_stride, this->dest_width*4); + xine_fast_memcpy (image, image-rgb_stride, this->dest_width*4); dy += this->step_dy; image += rgb_stride; @@ -878,14 +878,14 @@ static inline void yuv420_argb32 (yuv2rgb_t *this, do { dy -= 32768; py += y_stride; - - scale_line (py, this->y_buffer, + + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { pu += uv_stride; pv += uv_stride; - + scale_line (pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, @@ -894,7 +894,7 @@ static inline void yuv420_argb32 (yuv2rgb_t *this, height++; } while( dy>=32768 ); } - + } } @@ -948,11 +948,11 @@ static inline void yuv420_abgr32 (yuv2rgb_t *this, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, this->dest_width >> 1, this->step_dx); - scale_line (py, this->y_buffer, + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); dst_height = this->next_slice (this, &image); - + for (height = 0;; ) { y_buf = this->y_buffer; @@ -965,19 +965,19 @@ static inline void yuv420_abgr32 (yuv2rgb_t *this, /* printf ("i : %d\n",i); */ mmx_yuv2rgb (y_buf, u_buf, v_buf, this->table_mmx); - mmx_unpack_32bgr (img, cpu); + mmx_unpack_32bgr (img, cpu); y_buf += 8; u_buf += 4; v_buf += 4; img += 32; } while (--i); - + dy += this->step_dy; image += rgb_stride; while (--dst_height > 0 && dy < 32768) { - xine_fast_memcpy (image, image-rgb_stride, this->dest_width*4); + xine_fast_memcpy (image, image-rgb_stride, this->dest_width*4); dy += this->step_dy; image += rgb_stride; @@ -989,14 +989,14 @@ static inline void yuv420_abgr32 (yuv2rgb_t *this, do { dy -= 32768; py += y_stride; - - scale_line (py, this->y_buffer, + + scale_line (py, this->y_buffer, this->dest_width, this->step_dx); if (height & 1) { pu += uv_stride; pv += uv_stride; - + scale_line (pu, this->u_buffer, this->dest_width >> 1, this->step_dx); scale_line (pv, this->v_buffer, @@ -1006,7 +1006,7 @@ static inline void yuv420_abgr32 (yuv2rgb_t *this, } while( dy>=32768 ); } - + } } @@ -1082,7 +1082,7 @@ static void mmx_abgr32 (yuv2rgb_t *this, uint8_t * image, void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this) { - if (this->swapped) + if (this->swapped) return; /*no swapped pixel output upto now*/ switch (this->mode) { @@ -1106,7 +1106,7 @@ void yuv2rgb_init_mmxext (yuv2rgb_factory_t *this) { void yuv2rgb_init_mmx (yuv2rgb_factory_t *this) { - if (this->swapped) + if (this->swapped) return; /*no swapped pixel output upto now*/ switch (this->mode) { diff --git a/src/xine-engine/accel_xvmc.h b/src/xine-engine/accel_xvmc.h index cec5f9558..197b76050 100644 --- a/src/xine-engine/accel_xvmc.h +++ b/src/xine-engine/accel_xvmc.h @@ -3,23 +3,23 @@ * Copyright (C) 2004 the Unichrome project * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * - * Common acceleration definitions for XvMC. + * Common acceleration definitions for XvMC. * * */ @@ -81,7 +81,7 @@ typedef struct xine_xxmc_s { */ xine_xvmc_t xvmc; - + unsigned mpeg; unsigned acceleration; int fallback_format; @@ -103,7 +103,7 @@ typedef struct xine_xxmc_s { * For thread-safety only. */ - int (*proc_xxmc_lock_valid) (vo_frame_t *cur_frame, vo_frame_t *fw_frame, + int (*proc_xxmc_lock_valid) (vo_frame_t *cur_frame, vo_frame_t *fw_frame, vo_frame_t *bw_frame,unsigned pc_type); void (*proc_xxmc_unlock) (vo_driver_t *this_gen); } xine_xxmc_t; diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c index a7ab33cf8..4727740bd 100644 --- a/src/xine-engine/alphablend.c +++ b/src/xine-engine/alphablend.c @@ -1,7 +1,7 @@ /* * * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 - * + * * Copyright (C) 2000 Thomas Mirlacher * 2002-2004 the xine project * @@ -23,6 +23,10 @@ * */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + /* #define LOG_BLEND_YUV #define LOG_BLEND_RGB16 @@ -110,7 +114,7 @@ rle_img_advance_line(rle_elem_t *rle, rle_elem_t *rle_limit, int w) /* * heck, this function is overly complicated and currently buggy. - * if James would like to revive it (implementing proper clipping - + * if James would like to revive it (implementing proper clipping - * not to confuse with button highlight) i would have no objections, * but for now i will be using an alternate version based on rgb24. [MF] * @@ -177,7 +181,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, printf("blend_rgb16: dy_step=%i, x_scale=%i\n", dy_step, x_scale); #endif if (img_width & 1) img_width++; - img_offset = ( ( (y_off * img_height) / dst_height) * img_width) + img_offset = ( ( (y_off * img_height) / dst_height) * img_width) + ( (x_off * img_width) / dst_width); #ifdef LOG_BLEND_RGB16 printf("blend_rgb16: x=%i, y=%i, w=%i, h=%i, img_offset=%lf\n", img_overl->x, img_overl->y, @@ -186,7 +190,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, img_offset); #endif img_pix = (uint16_t *) img + (int)img_offset; -/* +/* + (y_off * img_height / dst_height) * img_width + (x_off * img_width / dst_width); */ @@ -196,26 +200,26 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else @@ -229,7 +233,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, x = x1_scaled = x2_scaled = 0; #ifdef LOG_BLEND_RGB16 - printf("blend_rgb16 started\n"); + printf("blend_rgb16 started\n"); #endif while (zone_state != 6) { @@ -283,10 +287,10 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); } x += rle_this_bite; - if (x >= src_width ) { + if (x >= src_width ) { x -= src_width; img_pix += img_width; - + dy += dy_step; if (dy >= INT_TO_SCALED(1)) { dy -= INT_TO_SCALED(1); @@ -300,7 +304,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, } else { rle = rle_start; /* y-scaling, reuse the last rle encoded line */ } - } + } rle_remainder = rlelen = rle->len; clr_next = rle->color; rle++; @@ -341,7 +345,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); } x += rle_this_bite; - if (x >= src_width ) { + if (x >= src_width ) { x -= src_width; img_pix += img_width; dy += dy_step; @@ -386,7 +390,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); } x += rle_this_bite; - if (x >= src_width ) { + if (x >= src_width ) { x -= src_width; img_pix += img_width; dy += dy_step; @@ -406,7 +410,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, zone_state = 5; break; } - } + } if (rle >= rle_limit) { zone_state = 6; } @@ -431,7 +435,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); } x += rle_this_bite; - if (x >= src_width ) { + if (x >= src_width ) { x -= src_width; img_pix += img_width; dy += dy_step; @@ -451,7 +455,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, zone_state = 5; break; } - } + } if (rle >= rle_limit) { zone_state = 6; } @@ -469,7 +473,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); } x += rle_this_bite; - if (x >= src_width ) { + if (x >= src_width ) { x -= src_width; img_pix += img_width; dy += dy_step; @@ -485,7 +489,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, } else { rle = rle_start; /* y-scaling, reuse the last rle encoded line */ } - } + } rle_remainder = rlelen = rle->len; clr_next = rle->color; rle++; @@ -509,7 +513,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, mem_blend16(img_pix+x1_scaled, *((uint16_t *)&clut[clr]), o, x2_scaled-x1_scaled); } x += rle_this_bite; - if (x >= src_width ) { + if (x >= src_width ) { x -= src_width; img_pix += img_width; dy += dy_step; @@ -525,7 +529,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, } else { rle = rle_start; /* y-scaling, reuse the last rle encoded line */ } - } + } rle_remainder = rlelen = rle->len; clr_next = rle->color; rle++; @@ -540,7 +544,7 @@ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, #ifdef LOG_BLEND_RGB16 printf("blend_rgb16 ended\n"); #endif - + } #endif @@ -572,26 +576,26 @@ void _x_blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else @@ -615,7 +619,7 @@ void _x_blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, if (rlelen <= 0) { if (rle >= rle_limit) break; - + rlelen = rle->len; clr = rle->color; rle++; @@ -623,7 +627,7 @@ void _x_blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, if (!mask) { /* above or below highlight area */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; @@ -642,7 +646,7 @@ void _x_blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, trans = img_overl->trans; } else { /* ends left */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; @@ -662,25 +666,25 @@ void _x_blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, trans = img_overl->hili_trans; } else { /* starts right */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; trans = img_overl->trans; - + if( x + rle_bite >= clip_right ) clipped = 1; } } else { /* starts not left and ends not right */ - + rle_bite = rlelen; /* we're in the center area so choose highlight palette */ colors = (clut_t*)img_overl->hili_color; trans = img_overl->hili_trans; } } - + x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale); o = trans[clr]; @@ -739,26 +743,26 @@ void _x_blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else @@ -782,7 +786,7 @@ void _x_blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, if (rlelen <= 0) { if (rle >= rle_limit) break; - + rlelen = rle->len; clr = rle->color; rle++; @@ -790,7 +794,7 @@ void _x_blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, if (!mask) { /* above or below highlight area */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; @@ -809,7 +813,7 @@ void _x_blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, trans = img_overl->trans; } else { /* ends left */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; @@ -829,25 +833,25 @@ void _x_blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, trans = img_overl->hili_trans; } else { /* starts right */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; trans = img_overl->trans; - + if( x + rle_bite >= clip_right ) clipped = 1; } } else { /* starts not left and ends not right */ - + rle_bite = rlelen; /* we're in the center area so choose highlight palette */ colors = (clut_t*)img_overl->hili_color; trans = img_overl->hili_trans; } } - + x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale); o = trans[clr]; @@ -906,50 +910,50 @@ void _x_blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else hili_left = clip_left; - + for (y = dy = 0; y < src_height && rle < rle_limit; ) { int mask = !(y < img_overl->hili_top || y >= img_overl->hili_bottom); rle_elem_t *rle_start = rle; int rlelen = 0; uint8_t clr = 0; - + for (x = x1_scaled = 0; x < src_width;) { int rle_bite; clut_t *colors; uint8_t *trans; uint16_t o; int clipped = (y < clip_top); - + /* take next element from rle list everytime an element is finished */ if (rlelen <= 0) { if (rle >= rle_limit) break; - + rlelen = rle->len; clr = rle->color; rle++; @@ -957,7 +961,7 @@ void _x_blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, if (!mask) { /* above or below highlight area */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; @@ -976,7 +980,7 @@ void _x_blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, trans = img_overl->trans; } else { /* ends left */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; @@ -996,25 +1000,25 @@ void _x_blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, trans = img_overl->hili_trans; } else { /* starts right */ - + rle_bite = rlelen; /* choose palette for surrounding area */ colors = (clut_t*)img_overl->color; trans = img_overl->trans; - + if( x + rle_bite >= clip_right ) clipped = 1; } } else { /* starts not left and ends not right */ - + rle_bite = rlelen; /* we're in the center area so choose highlight palette */ colors = (clut_t*)img_overl->hili_color; trans = img_overl->hili_trans; } } - + x2_scaled = SCALED_TO_INT((x + rle_bite) * x_scale); o = trans[clr]; @@ -1052,11 +1056,11 @@ static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz) } } -static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, +static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, uint8_t *(*blend_yuv_data)[ 3 ][ 2 ]) { int x; - + for (x = 0; x < src_width; x += 2) { /* get opacity of the 4 pixels that share chroma */ int o00 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 0 ]; @@ -1074,7 +1078,7 @@ static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, int cr01 = (*blend_yuv_data)[ 1 ][ 0 ][ x + 1 ]; int cr10 = (*blend_yuv_data)[ 1 ][ 1 ][ x + 0 ]; int cr11 = (*blend_yuv_data)[ 1 ][ 1 ][ x + 1 ]; - + int cb00 = (*blend_yuv_data)[ 2 ][ 0 ][ x + 0 ]; int cb01 = (*blend_yuv_data)[ 2 ][ 0 ][ x + 1 ]; int cb10 = (*blend_yuv_data)[ 2 ][ 1 ][ x + 0 ]; @@ -1104,18 +1108,18 @@ static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ][ 2 ] { - struct __attribute__((packed)) header_s { + struct XINE_PACKED header_s { int id; int max_width; uint8_t *data[ 3 ][ 2 ]; } *header = (struct header_s *)extra_data->buffer; - - int needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ][ 2 ]); - + + size_t needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ][ 2 ]); + if (extra_data->buffer_size < needed_buffer_size) { - + free(extra_data->buffer); - header = xine_xmalloc(needed_buffer_size); + header = calloc(1, needed_buffer_size); if (!header) { extra_data->buffer_size = 0; return 0; @@ -1139,7 +1143,7 @@ static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_wi return &(header->data); } - + void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, int dst_width, int dst_height, int dst_pitches[3], alphablend_t *extra_data) @@ -1164,12 +1168,12 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, int hili_right, hili_left; int clip_right, clip_left, clip_top; uint8_t clr=0; - + int any_line_buffered = 0; int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off)); int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */ uint8_t *(*blend_yuv_data)[ 3 ][ 2 ] = 0; - + uint8_t *dst_y = dst_base[0] + dst_pitches[0] * y_off + x_off; uint8_t *dst_cr = dst_base[2] + (y_off / 2) * dst_pitches[1] + (x_off / 2); uint8_t *dst_cb = dst_base[1] + (y_off / 2) * dst_pitches[2] + (x_off / 2); @@ -1184,26 +1188,26 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else @@ -1215,16 +1219,16 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, if (enable_exact_blending) { if (exact_blend_width <= 0) return; - + blend_yuv_data = blend_yuv_grow_extra_data(extra_data, exact_blend_width_m2); if (!blend_yuv_data) return; - + /* make linebuffer transparent */ memset(&(*blend_yuv_data)[ 0 ][ 0 ][ 0 ], 0, exact_blend_width_m2); memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } - + rlelen=rle_remainder=0; for (y = 0; y < src_height; y++) { if (rle >= rle_limit) { @@ -1233,7 +1237,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, #endif break; } - + ymask = ((y < img_overl->hili_top) || (y >= img_overl->hili_bottom)); xmask = 0; #ifdef LOG_BLEND_YUV @@ -1243,14 +1247,14 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, for (x = 0; x < src_width;) { uint16_t o; int clipped = (y < clip_top); - + if (rle >= rle_limit) { #ifdef LOG_BLEND_YUV printf("x-rle_limit\n"); #endif break; } - + #ifdef LOG_BLEND_YUV printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); #endif @@ -1259,7 +1263,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, #ifdef LOG_BLEND_YUV printf("alphablend: major bug in blend_yuv < 0\n"); #endif - } + } if (rlelen == 0) { rle_remainder = rlelen = rle->len; clr = rle->color; @@ -1277,11 +1281,11 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, #endif if (ymask == 0) { - if (x < hili_left) { + if (x < hili_left) { /* Starts outside highlight area */ if ((x + rle_remainder) > hili_left ) { #ifdef LOG_BLEND_YUV - printf("Outside highlight left %d, ending inside\n", hili_left); + printf("Outside highlight left %d, ending inside\n", hili_left); #endif /* Cutting needed, starts outside, ends inside */ rle_this_bite = (hili_left - x); @@ -1292,7 +1296,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, xmask = 0; } else { #ifdef LOG_BLEND_YUV - printf("Outside highlight left %d, ending outside\n", hili_left); + printf("Outside highlight left %d, ending outside\n", hili_left); #endif /* no cutting needed, starts outside, ends outside */ rle_this_bite = rle_remainder; @@ -1331,7 +1335,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, } } else if (x >= hili_right) { /* Starts outside highlight area, ends outside highlight area */ - if ((x + rle_remainder ) > src_width ) { + if ((x + rle_remainder ) > src_width ) { #ifdef LOG_BLEND_YUV printf("Outside highlight right %d, ending eol\n", hili_right); #endif @@ -1377,7 +1381,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, /* clip against right edge of destination area */ if ((x + rle_this_bite) > (dst_width - x_off)) { int toClip = (x + rle_this_bite) - (dst_width - x_off); - + rle_this_bite -= toClip; rle_remainder += toClip; rlelen += toClip; @@ -1388,7 +1392,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, memset(&(*blend_yuv_data)[ 0 ][ (y + y_odd) & 1 ][ x + x_odd ], o, rle_this_bite); any_line_buffered |= ((y + y_odd) & 1) ? 2 : 1; } - + if (o && !clipped) { if(o >= 15) { memset(dst_y + x, my_clut[clr].y, rle_this_bite); @@ -1430,17 +1434,17 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, /* make second line transparent */ memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } - + blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, blend_yuv_data); - + any_line_buffered = 0; } } - + dst_cr += dst_pitches[2]; dst_cb += dst_pitches[1]; } - + dst_y += dst_pitches[0]; } @@ -1451,21 +1455,21 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, /* make second line transparent */ memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } - + blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, blend_yuv_data); } } - + #ifdef LOG_BLEND_YUV printf("overlay_blend ended\n"); #endif } - + static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, uint8_t *(*blend_yuy2_data)[ 3 ]) { int x; - + for (x = 0; x < src_width; x += 2) { /* get opacity of the 2 pixels that share chroma */ int o0 = (*blend_yuy2_data)[ 0 ][ x + 0 ]; @@ -1477,7 +1481,7 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, /* get the chroma components of the 2 pixels */ int cr0 = (*blend_yuy2_data)[ 1 ][ x + 0 ]; int cr1 = (*blend_yuy2_data)[ 1 ][ x + 1 ]; - + int cb0 = (*blend_yuy2_data)[ 2 ][ x + 0 ]; int cb1 = (*blend_yuy2_data)[ 2 ][ x + 1 ]; @@ -1492,7 +1496,7 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, /* * No need to adjust chroma values with +/- 128: - * *dst_cb + * *dst_cb * = 128 + ((*dst_cb-128) * t2 + (cb0-128) * o0 + (cb1-128) * o1) / (2 * 0xf); * = 128 + (*dst_cb * t2 + cb0 * o0 + cb1 * o1 + (t2*(-128) - 128*o0 - 128*o1)) / (2 * 0xf); * = 128 + (*dst_cb * t2 + cb0 * o0 + cb1 * o1 + ((2*0xf-o0-o1)*(-128) - 128*o0 - 128*o1)) / (2 * 0xf); @@ -1508,8 +1512,8 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, * =(almost) X * 0x1112/0x10000 * = (X * 0x1112) >> 16 * - * The tricky point is 0x1111/0xffff --> 0x1112/0x10000. - * All calculations are done using integers and X is in + * The tricky point is 0x1111/0xffff --> 0x1112/0x10000. + * All calculations are done using integers and X is in * range of [0 ... 0xff*0xf*4]. This results in error of * X*0x1112/0x10000 - X/0xf * = X*(0x1112/0x10000 - 1/0xf) @@ -1519,7 +1523,7 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, * As the error is less than 1 and always positive, whole error * "disappears" during truncation (>>16). Rounding to exact results is * guaranteed by selecting 0x1112 instead of more accurate 0x1111 - * (with 0x1111 error=X*(-0.00001111...)). With 0x1112 error is + * (with 0x1111 error=X*(-0.00001111...)). With 0x1112 error is * always positive, but still less than one. * So, one can forget the "=(almost)" as it is really "=" when source * operands are within 0...0xff (U,V) and 0...0xf (A). @@ -1527,7 +1531,7 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, * 1/0x10000 (= >>16) was originally selected because of MMX pmullhw * instruction; it makes possible to do whole calculation in MMX using * uint16's (pmullhw is (X*Y)>>16). - * + * * Here X/(2*0xf) = X/0xf/2 = ((X*0x1112)>>16)>>1 = (X*0x1112)>>17 */ @@ -1546,18 +1550,18 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_width))[ 3 ] { - struct __attribute__((packed)) header_s { + struct XINE_PACKED header_s { int id; int max_width; uint8_t *data[ 3 ]; } *header = (struct header_s *)extra_data->buffer; - - int needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ]); - + + size_t needed_buffer_size = sizeof (*header) + osd_width * sizeof (uint8_t[ 3 ]); + if (extra_data->buffer_size < needed_buffer_size) { - + free(extra_data->buffer); - header = xine_xmalloc(needed_buffer_size); + header = calloc(1, needed_buffer_size); if (!header) { extra_data->buffer_size = 0; return 0; @@ -1615,7 +1619,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, int exact_blend_width = ((src_width <= (dst_width - x_off)) ? src_width : (dst_width - x_off)); int exact_blend_width_m2 = (x_odd + exact_blend_width + 1) & ~1; /* make it a (larger) multiple of 2 */ uint8_t *(*blend_yuy2_data)[ 3 ] = 0; - + uint8_t *dst_y = dst_img + dst_pitch * y_off + 2 * x_off; uint8_t *dst; @@ -1627,26 +1631,26 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else @@ -1658,11 +1662,11 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, if (enable_exact_blending) { if (exact_blend_width <= 0) return; - + blend_yuy2_data = blend_yuy2_grow_extra_data(extra_data, exact_blend_width_m2); if (!blend_yuy2_data) return; - + /* make linebuffer transparent */ memset(&(*blend_yuy2_data)[ 0 ][ 0 ], 0, exact_blend_width_m2); } @@ -1671,7 +1675,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, for (y = 0; y < src_height; y++) { if (rle >= rle_limit) break; - + ymask = ((y < img_overl->hili_top) || (y >= img_overl->hili_bottom)); dst = dst_y; @@ -1681,12 +1685,12 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, if (rle >= rle_limit) break; - + if ((rlelen < 0) || (rle_remainder < 0)) { #ifdef LOG_BLEND_YUV printf("alphablend: major bug in blend_yuv < 0\n"); #endif - } + } if (rlelen == 0) { rle_remainder = rlelen = rle->len; clr = rle->color; @@ -1704,11 +1708,11 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, #endif if (ymask == 0) { - if (x < hili_left) { + if (x < hili_left) { /* Starts outside highlight area */ if ((x + rle_remainder) > hili_left ) { #ifdef LOG_BLEND_YUV - printf("Outside highlight left %d, ending inside\n", hili_left); + printf("Outside highlight left %d, ending inside\n", hili_left); #endif /* Cutting needed, starts outside, ends inside */ rle_this_bite = (hili_left - x); @@ -1718,7 +1722,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, my_trans = img_overl->trans; } else { #ifdef LOG_BLEND_YUV - printf("Outside highlight left %d, ending outside\n", hili_left); + printf("Outside highlight left %d, ending outside\n", hili_left); #endif /* no cutting needed, starts outside, ends outside */ rle_this_bite = rle_remainder; @@ -1754,7 +1758,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, } } else if (x >= hili_right) { /* Starts outside highlight area, ends outsite highlight area */ - if ((x + rle_remainder ) > src_width ) { + if ((x + rle_remainder ) > src_width ) { #ifdef LOG_BLEND_YUV printf("Outside highlight right %d, ending eol\n", hili_right); #endif @@ -1794,7 +1798,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, /* clip against right edge of destination area */ if ((x + rle_this_bite) > (dst_width - x_off)) { int toClip = (x + rle_this_bite) - (dst_width - x_off); - + rle_this_bite -= toClip; rle_remainder += toClip; rlelen += toClip; @@ -1846,7 +1850,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, mem_blend32(dst, &yuy2.b[0], o, l); dst += 4*l; } - + if(rle_this_bite & 1) { *dst = BLEND_BYTE(*dst, yuy2.b[0], o); dst++; @@ -1871,15 +1875,15 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, dst += rle_this_bite*2; } } - + x += rle_this_bite; } - + if (enable_exact_blending) { /* blend buffered line */ if (any_line_buffered) { blend_yuy2_exact(dst_y - x_odd * 2 + 3, dst_y - x_odd * 2 + 1, exact_blend_width, blend_yuy2_data); - + any_line_buffered = 0; } } @@ -1888,7 +1892,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, } } -void _x_clear_xx44_palette(xx44_palette_t *p) +void _x_clear_xx44_palette(xx44_palette_t *p) { register int i; register uint32_t *cluts = p->cluts; @@ -1900,20 +1904,20 @@ void _x_clear_xx44_palette(xx44_palette_t *p) i = 2*OVL_PALETTE_SIZE; while(i--) *ids++ = -1; - p->max_used=1; + p->max_used=1; } -void _x_init_xx44_palette(xx44_palette_t *p, unsigned num_entries) +void _x_init_xx44_palette(xx44_palette_t *p, unsigned num_entries) { - p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries; + p->size = (num_entries > XX44_PALETTE_SIZE) ? XX44_PALETTE_SIZE : num_entries; } -void _x_dispose_xx44_palette(xx44_palette_t *p) +void _x_dispose_xx44_palette(xx44_palette_t *p) { } static void colorToPalette(const uint32_t *icolor, unsigned char *palette_p, - unsigned num_xvmc_components, char *xvmc_components) + unsigned num_xvmc_components, char *xvmc_components) { const clut_t *color = (const clut_t *) icolor; unsigned int i; @@ -1921,7 +1925,7 @@ static void colorToPalette(const uint32_t *icolor, unsigned char *palette_p, switch(xvmc_components[i]) { case 'V': *palette_p = color->cr; break; case 'U': *palette_p = color->cb; break; - case 'Y': + case 'Y': default: *palette_p = color->y; break; } palette_p++; @@ -1931,7 +1935,7 @@ static void colorToPalette(const uint32_t *icolor, unsigned char *palette_p, void _x_xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette, unsigned first_xx44_entry, unsigned num_xx44_entries, - unsigned num_xvmc_components, char *xvmc_components) + unsigned num_xvmc_components, char *xvmc_components) { register unsigned int i; register const uint32_t *cluts = p->cluts + first_xx44_entry; @@ -1942,16 +1946,16 @@ void _x_xx44_to_xvmc_palette(const xx44_palette_t *p,unsigned char *xvmc_palette xvmc_palette += num_xvmc_components; } } -} +} -static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut) +static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut) { register unsigned int i; register uint32_t *cluts = p->cluts; register int tmp; - if ((tmp = p->lookup_cache[color]) >= 0) + if ((tmp = p->lookup_cache[color]) >= 0) if (cluts[tmp] == clut) return tmp; for (i=0; i<p->max_used; ++i) { @@ -1968,7 +1972,7 @@ static int xx44_paletteIndex(xx44_palette_t *p, int color, uint32_t clut) static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_t mask) { - register uint8_t + register uint8_t masked_val; if (0 == (masked_val = val & mask)) return; @@ -1980,16 +1984,16 @@ static void memblend_xx44(uint8_t *mem,uint8_t val, register size_t size, uint8_ } void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, - int dst_width, int dst_height, int dst_pitch, + int dst_width, int dst_height, int dst_pitch, alphablend_t *extra_data, - xx44_palette_t *palette,int ia44) + xx44_palette_t *palette,int ia44) { int src_width, src_height; rle_elem_t *rle, *rle_limit; int mask; int x_off, y_off; int x, y; - uint8_t norm_pixel,hili_pixel; + uint8_t norm_pixel,hili_pixel; uint8_t *dst_y; uint8_t *dst; uint8_t alphamask = (ia44) ? 0x0F : 0xF0; @@ -2013,26 +2017,26 @@ void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, clip_right = src_width; else clip_right = dst_width - x_off; - + if( x_off >= 0 ) clip_left = 0; else clip_left = -x_off; - + if( y_off >= 0 ) clip_top = 0; else clip_top = -y_off; - + if( (src_height + y_off) > dst_height ) src_height = dst_height - y_off; - + /* make highlight area fit into clip area */ if( img_overl->hili_right <= clip_right ) hili_right = img_overl->hili_right; else hili_right = clip_right; - + if( img_overl->hili_left >= clip_left ) hili_left = img_overl->hili_left; else @@ -2049,10 +2053,10 @@ void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, if (len > 0) { norm_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color, - img_overl->color[rle->color]) << 4) | + img_overl->color[rle->color]) << 4) | (img_overl->trans[rle->color] & 0x0F)); hili_pixel = (uint8_t)((xx44_paletteIndex(palette,rle->color+OVL_PALETTE_SIZE, - img_overl->hili_color[rle->color]) << 4) | + img_overl->hili_color[rle->color]) << 4) | (img_overl->hili_trans[rle->color] & 0x0F)); if (!ia44) { norm_pixel = ((norm_pixel & 0x0F) << 4) | ((norm_pixel & 0xF0) >> 4); @@ -2087,7 +2091,7 @@ void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, dst += len; } } - } else if (x < hili_right) { + } else if (x < hili_right) { if (len <= hili_right - x) { if(!clipped) memblend_xx44(dst,hili_pixel,len, alphamask); @@ -2119,7 +2123,7 @@ void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, x += rle->len; rle++; if (rle >= rle_limit) break; - } + } if (rle >= rle_limit) break; dst_y += dst_pitch; } @@ -2135,7 +2139,7 @@ static void alphablend_disable_exact_osd_alpha_blending_changed(void *user_data, void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine) { config_values_t *config = xine->config; - + extra_data->buffer = 0; extra_data->buffer_size = 0; extra_data->offset_x = 0; diff --git a/src/xine-engine/alphablend.h b/src/xine-engine/alphablend.h index 3c9a693d9..86cc68302 100644 --- a/src/xine-engine/alphablend.h +++ b/src/xine-engine/alphablend.h @@ -39,22 +39,7 @@ typedef struct { void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine) XINE_PROTECTED; void _x_alphablend_free(alphablend_t *extra_data) XINE_PROTECTED; -/* _MSC_VER port changes */ -#undef ATTRIBUTE_PACKED -#undef PRAGMA_PACK_BEGIN -#undef PRAGMA_PACK_END - -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) || defined(__ICC) -#define ATTRIBUTE_PACKED __attribute__ ((packed)) -#define PRAGMA_PACK 0 -#endif - -#if !defined(ATTRIBUTE_PACKED) -#define ATTRIBUTE_PACKED -#define PRAGMA_PACK 1 -#endif - -#if PRAGMA_PACK +#if !SUPPORT_ATTRIBUTE_PACKED #pragma pack(8) #endif @@ -63,10 +48,10 @@ typedef struct { /* CLUT == Color LookUp Table */ uint8_t cr; uint8_t y; uint8_t foo; -} ATTRIBUTE_PACKED clut_t; +} XINE_PACKED clut_t; -#if PRAGMA_PACK +#if !SUPPORT_ATTRIBUTE_PACKED #pragma pack() #endif @@ -112,7 +97,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, */ void _x_blend_xx44 (uint8_t *dst_img, vo_overlay_t *img_overl, - int dst_width, int dst_height, int dst_pitch, + int dst_width, int dst_height, int dst_pitch, alphablend_t *extra_data, xx44_palette_t *palette,int ia44) XINE_PROTECTED; diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c index 5476262d9..dd15bf696 100644 --- a/src/xine-engine/audio_decoder.c +++ b/src/xine-engine/audio_decoder.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -60,18 +60,18 @@ static void *audio_decoder_loop (void *stream_gen) { while (running) { - lprintf ("audio_loop: waiting for package...\n"); + lprintf ("audio_loop: waiting for package...\n"); if( !replaying_headers ) buf = stream->audio_fifo->get (stream->audio_fifo); - lprintf ("audio_loop: got package pts = %"PRId64", type = %08x\n", buf->pts, buf->type); + lprintf ("audio_loop: got package pts = %"PRId64", type = %08x\n", buf->pts, buf->type); _x_extra_info_merge( stream->audio_decoder_extra_info, buf->extra_info ); stream->audio_decoder_extra_info->seek_count = stream->video_seek_count; - + switch (buf->type) { - + case BUF_CONTROL_HEADERS_DONE: pthread_mutex_lock (&stream->counter_lock); stream->header_count_audio++; @@ -85,25 +85,27 @@ static void *audio_decoder_loop (void *stream_gen) { /* decoder dispose might call port functions */ running_ticket->acquire(running_ticket, 0); - + if (stream->audio_decoder_plugin) { lprintf ("close old decoder\n"); + stream->keep_ao_driver_open = !!(buf->decoder_flags & BUF_FLAG_GAPLESS_SW); _x_free_audio_decoder (stream, stream->audio_decoder_plugin); stream->audio_decoder_plugin = NULL; stream->audio_track_map_entries = 0; stream->audio_type = 0; + stream->keep_ao_driver_open = 0; } - + running_ticket->release(running_ticket, 0); - - if( !stream->gapless_switch ) + + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSTART, 0); - + buftype_unknown = 0; break; - + case BUF_CONTROL_END: /* free all held header buffers, see comments below */ @@ -126,12 +128,12 @@ static void *audio_decoder_loop (void *stream_gen) { */ while(1) { int num_bufs, num_streams; - + running_ticket->acquire(running_ticket, 0); num_bufs = stream->audio_out->get_property(stream->audio_out, AO_PROP_BUFS_IN_FIFO); num_streams = stream->audio_out->get_property(stream->audio_out, AO_PROP_NUM_STREAMS); running_ticket->release(running_ticket, 0); - + if( num_bufs > 0 && num_streams == 1 && !stream->early_finish_event) xine_usec_sleep (10000); else @@ -142,7 +144,7 @@ static void *audio_decoder_loop (void *stream_gen) { pthread_mutex_lock (&stream->counter_lock); stream->finished_count_audio++; - + lprintf ("reached end marker # %d\n", stream->finished_count_audio); pthread_cond_broadcast (&stream->counter_changed); @@ -162,18 +164,18 @@ static void *audio_decoder_loop (void *stream_gen) { stream->audio_channel_auto = -1; break; - + case BUF_CONTROL_QUIT: /* decoder dispose might call port functions */ running_ticket->acquire(running_ticket, 0); - + if (stream->audio_decoder_plugin) { _x_free_audio_decoder (stream, stream->audio_decoder_plugin); stream->audio_decoder_plugin = NULL; stream->audio_track_map_entries = 0; stream->audio_type = 0; } - + running_ticket->release(running_ticket, 0); running = 0; break; @@ -191,14 +193,14 @@ static void *audio_decoder_loop (void *stream_gen) { running_ticket->release(running_ticket, 0); } break; - + case BUF_CONTROL_DISCONTINUITY: if (stream->audio_decoder_plugin) { running_ticket->acquire(running_ticket, 0); stream->audio_decoder_plugin->discontinuity (stream->audio_decoder_plugin); running_ticket->release(running_ticket, 0); } - + stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off); break; @@ -208,7 +210,7 @@ static void *audio_decoder_loop (void *stream_gen) { stream->audio_decoder_plugin->discontinuity (stream->audio_decoder_plugin); running_ticket->release(running_ticket, 0); } - + if (buf->decoder_flags & BUF_FLAG_SEEK) { stream->metronom->handle_audio_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off); } else { @@ -218,7 +220,7 @@ static void *audio_decoder_loop (void *stream_gen) { case BUF_CONTROL_AUDIO_CHANNEL: { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "audio_decoder: suggested switching to stream_id %02x\n", buf->decoder_info[0]); stream->audio_channel_auto = buf->decoder_info[0] & 0xff; } @@ -246,27 +248,27 @@ static void *audio_decoder_loop (void *stream_gen) { xine_profiler_start_count (prof_audio_decode); running_ticket->acquire(running_ticket, 0); - + if ( (buf->type & 0xFF000000) == BUF_AUDIO_BASE ) { - + uint32_t audio_type = 0; int i,j; uint32_t chan=buf->type&0x0000FFFF; /* printf("audio_decoder: buf_type=%08x auto=%08x user=%08x\n", - buf->type, + buf->type, stream->audio_channel_auto, audio_channel_user); */ /* update track map */ - + i = 0; - while ( (i<stream->audio_track_map_entries) && ((stream->audio_track_map[i]&0x0000FFFF)<chan) ) + while ( (i<stream->audio_track_map_entries) && ((stream->audio_track_map[i]&0x0000FFFF)<chan) ) i++; - - if ( (i==stream->audio_track_map_entries) + + if ( (i==stream->audio_track_map_entries) || ((stream->audio_track_map[i]&0x0000FFFF)!=chan) ) { xine_event_t ui_event; @@ -302,7 +304,7 @@ static void *audio_decoder_loop (void *stream_gen) { lprintf ("audio_channel_auto = %d\n", stream->audio_channel_auto); if (stream->audio_channel_auto>=0) { - + if ((buf->type & 0xFF) == stream->audio_channel_auto) { audio_type = buf->type; } else @@ -319,30 +321,30 @@ static void *audio_decoder_loop (void *stream_gen) { } /* now, decode stream buffer if it's the right audio type */ - + if (buf->type == audio_type) { - + int streamtype = (buf->type>>16) & 0xFF; /* close old decoder of audio type has changed */ - - if( buf->type != buftype_unknown && + + if( buf->type != buftype_unknown && (stream->audio_decoder_streamtype != streamtype || !stream->audio_decoder_plugin) ) { - + if (stream->audio_decoder_plugin) { _x_free_audio_decoder (stream, stream->audio_decoder_plugin); } - + stream->audio_decoder_streamtype = streamtype; stream->audio_decoder_plugin = _x_get_audio_decoder (stream, streamtype); - + _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_HANDLED, (stream->audio_decoder_plugin != NULL)); } - + if (audio_type != stream->audio_type) { - + if (stream->audio_decoder_plugin) { xine_event_t event; @@ -353,23 +355,23 @@ static void *audio_decoder_loop (void *stream_gen) { xine_event_send(stream, &event); } } - + /* finally - decode data */ - - if (stream->audio_decoder_plugin) + + if (stream->audio_decoder_plugin) stream->audio_decoder_plugin->decode_data (stream->audio_decoder_plugin, buf); - - if (buf->type != buftype_unknown && + + if (buf->type != buftype_unknown && !_x_stream_info_get(stream, XINE_STREAM_INFO_AUDIO_HANDLED)) { xine_log (stream->xine, XINE_LOG_MSG, _("audio_decoder: no plugin available to handle '%s'\n"), _x_buf_audio_name( buf->type ) ); - + if( !_x_meta_info_get(stream, XINE_META_INFO_AUDIOCODEC) ) _x_meta_info_set_utf8(stream, XINE_META_INFO_AUDIOCODEC, _x_buf_audio_name( buf->type )); - + buftype_unknown = buf->type; - /* fatal error - dispose plugin */ + /* fatal error - dispose plugin */ if (stream->audio_decoder_plugin) { _x_free_audio_decoder (stream, stream->audio_decoder_plugin); stream->audio_decoder_plugin = NULL; @@ -378,7 +380,7 @@ static void *audio_decoder_loop (void *stream_gen) { } } } else if( buf->type != buftype_unknown ) { - xine_log (stream->xine, XINE_LOG_MSG, + xine_log (stream->xine, XINE_LOG_MSG, _("audio_decoder: error, unknown buffer type: %08x\n"), buf->type ); buftype_unknown = buf->type; } @@ -386,14 +388,14 @@ static void *audio_decoder_loop (void *stream_gen) { if (running_ticket->ticket_revoked) running_ticket->renew(running_ticket, 0); running_ticket->release(running_ticket, 0); - + xine_profiler_stop_count (prof_audio_decode); } /* some decoders require a full reinitialization when audio * channel is changed (rate might be change and even a - * different codec may be used). - * + * different codec may be used). + * * we must close the old decoder and process all the headers * again, since they are needed for decoder initialization. */ @@ -406,7 +408,7 @@ static void *audio_decoder_loop (void *stream_gen) { running_ticket->acquire(running_ticket, 0); _x_free_audio_decoder (stream, stream->audio_decoder_plugin); running_ticket->release(running_ticket, 0); - + stream->audio_decoder_plugin = NULL; stream->audio_track_map_entries = 0; stream->audio_type = 0; @@ -454,7 +456,7 @@ static void *audio_decoder_loop (void *stream_gen) { } first_header = last_header = NULL; } - + return NULL; } @@ -469,7 +471,7 @@ int _x_audio_decoder_init (xine_stream_t *stream) { return 1; } else { int num_buffers; - + /* The fifo size is based on dvd playback where buffers are filled * with 2k of data. With 230 buffers and a typical audio data rate * of 1.8 Mbit/s (four ac3 streams), the fifo can hold about 2 seconds @@ -477,7 +479,7 @@ int _x_audio_decoder_init (xine_stream_t *stream) { * We provide buffers of 8k size instead of 2k for demuxers sending * larger chunks. */ - + num_buffers = stream->xine->config->register_num (stream->xine->config, "engine.buffers.audio_num_buffers", 230, @@ -487,7 +489,7 @@ int _x_audio_decoder_init (xine_stream_t *stream) { "mean smoother playback for unreliable inputs, but " "also increased latency and memory consumption."), 20, NULL, NULL); - + stream->audio_fifo = _x_fifo_buffer_new (num_buffers, 8192); stream->audio_channel_user = -1; stream->audio_channel_auto = -1; @@ -503,17 +505,17 @@ int _x_audio_decoder_init (xine_stream_t *stream) { pth_params.sched_priority = sched_get_priority_min(SCHED_OTHER); pthread_attr_setschedparam(&pth_attrs, &pth_params); pthread_attr_setscope(&pth_attrs, PTHREAD_SCOPE_SYSTEM); - - stream->audio_thread_created = 1; + + stream->audio_thread_created = 1; if ((err = pthread_create (&stream->audio_thread, &pth_attrs, audio_decoder_loop, stream)) != 0) { - xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "audio_decoder: can't create new thread (%s)\n", strerror(err)); stream->audio_thread_created = 0; pthread_attr_destroy(&pth_attrs); return 0; } - + pthread_attr_destroy(&pth_attrs); } return 1; @@ -530,16 +532,16 @@ void _x_audio_decoder_shutdown (xine_stream_t *stream) { buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_QUIT; stream->audio_fifo->put (stream->audio_fifo, buf); - + pthread_join (stream->audio_thread, &p); stream->audio_thread_created = 0; } - + stream->audio_fifo->dispose (stream->audio_fifo); stream->audio_fifo = NULL; } int _x_get_audio_channel (xine_stream_t *stream) { - return stream->audio_type & 0xFFFF; + return stream->audio_type & 0xFFFF; } diff --git a/src/xine-engine/audio_decoder.h b/src/xine-engine/audio_decoder.h index 8f75ba242..9f695685f 100644 --- a/src/xine-engine/audio_decoder.h +++ b/src/xine-engine/audio_decoder.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -46,14 +46,14 @@ struct audio_decoder_class_s { * open a new instance of this plugin class */ audio_decoder_t* (*open_plugin) (audio_decoder_class_t *this, xine_stream_t *stream); - + /* * return short, human readable identifier for this plugin class */ char* (*get_identifier) (audio_decoder_class_t *this); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ char* (*get_description) (audio_decoder_class_t *this); @@ -69,8 +69,8 @@ struct audio_decoder_class_s { struct audio_decoder_s { /* - * decode data from buf and feed decoded samples to - * audio output + * decode data from buf and feed decoded samples to + * audio output */ void (*decode_data) (audio_decoder_t *this, buf_element_t *buf); @@ -79,13 +79,13 @@ struct audio_decoder_s { * audio data not related to recently decoded data) */ void (*reset) (audio_decoder_t *this); - + /* * inform decoder that a time reference discontinuity has happened. * that is, it must forget any currently held pts value */ - void (*discontinuity) (audio_decoder_t *this); - + void (*discontinuity) (audio_decoder_t *this); + /* * close down, free all resources */ diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c index 7fe92d9fe..4f68b8975 100644 --- a/src/xine-engine/audio_out.c +++ b/src/xine-engine/audio_out.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with self program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -22,7 +22,7 @@ * 20-8-2001 First implementation of Audio sync and Audio driver separation. * (c) 2001 James Courtier-Dutton James@superbug.demon.co.uk */ - + /* * General Programming Guidelines: - * New concept of an "audio_frame". @@ -98,7 +98,7 @@ #define ZERO_BUF_SIZE 5000 /* By adding gap errors (difference between reported and expected - * sound card clock) into metronom's vpts_offset we can use its + * sound card clock) into metronom's vpts_offset we can use its * smoothing algorithms to correct sound card clock drifts. * obs: previously this error was added to xine scr. * @@ -154,13 +154,13 @@ typedef struct { #define EQ_BANDS 10 #define EQ_CHANNELS 8 -#define FP_FRBITS 28 +#define FP_FRBITS 28 #define EQ_REAL(x) ((int)((x) * (1 << FP_FRBITS))) typedef struct { int beta; - int alpha; + int alpha; int gamma; } sIIRCoefficients; @@ -193,15 +193,15 @@ static const sIIRCoefficients iir_cf[] = { /* 16k Hz*/ { EQ_REAL(2.4201241845e-01), EQ_REAL(3.7899379077e-01), EQ_REAL(-8.0847117831e-01) }, }; - + typedef struct { - + xine_audio_port_t ao; /* public part */ /* private stuff */ ao_driver_t *driver; pthread_mutex_t driver_lock; - + uint32_t driver_open:1; uint32_t audio_loop_running:1; uint32_t audio_thread_created:1; @@ -215,6 +215,7 @@ typedef struct { int num_driver_actions; /* number of threads, that wish to call * functions needing driver_lock */ pthread_mutex_t driver_action_lock; /* protects num_driver_actions */ + pthread_cond_t driver_action_cond; /* informs about num_driver_actions-- */ metronom_clock_t *clock; xine_t *xine; @@ -225,7 +226,7 @@ typedef struct { int64_t audio_step; /* pts per 32 768 samples (sample = #bytes/2) */ int32_t frames_per_kpts; /* frames per 1024/90000 sec */ - + int av_sync_method_conf; resample_sync_t resample_sync_info; double resample_sync_factor; /* correct buffer length by this factor @@ -243,11 +244,12 @@ typedef struct { 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 */ /* FIXME: replace all this->clock->speed with this->current_speed. we should make * sure nobody will change speed without going through xine.c:set_speed_internal */ int slow_fast_audio; /* play audio even on slow/fast speeds */ - + int16_t last_sample[RESAMPLE_MAX_CHANNELS]; audio_buffer_t *frame_buf[2]; /* two buffers for "stackable" conversions */ int16_t *zero_space; @@ -273,7 +275,7 @@ typedef struct { int eq_k; sXYData eq_data_history[EQ_BANDS][EQ_CHANNELS]; - + } aos_t; struct audio_fifo_s { @@ -287,13 +289,14 @@ struct audio_fifo_s { int num_buffers; }; +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 *fifo_new (xine_t *xine) { +static audio_fifo_t *XINE_MALLOC fifo_new (xine_t *xine) { audio_fifo_t *fifo; - fifo = (audio_fifo_t *) xine_xmalloc (sizeof (audio_fifo_t)); + fifo = (audio_fifo_t *) calloc(1, sizeof(audio_fifo_t)); if (!fifo) return NULL; @@ -437,7 +440,7 @@ static void fifo_wait_empty (audio_fifo_t *fifo) { } -static void write_pause_burst(aos_t *this, uint32_t num_frames) { +static void write_pause_burst(aos_t *this, uint32_t num_frames) { uint16_t sbuf[4096]; sbuf[0] = 0xf872; @@ -467,7 +470,7 @@ static void ao_fill_gap (aos_t *this, int64_t pts_len) { if ((this->output.mode == AO_CAP_MODE_A52) || (this->output.mode == AO_CAP_MODE_AC5)) { write_pause_burst(this,num_frames); - return; + return; } while (num_frames > 0 && !this->discard_buffers) { @@ -491,7 +494,7 @@ static void ensure_buffer_size (audio_buffer_t *buf, int bytes_per_frame, int frames) { int size = bytes_per_frame * frames; - + if (buf->mem_size < size) { buf->mem = realloc( buf->mem, size ); buf->mem_size = size; @@ -522,7 +525,7 @@ int _x_ao_mode2channels( int mode ) { return 6; } return 0; -} +} int _x_ao_channels2mode( int channels ) { @@ -553,7 +556,7 @@ static void audio_filter_compress (aos_t *this, int16_t *mem, int num_frames) { return; maxs = 0; - + /* measure */ for (i=0; i<num_frames*num_channels; i++) { @@ -569,12 +572,12 @@ static void audio_filter_compress (aos_t *this, int16_t *mem, int num_frames) { this->compression_factor = this->compression_factor * 0.999 + f_max * 0.001; if (this->compression_factor > f_max) this->compression_factor = f_max; - + if (this->compression_factor > this->compression_factor_max) this->compression_factor = this->compression_factor_max; } else f_max = 1.0; - + lprintf ("max=%d f_max=%f compression_factor=%f\n", maxs, f_max, this->compression_factor); /* apply it */ @@ -610,11 +613,11 @@ static void audio_filter_amp (aos_t *this, void *buf, int num_frames) { /* Force limit on amp_factor to prevent clipping */ if (test < INT8_MIN) { this->amp_factor = amp_factor = amp_factor * INT8_MIN / test; - test=INT8_MIN; + test=INT8_MIN; } if (test > INT8_MAX) { this->amp_factor = amp_factor = amp_factor * INT8_MIN / test; - test=INT8_MAX; + test=INT8_MAX; } mem[i] = test; } @@ -627,11 +630,11 @@ static void audio_filter_amp (aos_t *this, void *buf, int num_frames) { /* Force limit on amp_factor to prevent clipping */ if (test < INT16_MIN) { this->amp_factor = amp_factor = amp_factor * INT16_MIN / test; - test=INT16_MIN; + test=INT16_MIN; } if (test > INT16_MAX) { this->amp_factor = amp_factor = amp_factor * INT16_MIN / test; - test=INT16_MAX; + test=INT16_MAX; } mem[i] = test; } @@ -935,7 +938,7 @@ static int resample_rate_adjust(aos_t *this, int64_t gap, audio_buffer_t *buf) { if (gap_diff < RESAMPLE_MAX_GAP_DIFF) { #if LOG_RESAMPLE_SYNC int num_frames; - + /* if we are already resampling to a different output rate, consider * this during calculation */ num_frames = (this->do_resample) ? (buf->num_frames * this->frame_rate_factor) @@ -970,7 +973,7 @@ static int resample_rate_adjust(aos_t *this, int64_t gap, audio_buffer_t *buf) { info->window_duration += buf->vpts - info->last_vpts; info->last_vpts = buf->vpts; info->window++; - } + } return 0; } @@ -978,7 +981,7 @@ static int resample_rate_adjust(aos_t *this, int64_t gap, audio_buffer_t *buf) { static int ao_change_settings(aos_t *this, uint32_t bits, uint32_t rate, int mode); /* Audio output loop: - - * 1) Check for pause. + * 1) Check for pause. * 2) Make sure audio hardware is in RUNNING state. * 3) Get delay * 4) Do drop, 0-fill or output samples. @@ -1006,7 +1009,7 @@ static void *ao_loop (void *this_gen) { /* * get buffer to process for this loop iteration */ - + if (!in_buf) { lprintf ("loop: get buf from fifo\n"); in_buf = fifo_peek (this->out_fifo); @@ -1031,17 +1034,18 @@ static void *ao_loop (void *this_gen) { continue; } pthread_mutex_unlock(&this->flush_audio_driver_lock); - - /* + + /* * wait until user unpauses stream * if we are playing at a different speed (without slow_fast_audio flag) * we must process/free buffers otherwise the entire engine will stop. */ - - if ( this->audio_loop_running && - (this->clock->speed == XINE_SPEED_PAUSE || - (this->clock->speed != XINE_FINE_SPEED_NORMAL && + + pthread_mutex_lock(&this->current_speed_lock); + if ( this->audio_loop_running && + (this->clock->speed == XINE_SPEED_PAUSE || + (this->clock->speed != XINE_FINE_SPEED_NORMAL && !this->slow_fast_audio) ) ) { if (this->clock->speed != XINE_SPEED_PAUSE) { @@ -1054,6 +1058,7 @@ static void *ao_loop (void *this_gen) { _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); in_buf = NULL; + pthread_mutex_unlock(&this->current_speed_lock); continue; } @@ -1064,6 +1069,7 @@ static void *ao_loop (void *this_gen) { } lprintf ("loop:pause: I feel sleepy (%d buffers).\n", this->out_fifo->num_buffers); + pthread_mutex_unlock(&this->current_speed_lock); xine_usec_sleep (10000); lprintf ("loop:pause: I wake up.\n"); continue; @@ -1077,7 +1083,7 @@ static void *ao_loop (void *this_gen) { in_buf->format.rate != this->input.rate || in_buf->format.mode != this->input.mode ) { lprintf("audio format has changed\n"); - if( !in_buf->stream->emergency_brake && + if( !in_buf->stream->emergency_brake && ao_change_settings(this, in_buf->format.bits, in_buf->format.rate, @@ -1101,7 +1107,7 @@ static void *ao_loop (void *this_gen) { delay = 0; pthread_mutex_unlock( &this->driver_lock ); - + if (in_buf && in_buf->num_frames) { xine_list_iterator_t ite; @@ -1121,8 +1127,8 @@ static void *ao_loop (void *this_gen) { } } - cur_time = this->clock->get_current_time (this->clock); - + cur_time = this->clock->get_current_time (this->clock); + /* we update current_extra_info if either there is no video stream that could do that * or if the current_extra_info is getting too much out of date */ if( in_buf && in_buf->stream && (!in_buf->stream->video_decoder_plugin || @@ -1132,9 +1138,9 @@ static void *ao_loop (void *this_gen) { _x_extra_info_merge( in_buf->stream->current_extra_info, in_buf->extra_info ); pthread_mutex_unlock( &in_buf->stream->current_extra_info_lock ); } - + /* - * where, in the timeline is the "end" of the + * where, in the timeline is the "end" of the * hardware audio buffer at the moment? */ @@ -1142,12 +1148,12 @@ static void *ao_loop (void *this_gen) { lprintf ("current delay is %" PRId64 ", current time is %" PRId64 "\n", delay, cur_time); /* External A52 decoder delay correction */ - if ((this->output.mode==AO_CAP_MODE_A52) || (this->output.mode==AO_CAP_MODE_AC5)) + if ((this->output.mode==AO_CAP_MODE_A52) || (this->output.mode==AO_CAP_MODE_AC5)) delay += this->passthrough_offset; if(this->frames_per_kpts) hw_vpts += (delay * 1024) / this->frames_per_kpts; - + /* * calculate gap: */ @@ -1183,13 +1189,13 @@ static void *ao_loop (void *this_gen) { in_buf->vpts, gap); in_buf = NULL; - - /* for small gaps ( tolerance < abs(gap) < AO_MAX_GAP ) + + /* for small gaps ( tolerance < abs(gap) < AO_MAX_GAP ) * feedback them into metronom's vpts_offset (when using * metronom feedback for A/V sync) */ } else if ( abs(gap) < AO_MAX_GAP && abs(gap) > this->gap_tolerance && - cur_time > (last_sync_time + SYNC_TIME_INVERVAL) && + cur_time > (last_sync_time + SYNC_TIME_INVERVAL) && bufs_since_sync >= SYNC_BUF_INTERVAL && !this->resample_sync_method ) { xine_list_iterator_t *ite; @@ -1242,7 +1248,7 @@ static void *ao_loop (void *this_gen) { result = 0; } fifo_remove (this->out_fifo); - + if( result < 0 ) { /* device unplugged. */ xprintf(this->xine, XINE_VERBOSITY_LOG, _("write to sound card failed. Assuming the device was unplugged.\n")); @@ -1266,19 +1272,27 @@ static void *ao_loop (void *this_gen) { pthread_mutex_unlock( &this->driver_lock ); /* closing the driver will result in XINE_MSG_AUDIO_OUT_UNAVAILABLE to be emitted */ } - + lprintf ("loop: next buf from fifo\n"); if (in_buf->stream) _x_refcounter_dec(in_buf->stream->refcounter); fifo_append (this->free_fifo, in_buf); in_buf = NULL; } + pthread_mutex_unlock(&this->current_speed_lock); /* Give other threads a chance to use functions which require this->driver_lock to * be available. This is needed when using NPTL on Linux (and probably PThreads * on Solaris as well). */ - if (this->num_driver_actions > 0) - sched_yield(); + if (this->num_driver_actions > 0) { + /* calling sched_yield() is not sufficient on multicore systems */ + /* sched_yield(); */ + /* instead wait for the other thread to acquire this->driver_lock */ + pthread_mutex_lock(&this->driver_action_lock); + if (this->num_driver_actions > 0) + pthread_cond_wait(&this->driver_action_cond, &this->driver_action_lock); + pthread_mutex_unlock(&this->driver_action_lock); + } } if (in_buf) { @@ -1311,9 +1325,9 @@ int xine_get_next_audio_frame (xine_audio_port_t *this_gen, continue; } stream = xine_list_get_value(this->streams, ite); - + /* FIXME: ugly, use conditions and locks instead? */ - + pthread_mutex_lock (&this->out_fifo->mutex); in_buf = this->out_fifo->first; if (!in_buf) { @@ -1367,10 +1381,10 @@ void xine_free_audio_frame (xine_audio_port_t *this_gen, xine_audio_frame_t *fra } static int ao_update_resample_factor(aos_t *this) { - + if( !this->driver_open ) return 0; - + switch (this->resample_conf) { case 1: /* force off */ this->do_resample = 0; @@ -1395,7 +1409,7 @@ static int ao_update_resample_factor(aos_t *this) { this->frame_rate_factor = ( XINE_FINE_SPEED_NORMAL / (double)this->current_speed ) * ((double)(this->output.rate)) / ((double)(this->input.rate)); this->frames_per_kpts = (this->output.rate * 1024) / 90000; this->audio_step = ((int64_t)90000 * (int64_t)32768) / (int64_t)this->input.rate; - + lprintf ("audio_step %" PRId64 " pts per 32768 frames\n", this->audio_step); return this->output.rate; } @@ -1404,7 +1418,7 @@ static int ao_change_settings(aos_t *this, uint32_t bits, uint32_t rate, int mod int output_sample_rate; if(this->driver_open && !this->grab_only) - this->driver->close(this->driver); + this->driver->close(this->driver); this->driver_open = 0; this->input.mode = mode; @@ -1413,7 +1427,7 @@ static int ao_change_settings(aos_t *this, uint32_t bits, uint32_t rate, int mod if (!this->grab_only) { /* not all drivers/cards support 8 bits */ - if( this->input.bits == 8 && + if( this->input.bits == 8 && !(this->driver->get_capabilities(this->driver) & AO_CAP_8BITS) ) { bits = 16; xprintf (this->xine, XINE_VERBOSITY_LOG, @@ -1433,7 +1447,7 @@ static int ao_change_settings(aos_t *this, uint32_t bits, uint32_t rate, int mod xprintf (this->xine, XINE_VERBOSITY_LOG, _("stereo not supported by driver, converting to mono.\n")); } - + output_sample_rate=(this->driver->open) (this->driver,bits,(this->force_rate ? this->force_rate : rate),mode); } else output_sample_rate = this->input.rate; @@ -1469,6 +1483,8 @@ static inline void dec_num_driver_actions(aos_t *this) { pthread_mutex_lock(&this->driver_action_lock); this->num_driver_actions--; + /* indicate the change to ao_loop() */ + pthread_cond_broadcast(&this->driver_action_cond); pthread_mutex_unlock(&this->driver_action_lock); } @@ -1479,7 +1495,7 @@ static inline void dec_num_driver_actions(aos_t *this) { static int ao_open(xine_audio_port_t *this_gen, xine_stream_t *stream, uint32_t bits, uint32_t rate, int mode) { - + aos_t *this = (aos_t *) this_gen; int channels; @@ -1495,7 +1511,7 @@ static int ao_open(xine_audio_port_t *this_gen, xine_stream_t *stream, pthread_mutex_lock( &this->driver_lock ); ret = ao_change_settings(this, bits, rate, mode); pthread_mutex_unlock( &this->driver_lock ); - + if( !ret ) { stream->emergency_brake = 1; _x_message (stream, XINE_MSG_AUDIO_OUT_UNAVAILABLE, NULL); @@ -1506,7 +1522,7 @@ static int ao_open(xine_audio_port_t *this_gen, xine_stream_t *stream, } } - /* + /* * set metainfo */ if (stream) { @@ -1525,7 +1541,7 @@ static int ao_open(xine_audio_port_t *this_gen, xine_stream_t *stream, pthread_mutex_lock(&this->streams_lock); xine_list_push_back(this->streams, stream); pthread_mutex_unlock(&this->streams_lock); - + return this->output.rate; } @@ -1533,18 +1549,18 @@ static audio_buffer_t *ao_get_buffer (xine_audio_port_t *this_gen) { aos_t *this = (aos_t *) this_gen; audio_buffer_t *buf; - + while (!(buf = fifo_remove_nonblock (this->free_fifo))) if (this->xine->port_ticket->ticket_revoked) this->xine->port_ticket->renew(this->xine->port_ticket, 1); - + _x_extra_info_reset( buf->extra_info ); buf->stream = NULL; - + return buf; } -static void ao_put_buffer (xine_audio_port_t *this_gen, +static void ao_put_buffer (xine_audio_port_t *this_gen, audio_buffer_t *buf, xine_stream_t *stream) { aos_t *this = (aos_t *) this_gen; @@ -1557,11 +1573,11 @@ static void ao_put_buffer (xine_audio_port_t *this_gen, /* handle anonymous streams like NULL for easy checking */ if (stream == XINE_ANON_STREAM) stream = NULL; - + buf->stream = stream; - + pts = buf->vpts; - + if (stream) { buf->format.bits = _x_stream_info_get(stream, XINE_STREAM_INFO_AUDIO_BITS); buf->format.rate = _x_stream_info_get(stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE); @@ -1571,7 +1587,7 @@ static void ao_put_buffer (xine_audio_port_t *this_gen, } buf->extra_info->vpts = buf->vpts; - + lprintf ("ao_put_buffer, pts=%" PRId64 ", vpts=%" PRId64 ", flushmode=%d\n", pts, buf->vpts, this->discard_buffers); @@ -1581,7 +1597,7 @@ static void ao_put_buffer (xine_audio_port_t *this_gen, fifo_append (this->out_fifo, buf); } else fifo_append (this->free_fifo, buf); - + this->last_audio_vpts = buf->vpts; lprintf ("ao_put_buffer done\n"); @@ -1604,26 +1620,30 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) { break; } } - ite = xine_list_front(this->streams); + ite = xine_list_front(this->streams); pthread_mutex_unlock(&this->streams_lock); /* close driver if no streams left */ - if (!ite && !this->grab_only && !stream->gapless_switch) { + if (!ite && !this->grab_only && !stream->keep_ao_driver_open) { xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: no streams left, closing driver\n"); if (this->audio_loop_running) { + /* make sure there are no more buffers on queue */ if (this->clock->speed == XINE_SPEED_PAUSE || (this->clock->speed != XINE_FINE_SPEED_NORMAL && !this->slow_fast_audio)) { - /* discard buffers, otherwise we'll wait forever */ + int discard = ao_get_property(this_gen, AO_PROP_DISCARD_BUFFERS); + /* discard buffers while waiting, otherwise we'll wait forever */ ao_set_property(this_gen, AO_PROP_DISCARD_BUFFERS, 1); + fifo_wait_empty(this->out_fifo); + ao_set_property(this_gen, AO_PROP_DISCARD_BUFFERS, discard); } - /* make sure there are no more buffers on queue */ - fifo_wait_empty(this->out_fifo); + else + fifo_wait_empty(this->out_fifo); } pthread_mutex_lock( &this->driver_lock ); if(this->driver_open) - this->driver->close(this->driver); + this->driver->close(this->driver); this->driver_open = 0; pthread_mutex_unlock( &this->driver_lock ); } @@ -1633,7 +1653,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { aos_t *this = (aos_t *) this_gen; int vol; int prop = 0; - + audio_buffer_t *buf, *next; if (this->audio_loop_running) { @@ -1649,15 +1669,15 @@ static void ao_exit(xine_audio_port_t *this_gen) { pthread_join (this->audio_thread, &p); this->audio_thread_created = 0; } - + if (!this->grab_only) { pthread_mutex_lock( &this->driver_lock ); - + if((this->driver->get_capabilities(this->driver)) & AO_CAP_MIXER_VOL) prop = AO_PROP_MIXER_VOL; else if((this->driver->get_capabilities(this->driver)) & AO_CAP_PCM_VOL) prop = AO_PROP_PCM_VOL; - + vol = this->driver->get_property(this->driver, prop); this->xine->config->update_num(this->xine->config, "audio.volume.mixer_volume", vol); if(this->driver_open) @@ -1667,6 +1687,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { } pthread_mutex_destroy(&this->driver_lock); + pthread_cond_destroy(&this->driver_action_cond); pthread_mutex_destroy(&this->driver_action_lock); pthread_mutex_destroy(&this->streams_lock); xine_list_delete(this->streams); @@ -1678,7 +1699,8 @@ static void ao_exit(xine_audio_port_t *this_gen) { free (this->frame_buf[1]->extra_info); free (this->frame_buf[1]); free (this->zero_space); - + + pthread_mutex_destroy(&this->current_speed_lock); pthread_mutex_destroy(&this->flush_audio_driver_lock); pthread_cond_destroy(&this->flush_audio_driver_reached); @@ -1711,11 +1733,11 @@ static void ao_exit(xine_audio_port_t *this_gen) { pthread_mutex_destroy(&this->free_fifo->mutex); pthread_cond_destroy(&this->free_fifo->empty); pthread_cond_destroy(&this->free_fifo->not_empty); - + pthread_mutex_destroy(&this->out_fifo->mutex); pthread_cond_destroy(&this->out_fifo->empty); pthread_cond_destroy(&this->out_fifo->not_empty); - + free (this->free_fifo); free (this->out_fifo); free (this); @@ -1724,7 +1746,7 @@ static void ao_exit(xine_audio_port_t *this_gen) { static uint32_t ao_get_capabilities (xine_audio_port_t *this_gen) { aos_t *this = (aos_t *) this_gen; uint32_t result; - + if (this->grab_only) { return AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO ; @@ -1736,7 +1758,7 @@ static uint32_t ao_get_capabilities (xine_audio_port_t *this_gen) { inc_num_driver_actions(this); pthread_mutex_lock( &this->driver_lock ); dec_num_driver_actions(this); - result=this->driver->get_capabilities(this->driver); + result=this->driver->get_capabilities(this->driver); pthread_mutex_unlock( &this->driver_lock ); } return result; @@ -1750,25 +1772,25 @@ static int ao_get_property (xine_audio_port_t *this_gen, int property) { case AO_PROP_COMPRESSOR: ret = this->compression_factor_max*100; break; - + case AO_PROP_BUFS_IN_FIFO: ret = this->audio_loop_running ? this->out_fifo->num_buffers : -1; break; - + case AO_PROP_NUM_STREAMS: pthread_mutex_lock(&this->streams_lock); ret = xine_list_size(this->streams); pthread_mutex_unlock(&this->streams_lock); break; - + case AO_PROP_AMP: ret = this->amp_factor*100; break; - + case AO_PROP_AMP_MUTE: ret = this->amp_mute; break; - + case AO_PROP_EQ_30HZ: case AO_PROP_EQ_60HZ: case AO_PROP_EQ_125HZ: @@ -1778,14 +1800,14 @@ static int ao_get_property (xine_audio_port_t *this_gen, int property) { case AO_PROP_EQ_2000HZ: case AO_PROP_EQ_4000HZ: case AO_PROP_EQ_8000HZ: - case AO_PROP_EQ_16000HZ: + case AO_PROP_EQ_16000HZ: ret = (100.0 * this->eq_gain[property - AO_PROP_EQ_30HZ]) / (1 << FP_FRBITS) ; break; case AO_PROP_DISCARD_BUFFERS: ret = this->discard_buffers; break; - + case AO_PROP_CLOCK_SPEED: ret = this->current_speed; break; @@ -1813,7 +1835,7 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value ret = this->compression_factor_max*100; break; - + case AO_PROP_AMP: this->amp_factor = (double) value / 100.0; @@ -1838,13 +1860,13 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value case AO_PROP_EQ_2000HZ: case AO_PROP_EQ_4000HZ: case AO_PROP_EQ_8000HZ: - case AO_PROP_EQ_16000HZ: + case AO_PROP_EQ_16000HZ: { int min_gain, max_gain, i; this->eq_gain[property - AO_PROP_EQ_30HZ] = EQ_REAL(((float)value / 100.0)) ; - + /* calc pregain, find out if any gain != 0.0 - enable eq if that is the case */ min_gain = EQ_REAL(0.0); max_gain = EQ_REAL(0.0); @@ -1854,7 +1876,7 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value if (this->eq_gain[i] > max_gain) max_gain = this->eq_gain[i]; } - + lprintf ("eq min_gain=%d, max_gain=%d\n", min_gain, max_gain); this->do_equ = ((min_gain != EQ_REAL(0.0)) || (max_gain != EQ_REAL(0.0))); @@ -1862,22 +1884,22 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value ret = value; } break; - + case AO_PROP_DISCARD_BUFFERS: /* recursive discard buffers setting */ if(value) this->discard_buffers++; else this->discard_buffers--; - + ret = this->discard_buffers; - + /* discard buffers here because we have no output thread */ if (this->grab_only && this->discard_buffers) { audio_buffer_t *buf; - + pthread_mutex_lock(&this->out_fifo->mutex); - + while ((buf = this->out_fifo->first)) { lprintf ("flushing out frame\n"); buf = fifo_remove_int (this->out_fifo, 1); @@ -1905,13 +1927,20 @@ static int ao_set_property (xine_audio_port_t *this_gen, int property, int value if (value != XINE_FINE_SPEED_NORMAL && value != XINE_SPEED_PAUSE && !this->slow_fast_audio ) this->ao.control(&this->ao, AO_CTRL_FLUSH_BUFFERS, NULL); - this->ao.control(&this->ao, - (value == XINE_SPEED_PAUSE) ? AO_CTRL_PLAY_PAUSE : AO_CTRL_PLAY_RESUME, NULL); + if( value == XINE_SPEED_PAUSE ) { + /* current_speed_lock is here to make sure the ao_loop will pause in a safe place. + * that is, we cannot pause writing to device, filling gaps etc. */ + pthread_mutex_lock(&this->current_speed_lock); + this->ao.control(&this->ao, AO_CTRL_PLAY_PAUSE, NULL); + pthread_mutex_unlock(&this->current_speed_lock); + } else { + this->ao.control(&this->ao, AO_CTRL_PLAY_RESUME, NULL); + } this->current_speed = value; if( this->slow_fast_audio ) ao_update_resample_factor(this); break; - + default: if (!this->grab_only) { /* Let the sound driver lock it's own mixer */ @@ -1957,7 +1986,7 @@ static void ao_flush (xine_audio_port_t *this_gen) { pthread_mutex_lock(&this->flush_audio_driver_lock); this->discard_buffers++; this->flush_audio_driver++; - + /* do not try this in paused mode */ while( this->flush_audio_driver && this->clock->speed != XINE_SPEED_PAUSE) { struct timeval tv; @@ -1996,7 +2025,7 @@ static int ao_status (xine_audio_port_t *this_gen, xine_stream_t *stream, xine_stream_t *cur; int ret = 0; xine_list_iterator_t ite; - + pthread_mutex_lock(&this->streams_lock); for (ite = xine_list_front(this->streams); ite; ite = xine_list_next(this->streams, ite)) { @@ -2010,8 +2039,8 @@ static int ao_status (xine_audio_port_t *this_gen, xine_stream_t *stream, } } pthread_mutex_unlock(&this->streams_lock); - - return ret; + + return ret; } static void ao_update_av_sync_method(void *this_gen, xine_cfg_entry_t *entry) { @@ -2020,7 +2049,7 @@ static void ao_update_av_sync_method(void *this_gen, xine_cfg_entry_t *entry) { lprintf ("av_sync_method = %d\n", entry->num_value); this->av_sync_method_conf = entry->num_value; - + switch (this->av_sync_method_conf) { case 0: this->resample_sync_method = 0; @@ -2037,7 +2066,7 @@ static void ao_update_av_sync_method(void *this_gen, xine_cfg_entry_t *entry) { xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only) { - + config_values_t *config = xine->config; aos_t *this; int i, err; @@ -2046,13 +2075,14 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, static const char* resample_modes[] = {"auto", "off", "on", NULL}; static const char* av_sync_methods[] = {"metronom feedback", "resample", NULL}; - this = xine_xmalloc (sizeof (aos_t)) ; + this = calloc(1, sizeof(aos_t)) ; this->driver = driver; this->xine = xine; this->clock = xine->clock; + this->current_speed = xine->clock->speed; this->streams = xine_list_new(); - + /* warning: driver_lock is a recursive mutex. it must NOT be * used with neither pthread_cond_wait() or pthread_cond_timedwait() */ @@ -2062,6 +2092,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, 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 ); this->ao.open = ao_open; this->ao.get_buffer = ao_get_buffer; @@ -2075,13 +2106,14 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, this->ao.flush = ao_flush; this->ao.status = ao_status; - this->num_driver_actions = 0; + this->num_driver_actions = 0; this->audio_loop_running = 0; this->grab_only = grab_only; this->flush_audio_driver = 0; this->discard_buffers = 0; - this->zero_space = xine_xmalloc (ZERO_BUF_SIZE * 4 * 6); /* MAX as 32bit, 6 channels. */ - + 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 ); @@ -2116,7 +2148,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, "an external decoder in digital form."), 20, ao_update_av_sync_method, this); config->update_num(config,"audio.synchronization.av_sync_method",this->av_sync_method_conf); - + this->resample_conf = config->register_enum (config, "audio.synchronization.resample_mode", 0, resample_modes, _("enable resampling"), @@ -2143,7 +2175,7 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, "a fixed offset here to compensate.\nThe unit of " "the value is one PTS tick, which is the 90000th " "part of a second."), 10, NULL, NULL); - + this->slow_fast_audio = config->register_bool (config, "audio.synchronization.slow_fast_audio", 0, @@ -2191,23 +2223,23 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, audio_buffer_t *buf; - buf = (audio_buffer_t *) xine_xmalloc (sizeof (audio_buffer_t)); - buf->mem = xine_xmalloc (AUDIO_BUF_SIZE); + 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); } 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 *) xine_xmalloc (sizeof (audio_buffer_t)); - buf->mem = xine_xmalloc (4*AUDIO_BUF_SIZE); + 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)); @@ -2219,13 +2251,13 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, */ if(this->driver){ int vol; - - vol = config->register_range (config, "audio.volume.mixer_volume", - 50, 0, 100, _("startup audio volume"), + + vol = config->register_range (config, "audio.volume.mixer_volume", + 50, 0, 100, _("startup audio volume"), _("The overall audio volume set at xine startup."), 10, NULL, NULL); - + if(config->register_bool (config, "audio.volume.remember_volume", 0, - _("restore volume level at startup"), + _("restore volume level at startup"), _("If disabled, xine will not modify any mixer settings at startup."), 10, NULL, NULL)) { int prop = 0; @@ -2234,34 +2266,34 @@ xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, prop = AO_PROP_MIXER_VOL; else if((ao_get_capabilities(&this->ao)) & AO_CAP_PCM_VOL) prop = AO_PROP_PCM_VOL; - + ao_set_property(&this->ao, prop, vol); } - } - + } + if (!this->grab_only) { /* * start output thread */ - this->audio_loop_running = 1; - + this->audio_loop_running = 1; + pthread_attr_init(&pth_attrs); pthread_attr_setscope(&pth_attrs, PTHREAD_SCOPE_SYSTEM); this->audio_thread_created = 1; if ((err = pthread_create (&this->audio_thread, &pth_attrs, ao_loop, this)) != 0) { - - xprintf (this->xine, XINE_VERBOSITY_DEBUG, + + xprintf (this->xine, XINE_VERBOSITY_NONE, "audio_out: can't create thread (%s)\n", strerror(err)); - xprintf (this->xine, XINE_VERBOSITY_LOG, + xprintf (this->xine, XINE_VERBOSITY_LOG, _("audio_out: sorry, this should not happen. please restart xine.\n")); _x_abort(); - + } else xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_out: thread created\n"); - + pthread_attr_destroy(&pth_attrs); } diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h index c4581ec24..832c65a9e 100644 --- a/src/xine-engine/audio_out.h +++ b/src/xine-engine/audio_out.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -48,9 +48,9 @@ typedef struct ao_driver_s ao_driver_t; struct ao_driver_s { - /* + /* * - * find out what output modes + capatilities are supported by + * find out what output modes + capatilities are supported by * this plugin (constants for the bit vector to return see above) * * See AO_CAP_* bellow. @@ -58,7 +58,7 @@ struct ao_driver_s { uint32_t (*get_capabilities) (ao_driver_t *); /* - * open the driver and make it ready to receive audio data + * open the driver and make it ready to receive audio data * buffers may be flushed(!) * * return value: 0 : failure, >0 : output sample rate @@ -74,21 +74,21 @@ struct ao_driver_s { */ int (*bytes_per_frame)(ao_driver_t *self_gen); - /* return the delay is frames measured by + /* return the delay is frames measured by * looking at pending samples in the audio output device */ int (*delay)(ao_driver_t *self_gen); - /* + /* * return gap tolerance (in pts) needed for this driver */ int (*get_gap_tolerance) (ao_driver_t *self_gen); /* * write audio data to audio output device - * return value: + * return value: * >0 => audio samples were processed ok - * 0 => audio samples were not yet processed, + * 0 => audio samples were not yet processed, * call write_audio_data with the _same_ samples again */ int (*write)(ao_driver_t *, @@ -152,9 +152,9 @@ struct audio_buffer_s { int64_t vpts; uint32_t frame_header_count; uint32_t first_access_unit; - + /* extra info coming from input or demuxers */ - extra_info_t *extra_info; + extra_info_t *extra_info; xine_stream_t *stream; /* stream that send that buffer */ @@ -179,7 +179,7 @@ struct xine_audio_port_s { int (*get_property) (xine_audio_port_t *, int property); int (*set_property) (xine_audio_port_t *, int property, int value); - /* open audio driver for audio output + /* open audio driver for audio output * return value: 0:failure, >0:output sample rate */ /* when you are not a full-blown stream, but still need to open the port @@ -188,7 +188,7 @@ struct xine_audio_port_s { uint32_t bits, uint32_t rate, int mode); /* - * get a piece of memory for audio data + * get a piece of memory for audio data */ audio_buffer_t * (*get_buffer) (xine_audio_port_t *); @@ -218,7 +218,7 @@ struct xine_audio_port_s { * Flush audio_out fifo. */ void (*flush) (xine_audio_port_t *); - + /* * Check if port is opened for this stream and get parameters. * The stream can be anonymous. @@ -236,14 +236,14 @@ struct audio_driver_class_s { * open a new instance of this plugin class */ ao_driver_t* (*open_plugin) (audio_driver_class_t *, const void *data); - + /* * return short, human readable identifier for this plugin class */ char* (*get_identifier) (audio_driver_class_t *); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ char* (*get_description) (audio_driver_class_t *); @@ -255,11 +255,11 @@ struct audio_driver_class_s { void (*dispose) (audio_driver_class_t *); }; -/* +/* * this initiates the audio_out sync routines * found in ./src/xine-engine/audio_out.c */ -xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only) XINE_PROTECTED; +xine_audio_port_t *_x_ao_new_port (xine_t *xine, ao_driver_t *driver, int grab_only) XINE_MALLOC XINE_PROTECTED; /* * audio output modes + capabilities @@ -331,7 +331,7 @@ int _x_ao_channels2mode( int channels ) XINE_PROTECTED; /* audio device control ops */ #define AO_CTRL_PLAY_PAUSE 0 #define AO_CTRL_PLAY_RESUME 1 -#define AO_CTRL_FLUSH_BUFFERS 2 +#define AO_CTRL_FLUSH_BUFFERS 2 /* above that value audio frames are discarded */ #define AO_MAX_GAP 15000 diff --git a/src/xine-engine/broadcaster.c b/src/xine-engine/broadcaster.c index 1d2f01366..a554337a3 100644 --- a/src/xine-engine/broadcaster.c +++ b/src/xine-engine/broadcaster.c @@ -9,7 +9,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -27,11 +27,15 @@ * - master will wait for connections on specified port, accepting new clients. * - several xine clients may connect to the server as "slaves", using mrl: * slave://master_address:port - * - streams played on master will appear on every slave. + * - streams played on master will appear on every slave. * if master is not meant to use video/audio devices it may be started with * 'xine -V none -A none' */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -69,7 +73,7 @@ struct broadcaster_s { int port; /* server port */ int msock; /* master network socket */ xine_list_t *connections; /* active connections */ - + pthread_t manager_thread; pthread_mutex_t lock; @@ -83,21 +87,21 @@ static int sock_check_opened(int socket) { fd_set readfds, writefds, exceptfds; int retval; struct timeval timeout; - + for(;;) { - FD_ZERO(&readfds); - FD_ZERO(&writefds); + FD_ZERO(&readfds); + FD_ZERO(&writefds); FD_ZERO(&exceptfds); FD_SET(socket, &exceptfds); - - timeout.tv_sec = 0; + + timeout.tv_sec = 0; timeout.tv_usec = 0; - + retval = select(socket + 1, &readfds, &writefds, &exceptfds, &timeout); - + if(retval == -1 && (errno != EAGAIN && errno != EINTR)) return 0; - + if (retval != -1) return 1; } @@ -111,21 +115,21 @@ static int sock_check_opened(int socket) { static int sock_data_write(xine_t *xine, int socket, char *buf, int len) { ssize_t size; int wlen = 0; - + if((socket < 0) || (buf == NULL)) return -1; - + if(!sock_check_opened(socket)) return -1; - + while(len) { size = write(socket, buf, len); - + if(size <= 0) { xprintf(xine, XINE_VERBOSITY_DEBUG, "broadcaster: error writing to socket %d\n",socket); return -1; } - + len -= size; wlen += size; buf += size; @@ -138,20 +142,20 @@ static int XINE_FORMAT_PRINTF(3, 4) sock_string_write(xine_t *xine, int socket, char *msg, ...) { char buf[_BUFSIZ]; va_list args; - + va_start(args, msg); vsnprintf(buf, _BUFSIZ - 1, msg, args); va_end(args); - + /* Each line sent is '\n' terminated */ if((buf[strlen(buf)] == '\0') && (buf[strlen(buf) - 1] != '\n')) strcat(buf, "\n"); - + return sock_data_write(xine, socket, buf, strlen(buf)); } /* - * this is the most important broadcaster function. + * this is the most important broadcaster function. * it sends data to every connected client (slaves). */ static void broadcaster_data_write(broadcaster_t *this, char *buf, int len) { @@ -161,9 +165,9 @@ static void broadcaster_data_write(broadcaster_t *this, char *buf, int len) { while (ite) { int *psock = xine_list_get_value(this->connections, ite); - + ite = xine_list_next(this->connections, ite); - + /* in case of failure remove from list */ if( sock_data_write(this->stream->xine, *psock, buf, len) < 0 ) { @@ -180,15 +184,15 @@ static void XINE_FORMAT_PRINTF(2, 3) broadcaster_string_write(broadcaster_t *this, char *msg, ...) { char buf[_BUFSIZ]; va_list args; - + va_start(args, msg); vsnprintf(buf, _BUFSIZ - 1, msg, args); va_end(args); - + /* Each line sent is '\n' terminated */ if((buf[strlen(buf)] == '\0') && (buf[strlen(buf) - 1] != '\n')) strcat(buf, "\n"); - + broadcaster_data_write(this, buf, strlen(buf)); } @@ -205,40 +209,40 @@ static void *manager_loop (void *this_gen) { socklen_t alen; /* from-address length */ fd_set rfds; /* read file descriptor set */ fd_set efds; /* exception descriptor set */ - + while( this->running ) { FD_ZERO(&rfds); FD_SET(this->msock, &rfds); FD_ZERO(&efds); FD_SET(this->msock, &efds); - + if (select(this->msock+1, &rfds, (fd_set *)0, &efds, (struct timeval *)0) > 0) { - + pthread_mutex_lock( &this->lock ); - + if (FD_ISSET(this->msock, &rfds)) { int ssock; alen = sizeof(fsin.in); - + ssock = accept(this->msock, &(fsin.sa), &alen); if (ssock >= 0) { /* identification string, helps demuxer probing */ if( sock_string_write(this->stream->xine, ssock,"master xine v1") > 0 ) { int *psock = malloc(sizeof(int)); *psock = ssock; - - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "broadcaster: new connection socket %d\n", *psock); xine_list_push_back(this->connections, psock); } } } - + pthread_mutex_unlock( &this->lock ); } } - + return NULL; } @@ -249,7 +253,7 @@ static void *manager_loop (void *this_gen) { */ static void send_buf (broadcaster_t *this, char *from, buf_element_t *buf) { int i; - + /* ignore END buffers since they would stop the slavery */ if( buf->type == BUF_CONTROL_END ) return; @@ -268,7 +272,7 @@ static void send_buf (broadcaster_t *this, char *from, buf_element_t *buf) { broadcaster_data_write(this, buf->decoder_info_ptr[i], buf->decoder_info[i]); } } - + broadcaster_string_write(this, "buffer fifo=%s size=%d type=%u pts=%"PRId64" disc=%"PRId64" flags=%u", from, buf->size, buf->type, buf->pts, buf->disc_off, buf->decoder_flags ); @@ -302,7 +306,7 @@ broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) struct sockaddr sa; } servAddr; int msock, err; - + msock = socket(PF_INET, SOCK_STREAM, 0); if( msock < 0 ) { @@ -320,31 +324,31 @@ broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) } listen(msock,QLEN); - + signal( SIGPIPE, SIG_IGN ); - this = xine_xmalloc(sizeof(broadcaster_t)); + this = calloc(1, sizeof(broadcaster_t)); this->port = port; this->stream = stream; this->msock = msock; this->connections = xine_list_new(); - + pthread_mutex_init (&this->lock, NULL); - + stream->video_fifo->register_put_cb(stream->video_fifo, video_put_cb, this); if(stream->audio_fifo) stream->audio_fifo->register_put_cb(stream->audio_fifo, audio_put_cb, this); - + this->running = 1; if ((err = pthread_create (&this->manager_thread, NULL, manager_loop, (void *)this)) != 0) { - xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (stream->xine, XINE_VERBOSITY_NONE, "broadcaster: can't create new thread (%s)\n", strerror(err)); _x_abort(); } - - return this; + + return this; } void _x_close_broadcaster(broadcaster_t *this) @@ -353,15 +357,15 @@ void _x_close_broadcaster(broadcaster_t *this) pthread_cancel(this->manager_thread); pthread_join(this->manager_thread,NULL); close(this->msock); - + if (this->stream->video_fifo) this->stream->video_fifo->unregister_put_cb(this->stream->video_fifo, video_put_cb); if(this->stream->audio_fifo) this->stream->audio_fifo->unregister_put_cb(this->stream->audio_fifo, audio_put_cb); - + xine_list_iterator_t ite; - + while ( (ite = xine_list_front(this->connections)) ) { int *psock = xine_list_get_value(this->connections, ite); xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "broadcaster: closing socket %d\n", *psock); @@ -378,5 +382,5 @@ void _x_close_broadcaster(broadcaster_t *this) int _x_get_broadcaster_port(broadcaster_t *this) { - return this->port; + return this->port; } diff --git a/src/xine-engine/broadcaster.h b/src/xine-engine/broadcaster.h index 093fb4af0..0cd416cac 100644 --- a/src/xine-engine/broadcaster.h +++ b/src/xine-engine/broadcaster.h @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -27,13 +27,9 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - typedef struct broadcaster_s broadcaster_t; -broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_PROTECTED; +broadcaster_t *_x_init_broadcaster(xine_stream_t *stream, int port) XINE_MALLOC XINE_PROTECTED; void _x_close_broadcaster(broadcaster_t *this) XINE_PROTECTED; int _x_get_broadcaster_port(broadcaster_t *this) XINE_PROTECTED; diff --git a/src/xine-engine/bswap.h b/src/xine-engine/bswap.h index 635c6ae3a..f58648728 100644 --- a/src/xine-engine/bswap.h +++ b/src/xine-engine/bswap.h @@ -23,7 +23,7 @@ #include "config.h" -#define always_inline inline +#define always_inline inline #include "ffmpeg_bswap.h" @@ -98,7 +98,7 @@ ( (uint32_t)(unsigned char)(ch1) << 8 ) | \ ( (uint32_t)(unsigned char)(ch2) << 16 ) | \ ( (uint32_t)(unsigned char)(ch3) << 24 ) ) - + #ifdef WORDS_BIGENDIAN #define ME_FOURCC BE_FOURCC #else diff --git a/src/xine-engine/buffer.c b/src/xine-engine/buffer.c index 93ad75ba0..77c0abc9d 100644 --- a/src/xine-engine/buffer.c +++ b/src/xine-engine/buffer.c @@ -1,13 +1,13 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -64,7 +64,7 @@ static void buffer_pool_free (buf_element_t *element) { fprintf(stderr, _("xine-lib: buffer.c: There has been a fatal error: TOO MANY FREE's\n")); _x_abort(); } - + pthread_cond_signal (&this->buffer_pool_cond_not_empty); pthread_mutex_unlock (&this->buffer_pool_mutex); @@ -104,7 +104,7 @@ static buf_element_t *buffer_pool_alloc (fifo_buffer_t *this) { memset(buf->decoder_info, 0, sizeof(buf->decoder_info)); memset(buf->decoder_info_ptr, 0, sizeof(buf->decoder_info_ptr)); _x_extra_info_reset( buf->extra_info ); - + return buf; } @@ -151,7 +151,7 @@ static buf_element_t *buffer_pool_try_alloc (fifo_buffer_t *this) { */ static void fifo_buffer_put (fifo_buffer_t *fifo, buf_element_t *element) { int i; - + pthread_mutex_lock (&fifo->mutex); for(i = 0; fifo->put_cb[i]; i++) @@ -177,7 +177,7 @@ static void fifo_buffer_put (fifo_buffer_t *fifo, buf_element_t *element) { */ static void dummy_fifo_buffer_put (fifo_buffer_t *fifo, buf_element_t *element) { int i; - + pthread_mutex_lock (&fifo->mutex); for(i = 0; fifo->put_cb[i]; i++) @@ -444,7 +444,7 @@ static void fifo_unregister_alloc_cb (fifo_buffer_t *this, this->alloc_cb_data[j] = this->alloc_cb_data[j+1]; } } - } + } pthread_mutex_unlock(&this->mutex); } @@ -465,7 +465,7 @@ static void fifo_unregister_put_cb (fifo_buffer_t *this, this->put_cb_data[j] = this->put_cb_data[j+1]; } } - } + } pthread_mutex_unlock(&this->mutex); } @@ -486,7 +486,7 @@ static void fifo_unregister_get_cb (fifo_buffer_t *this, this->get_cb_data[j] = this->get_cb_data[j+1]; } } - } + } pthread_mutex_unlock(&this->mutex); } @@ -500,7 +500,7 @@ fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) { int alignment = 2048; unsigned char *multi_buffer = NULL; - this = xine_xmalloc (sizeof (fifo_buffer_t)); + this = calloc(1, sizeof(fifo_buffer_t)); this->first = NULL; this->last = NULL; @@ -551,7 +551,7 @@ fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) { for (i = 0; i<num_buffers; i++) { buf_element_t *buf; - buf = xine_xmalloc (sizeof (buf_element_t)); + buf = calloc(1, sizeof(buf_element_t)); buf->mem = multi_buffer; multi_buffer += buf_size; diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index 35ab1e620..42302b30f 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -1,8 +1,8 @@ /* - * Copyright (C) 2000-2004 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -35,10 +35,7 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - +#include <string.h> #include <stdio.h> #include <pthread.h> #include <sys/types.h> @@ -111,7 +108,7 @@ extern "C" { #define BUF_VIDEO_WMV8 0x02140000 #define BUF_VIDEO_MSVC 0x02150000 #define BUF_VIDEO_DV 0x02160000 -#define BUF_VIDEO_REAL 0x02170000 +#define BUF_VIDEO_REAL 0x02170000 #define BUF_VIDEO_VP31 0x02180000 #define BUF_VIDEO_H263 0x02190000 #define BUF_VIDEO_3IVX 0x021A0000 @@ -190,6 +187,8 @@ extern "C" { #define BUF_VIDEO_VP6F 0x02630000 #define BUF_VIDEO_THEORA_RAW 0x02640000 #define BUF_VIDEO_VC1 0x02650000 +#define BUF_VIDEO_VMNC 0x02660000 +#define BUF_VIDEO_SNOW 0x02670000 /* audio buffer types: (please keep in sync with buffer_types.c) */ @@ -210,7 +209,7 @@ extern "C" { #define BUF_AUDIO_VOXWARE 0x030c0000 #define BUF_AUDIO_ACELPNET 0x030d0000 #define BUF_AUDIO_AAC 0x030e0000 -#define BUF_AUDIO_DNET 0x030f0000 +#define BUF_AUDIO_DNET 0x030f0000 #define BUF_AUDIO_VIVOG723 0x03100000 #define BUF_AUDIO_DK3ADPCM 0x03110000 #define BUF_AUDIO_DK4ADPCM 0x03120000 @@ -228,10 +227,10 @@ extern "C" { #define BUF_AUDIO_GSM610 0x031E0000 #define BUF_AUDIO_EA_ADPCM 0x031F0000 #define BUF_AUDIO_WMAV2 0x03200000 -#define BUF_AUDIO_COOK 0x03210000 -#define BUF_AUDIO_ATRK 0x03220000 -#define BUF_AUDIO_14_4 0x03230000 -#define BUF_AUDIO_28_8 0x03240000 +#define BUF_AUDIO_COOK 0x03210000 +#define BUF_AUDIO_ATRK 0x03220000 +#define BUF_AUDIO_14_4 0x03230000 +#define BUF_AUDIO_28_8 0x03240000 #define BUF_AUDIO_SIPRO 0x03250000 #define BUF_AUDIO_WMAV3 0x03260000 #define BUF_AUDIO_INTERPLAY 0x03270000 @@ -257,6 +256,9 @@ extern "C" { #define BUF_AUDIO_SMACKER 0x033B0000 #define BUF_AUDIO_FLVADPCM 0x033C0000 #define BUF_AUDIO_WAVPACK 0x033D0000 +#define BUF_AUDIO_MP3ADU 0x033E0000 +#define BUF_AUDIO_AMR_NB 0x033F0000 +#define BUF_AUDIO_AMR_WB 0x03400000 /* spu buffer types: */ @@ -269,6 +271,7 @@ extern "C" { #define BUF_SPU_CVD 0x04050000 #define BUF_SPU_OGM 0x04060000 #define BUF_SPU_CMML 0x04070000 +#define BUF_SPU_HDMV 0x04080000 /* demuxer block types: */ @@ -281,7 +284,7 @@ typedef struct extra_info_s extra_info_t; * to output frames (past decoder). new data must be added after the existing * fields for backward compatibility. */ - + struct extra_info_s { int input_normpos; /* remember where this buf came from in @@ -290,10 +293,10 @@ struct extra_info_s { int input_time; /* time offset in miliseconds from * beginning of stream */ uint32_t frame_number; /* number of current frame if known */ - + int seek_count; /* internal engine use */ - int64_t vpts; /* set on output layers only */ - + int64_t vpts; /* set on output layers only */ + int invalid; /* do not use this extra info to update anything */ int total_time; /* duration in miliseconds of the stream */ }; @@ -319,7 +322,7 @@ struct buf_element_s { uint32_t decoder_flags; /* stuff like keyframe, is_header ... see below */ /* additional decoder flags and other dec-spec. stuff */ - uint32_t decoder_info[BUF_NUM_DEC_INFO]; + uint32_t decoder_info[BUF_NUM_DEC_INFO]; /* pointers to dec-spec. stuff */ void *decoder_info_ptr[BUF_NUM_DEC_INFO]; @@ -366,12 +369,22 @@ struct buf_element_s { * xine_waveformatex is actually optional since the most important * information for audio init is available from decoder_info[]. * note: BUF_FLAG_HEADER must also be set. */ -#define BUF_FLAG_STDHEADER 0x0400 +#define BUF_FLAG_STDHEADER 0x0400 /* decoder_info[1] carries numerator for display aspect ratio * decoder_info[2] carries denominator for display aspect ratio */ #define BUF_FLAG_ASPECT 0x0800 +/* represent the state of gapless_switch at the time buf was enqueued */ +#define BUF_FLAG_GAPLESS_SW 0x1000 + +/* Amount of audio padding added by encoder (mp3, aac). These empty + * audio frames are causing a gap when switching between mp3 files. + * decoder_info[1] carries amount of audio frames padded at the + * beginning of the buffer + * decoder_info[2] carries amount of audio frames padded at the end of + * the buffer */ +#define BUF_FLAG_AUDIO_PADDING 0x2000 /* Special buffer types: * Sometimes there is a need to relay special information from a demuxer @@ -443,7 +456,7 @@ struct buf_element_s { * four length bytes at the beginning * decoder_info_ptr[2] = pointer to ImageDescription atom, starting with * the codec fourcc - * Some Quicktime decoders need information contained within the + * Some Quicktime decoders need information contained within the * ImageDescription atom inside a Quicktime file's stsd atom. This * special buffer carries the ImageDescription atom from the QT demuxer * to an A/V decoder. @@ -476,7 +489,7 @@ struct buf_element_s { * In a BUF_SPECIAL_SPU_DVD_SUBTYPE: * decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE * decoder_info[2] = subtype - * decoder_info[3] = + * decoder_info[3] = * This buffer is pass SPU subtypes from DVDs */ #define BUF_SPECIAL_SPU_DVD_SUBTYPE 8 @@ -516,7 +529,7 @@ struct spu_dvb_descriptor_s long comp_page_id; long aux_page_id; } ; - + typedef struct palette_entry_s palette_entry_t; struct palette_entry_s { @@ -605,8 +618,8 @@ struct fifo_buffer_s * allocate num_buffers of buf_size bytes each */ -fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_PROTECTED; -fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_PROTECTED; +fifo_buffer_t *_x_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_MALLOC XINE_PROTECTED; +fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XINE_MALLOC XINE_PROTECTED; /* return BUF_VIDEO_xxx given the fourcc @@ -616,16 +629,16 @@ fifo_buffer_t *_x_dummy_fifo_buffer_new (int num_buffers, uint32_t buf_size) XIN uint32_t _x_fourcc_to_buf_video( uint32_t fourcc_int ) XINE_PROTECTED; /* return codec name given BUF_VIDEO_xxx */ -char * _x_buf_video_name( uint32_t buf_type ) XINE_PROTECTED; +const char * _x_buf_video_name( uint32_t buf_type ) XINE_PROTECTED; /* return BUF_AUDIO_xxx given the formattag */ uint32_t _x_formattag_to_buf_audio( uint32_t formattag ) XINE_PROTECTED; /* return codec name given BUF_AUDIO_xxx */ -char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; +const char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; -#ifndef ATTRIBUTE_PACKED +#ifndef SUPPORT_ATTRIBUTE_PACKED /* no attribute packed? let's try with pragma pack as a last resort */ #pragma pack(2) #endif @@ -634,7 +647,7 @@ char * _x_buf_audio_name( uint32_t buf_type ) XINE_PROTECTED; * - will always use machine endian format, so demuxers reading * stuff from win32 formats must use the function below. */ -typedef struct __attribute__((__packed__)) { +typedef struct XINE_PACKED { int32_t biSize; int32_t biWidth; int32_t biHeight; @@ -648,10 +661,10 @@ typedef struct __attribute__((__packed__)) { int32_t biClrImportant; } xine_bmiheader; -/* this is xine version of WAVEFORMATEX +/* this is xine version of WAVEFORMATEX * (the same comments from xine_bmiheader) */ -typedef struct __attribute__((__packed__)) { +typedef struct XINE_PACKED { int16_t wFormatTag; int16_t nChannels; int32_t nSamplesPerSec; @@ -660,7 +673,7 @@ typedef struct __attribute__((__packed__)) { int16_t wBitsPerSample; int16_t cbSize; } xine_waveformatex; -#ifndef ATTRIBUTE_PACKED +#ifndef SUPPORT_ATTRIBUTE_PACKED #pragma pack() #endif @@ -670,6 +683,10 @@ void _x_bmiheader_le2me( xine_bmiheader *bih ) XINE_PROTECTED; /* convert xine_waveformatex struct from little endian */ void _x_waveformatex_le2me( xine_waveformatex *wavex ) XINE_PROTECTED; +static __inline int _x_is_fourcc(void *ptr, void *tag) { + return memcmp(ptr, tag, 4) == 0; +} + #ifdef __cplusplus } #endif diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index ee50e5391..51e688f7e 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -1,18 +1,18 @@ /* - * Copyright (C) 2000-2005 the xine project - * + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,7 +20,7 @@ * * contents: * - * buffer types management. + * buffer types management. * convert FOURCC and audioformattag to BUF_xxx defines */ @@ -270,7 +270,7 @@ static const video_db_t video_db[] = { "Raw RGB" }, { - { + { /* is this right? copied from demux_qt: else if (!strncasecmp (video, "yuv2", 4)) this->video_type = BUF_VIDEO_YUY2; @@ -659,6 +659,8 @@ static const video_db_t video_db[] = { ME_FOURCC('a','v','c','1'), ME_FOURCC('h','2','6','4'), ME_FOURCC('H','2','6','4'), + ME_FOURCC('x','2','6','4'), + ME_FOURCC('X','2','6','4'), 0 }, BUF_VIDEO_H264, @@ -771,6 +773,22 @@ static const video_db_t video_db[] = { BUF_VIDEO_KMVC, "Karl Morton's Video Codec" }, +{ + { + ME_FOURCC('V','M','n','c'), + 0 + }, + BUF_VIDEO_VMNC, + "VMware Screen Codec" +}, +{ + { + ME_FOURCC('S','N','O','W'), + 0 + }, + BUF_VIDEO_SNOW, + "Snow" +}, { { 0 }, 0, "last entry" } }; @@ -798,6 +816,14 @@ static const audio_db_t audio_db[] = { }, { { + ME_FOURCC('a', 'd', 'u', 0x55), + 0 + }, + BUF_AUDIO_MP3ADU, + "MPEG layer-3 adu" +}, +{ + { ME_FOURCC('t','w','o','s'), ME_FOURCC('i','n','2','4'), 0 @@ -859,7 +885,7 @@ static const audio_db_t audio_db[] = { }, { { - 0x02, + 0x02, ME_FOURCC('m', 's', 0, 0x02), 0 }, @@ -883,7 +909,7 @@ static const audio_db_t audio_db[] = { "MS GSM" }, { - { + { /* these formattags are used by Vorbis ACM encoder and supported by NanDub, a variant of VirtualDub. */ 0x674f, 0x676f, 0x6750, 0x6770, 0x6751, 0x6771, @@ -992,7 +1018,7 @@ static const audio_db_t audio_db[] = { ME_FOURCC('M', 'P', '4', 'A'), ME_FOURCC('r', 'a', 'a', 'c'), ME_FOURCC('r', 'a', 'c', 'p'), - ME_FOURCC('A', 'A', 'C', ' '), + ME_FOURCC('A', 'A', 'C', ' '), 0 }, BUF_AUDIO_AAC, @@ -1124,11 +1150,32 @@ static const audio_db_t audio_db[] = { }, { { - 0 + ME_FOURCC('W', 'V', 'P', 'K'), }, BUF_AUDIO_WAVPACK, "Wavpack" }, +{ + { + ME_FOURCC('s', 'a', 'm', 'r'), + }, + BUF_AUDIO_AMR_NB, + "AMR narrow band" +}, +{ + { + ME_FOURCC('s', 'a', 'w', 'b'), + }, + BUF_AUDIO_AMR_WB, + "AMR wide band" +}, +{ + { + ME_FOURCC('T', 'T', 'A', '1'), + }, + BUF_AUDIO_TTA, + "True Audio Lossless" +}, { { 0 }, 0, "last entry" } }; @@ -1140,7 +1187,7 @@ static uint32_t cached_buf_type=0; if( fourcc_int == cached_fourcc ) return cached_buf_type; - + for( i = 0; video_db[i].buf_type; i++ ) { for( j = 0; video_db[i].fourcc[j]; j++ ) { if( fourcc_int == video_db[i].fourcc[j] ) { @@ -1153,11 +1200,11 @@ static uint32_t cached_buf_type=0; return 0; } -char * _x_buf_video_name( uint32_t buf_type ) { +const char * _x_buf_video_name( uint32_t buf_type ) { int i; - + buf_type &= 0xffff0000; - + for( i = 0; video_db[i].buf_type; i++ ) { if( buf_type == video_db[i].buf_type ) { return video_db[i].name; @@ -1174,7 +1221,7 @@ static uint32_t cached_buf_type=0; if( formattag == cached_formattag ) return cached_buf_type; - + for( i = 0; audio_db[i].buf_type; i++ ) { for( j = 0; audio_db[i].formattag[j]; j++ ) { if( formattag == audio_db[i].formattag[j] ) { @@ -1187,11 +1234,11 @@ static uint32_t cached_buf_type=0; return 0; } -char * _x_buf_audio_name( uint32_t buf_type ) { +const char * _x_buf_audio_name( uint32_t buf_type ) { int i; - + buf_type &= 0xffff0000; - + for( i = 0; audio_db[i].buf_type; i++ ) { if( buf_type == audio_db[i].buf_type ) { return audio_db[i].name; @@ -1205,7 +1252,7 @@ void _x_bmiheader_le2me( xine_bmiheader *bih ) { /* OBS: fourcc must be read using machine endianness * so don't play with biCompression here! */ - + bih->biSize = le2me_32(bih->biSize); bih->biWidth = le2me_32(bih->biWidth); bih->biHeight = le2me_32(bih->biHeight); @@ -1219,7 +1266,7 @@ void _x_bmiheader_le2me( xine_bmiheader *bih ) { } void _x_waveformatex_le2me( xine_waveformatex *wavex ) { - + wavex->wFormatTag = le2me_16(wavex->wFormatTag); wavex->nChannels = le2me_16(wavex->nChannels); wavex->nSamplesPerSec = le2me_32(wavex->nSamplesPerSec); diff --git a/src/xine-engine/configfile.c b/src/xine-engine/configfile.c index 2dc89f0af..8b274a801 100644 --- a/src/xine-engine/configfile.c +++ b/src/xine-engine/configfile.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -225,7 +225,7 @@ static int config_section_enum(const char *sect) { NULL }; int i = 0; - + while (known_section[i]) if (strcmp(sect, known_section[i++]) == 0) return i; @@ -234,7 +234,7 @@ static int config_section_enum(const char *sect) { static void config_key_split(const char *key, char **base, char **section, char **subsect, char **name) { char *parse; - + *base = strdup(key); if ((parse = strchr(*base, '.'))) { *section = *base; @@ -259,10 +259,10 @@ static void config_insert(config_values_t *this, cfg_entry_t *new_entry) { cfg_entry_t *cur, *prev; char *new_base, *new_section, *new_subsect, *new_name; char *cur_base, *cur_section, *cur_subsect, *cur_name; - + /* extract parts of the new key */ config_key_split(new_entry->key, &new_base, &new_section, &new_subsect, &new_name); - + /* search right position */ cur_base = NULL; for (cur = this->first, prev = NULL; cur; prev = cur, cur = cur->next) { @@ -270,7 +270,7 @@ static void config_insert(config_values_t *this, cfg_entry_t *new_entry) { if (cur_base) free(cur_base); config_key_split(cur->key, &cur_base, &cur_section, &cur_subsect, &cur_name); - + /* sort by section name */ if (!new_section && cur_section) break; if ( new_section && !cur_section) continue; @@ -302,14 +302,14 @@ static void config_insert(config_values_t *this, cfg_entry_t *new_entry) { if (cmp < 0) break; if (cmp > 0) continue; } - + break; } if (new_base) free(new_base); if (cur_base) free(cur_base); - + new_entry->next = cur; if (!cur) this->last = new_entry; @@ -319,18 +319,18 @@ static void config_insert(config_values_t *this, cfg_entry_t *new_entry) { this->first = new_entry; } -static cfg_entry_t *config_add (config_values_t *this, const char *key, int exp_level) { +static cfg_entry_t *XINE_MALLOC config_add (config_values_t *this, const char *key, int exp_level) { cfg_entry_t *entry; - entry = (cfg_entry_t *) xine_xmalloc (sizeof (cfg_entry_t)); + entry = calloc (1, sizeof (cfg_entry_t)); entry->config = this; entry->key = strdup(key); entry->type = XINE_CONFIG_TYPE_UNKNOWN; entry->unknown_value = NULL; entry->str_value = NULL; entry->exp_level = exp_level; - + config_insert(this, entry); lprintf ("add entry key=%s\n", key); @@ -356,22 +356,22 @@ static const char *config_xlate_internal (const char *key, const xine_config_ent return NULL; } -static const char *config_translate_key (const char *key) { +static const char *config_translate_key (const char *key, char **tmp) { /* Returns translated key or, if no translation found, NULL. * Translated key may be in a static buffer allocated within this function. * NOT re-entrant; assumes that config_lock is held. */ unsigned trans; - static char *newkey = NULL; + const char *newkey = NULL; /* first, special-case the decoder entries (so that new ones can be added * without requiring modification of the translation table) */ + *tmp = NULL; if (!strncmp (key, "decoder.", 8) && !strcmp (key + (trans = strlen (key)) - 9, "_priority")) { - newkey = realloc (newkey, trans + 27 - 17); /* diff. in string lengths */ - sprintf (newkey, "engine.decoder_priorities.%.*s", trans - 17, key + 8); - return newkey; + asprintf (tmp, "engine.decoder_priorities.%.*s", trans - 17, key + 8); + return *tmp; } /* search the translation table... */ @@ -386,6 +386,7 @@ static void config_lookup_entry_int (config_values_t *this, const char *key, cfg_entry_t **entry, cfg_entry_t **prev) { int trans; + char *tmp = NULL; /* try twice at most (second time with translation from old key name) */ for (trans = 2; trans; --trans) { @@ -396,15 +397,19 @@ static void config_lookup_entry_int (config_values_t *this, const char *key, *prev = *entry; *entry = (*entry)->next; } - - if (*entry) + + if (*entry) { + free(tmp); return; + } /* we did not find a match, maybe this is an old config entry name * trying to translate */ - key = config_translate_key(key); - if (!key) + key = config_translate_key(key, &tmp); + if (!key) { + free(tmp); return; + } } } @@ -415,11 +420,11 @@ static void config_lookup_entry_int (config_values_t *this, const char *key, static cfg_entry_t *config_lookup_entry(config_values_t *this, const char *key) { cfg_entry_t *entry, *prev; - + pthread_mutex_lock(&this->config_lock); config_lookup_entry_int(this, key, &entry, &prev); pthread_mutex_unlock(&this->config_lock); - + return entry; } @@ -520,7 +525,7 @@ static cfg_entry_t *config_register_string_internal (config_values_t *this, /* set string */ entry->type = XINE_CONFIG_TYPE_STRING; - + if (entry->unknown_value) entry->str_value = strdup(entry->unknown_value); else @@ -748,22 +753,22 @@ static int config_register_enum (config_values_t *this, entry->type = XINE_CONFIG_TYPE_ENUM; if (entry->unknown_value) - entry->num_value = config_parse_enum (entry->unknown_value, values); + entry->num_value = config_parse_enum (entry->unknown_value, (const char **)values); else entry->num_value = def_value; - + /* fill out rest of struct */ entry->num_default = def_value; /* allocate and copy the enum values */ - value_src = values; + value_src = (const char **)values; value_count = 0; while (*value_src) { value_src++; value_count++; } entry->enum_values = malloc (sizeof(char*) * (value_count + 1)); - value_src = values; + value_src = (const char **)values; value_dest = entry->enum_values; while (*value_src) { *value_dest = strdup(*value_src); @@ -801,7 +806,7 @@ static void config_shallow_copy(xine_cfg_entry_t *dest, cfg_entry_t *src) static void config_update_num (config_values_t *this, const char *key, int value) { - + cfg_entry_t *entry; entry = this->lookup_entry (this, key); @@ -830,13 +835,13 @@ static void config_update_num (config_values_t *this, xine_cfg_entry_t cb_entry; config_shallow_copy(&cb_entry, entry); - + /* it is safe to enter the callback from within a locked context * because we use a recursive mutex. */ entry->callback (entry->callback_data, &cb_entry); } - + pthread_mutex_unlock(&this->config_lock); } @@ -858,11 +863,11 @@ static void config_update_string (config_values_t *this, return; } - + /* if an enum is updated with a string, we convert the string to * its index and use update number */ if (entry->type == XINE_CONFIG_TYPE_ENUM) { - config_update_num(this, key, config_parse_enum(value, entry->enum_values)); + config_update_num(this, key, config_parse_enum(value, (const char **)entry->enum_values)); return; } @@ -882,7 +887,7 @@ static void config_update_string (config_values_t *this, xine_cfg_entry_t cb_entry; config_shallow_copy(&cb_entry, entry); - + /* it is safe to enter the callback from within a locked context * because we use a recursive mutex. */ @@ -924,7 +929,7 @@ void xine_config_load (xine_t *xine, const char *filename) { if (line[0] == '#') continue; - + if (line[0] == '.') { if (strncmp(line, ".version:", 9) == 0) { sscanf(line + 9, "%d", &this->current_version); @@ -944,15 +949,17 @@ void xine_config_load (xine_t *xine, const char *filename) { if (!(entry = config_lookup_entry(this, line))) { const char *key = line; + char *tmp = NULL; pthread_mutex_lock(&this->config_lock); if (this->current_version < CONFIG_FILE_VERSION) { /* old config file -> let's see if we have to rename this one */ - key = config_translate_key(key); + key = config_translate_key(key, &tmp); if (!key) key = line; /* no translation? fall back on untranslated key */ } entry = config_add (this, key, 50); entry->unknown_value = strdup(value); + free(tmp); pthread_mutex_unlock(&this->config_lock); } else { switch (entry->type) { @@ -995,32 +1002,32 @@ void xine_config_save (xine_t *xine, const char *filename) { unlink (temp); if (stat(temp, &backup_stat) != 0) { - + lprintf("backing up configfile to %s\n", temp); f_backup = fopen(temp, "w"); f_config = fopen(filename, "r"); - + if (f_config && f_backup && (stat(filename, &config_stat) == 0)) { char *buf = NULL; size_t rlen; - - buf = (char *) xine_xmalloc(config_stat.st_size + 1); + + buf = (char *) malloc(config_stat.st_size + 1); if((rlen = fread(buf, 1, config_stat.st_size, f_config)) && ((off_t)rlen == config_stat.st_size)) { (void) fwrite(buf, 1, rlen, f_backup); } free(buf); - + fclose(f_config); fclose(f_backup); stat(temp, &backup_stat); - + if (config_stat.st_size == backup_stat.st_size) backup = 1; else unlink(temp); - - } + + } else { if (f_config) @@ -1033,17 +1040,17 @@ void xine_config_save (xine_t *xine, const char *filename) { } } - + if (!backup && (stat(filename, &config_stat) == 0)) { xprintf(xine, XINE_VERBOSITY_LOG, _("configfile: WARNING: backing up configfile to %s failed\n"), temp); xprintf(xine, XINE_VERBOSITY_LOG, _("configfile: WARNING: your configuration will not be saved\n")); return; } - + lprintf ("writing config file to %s\n", filename); f_config = fopen(filename, "w"); - + if (f_config) { cfg_entry_t *entry; @@ -1134,7 +1141,7 @@ void xine_config_save (xine_t *xine, const char *filename) { entry = entry->next; } pthread_mutex_unlock(&this->config_lock); - + if (fclose(f_config) != 0) { xprintf(xine, XINE_VERBOSITY_LOG, _("configfile: WARNING: writing configuration to %s failed\n"), filename); xprintf(xine, XINE_VERBOSITY_LOG, _("configfile: WARNING: removing possibly broken config file %s\n"), filename); @@ -1145,7 +1152,7 @@ void xine_config_save (xine_t *xine, const char *filename) { backup = 0; } } - + if (backup) unlink(temp); } @@ -1204,7 +1211,7 @@ config_values_t *_x_config_init (void) { config_values_t *this; pthread_mutexattr_t attr; - if (!(this = xine_xmalloc(sizeof(config_values_t)))) { + if (!(this = calloc(1, sizeof(config_values_t)))) { printf ("configfile: could not allocate config object\n"); _x_abort(); @@ -1277,13 +1284,13 @@ int _x_config_change_opt(config_values_t *config, const char *opt) { free(key); return -1; } - + switch(entry->type) { case XINE_CONFIG_TYPE_STRING: config->update_string(config, key, value); handled = 1; break; - + case XINE_CONFIG_TYPE_RANGE: case XINE_CONFIG_TYPE_ENUM: case XINE_CONFIG_TYPE_NUM: @@ -1291,13 +1298,13 @@ int _x_config_change_opt(config_values_t *config, const char *opt) { config->update_num(config, key, (atoi(value))); handled = 1; break; - + case XINE_CONFIG_TYPE_UNKNOWN: entry->unknown_value = strdup(value); handled = 1; break; } - + free(key); return handled; } diff --git a/src/xine-engine/configfile.h b/src/xine-engine/configfile.h index e21b08db0..4622f87fe 100644 --- a/src/xine-engine/configfile.h +++ b/src/xine-engine/configfile.h @@ -38,11 +38,11 @@ extern "C" { #define CONFIG_FILE_VERSION 2 /* - * config entries above this experience + * config entries above this experience * level must never be changed from MRL */ #define XINE_CONFIG_SECURITY 30 - + typedef struct cfg_entry_s cfg_entry_t; typedef struct config_values_s config_values_t; @@ -190,7 +190,7 @@ struct config_values_s { * mutex for modification to the config */ pthread_mutex_t config_lock; - + /* * current config file's version number */ @@ -200,7 +200,7 @@ struct config_values_s { /* * allocate and init a new xine config object */ -config_values_t *_x_config_init (void) XINE_PROTECTED; +config_values_t *_x_config_init (void) XINE_MALLOC XINE_PROTECTED; /* * interpret stream_setup part of mrls for config value changes diff --git a/src/xine-engine/demux.c b/src/xine-engine/demux.c index f33397256..bbc130988 100644 --- a/src/xine-engine/demux.c +++ b/src/xine-engine/demux.c @@ -21,6 +21,9 @@ * hide some xine engine details from demuxers and reduce code duplication */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include <stdio.h> #include <string.h> @@ -47,12 +50,7 @@ #include <winsock.h> #endif -#ifdef MIN -#undef MIN -#endif -#define MIN(a,b) ( (a) < (b) ) ? (a) : (b) - -/* +/* * Flush audio and video buffers. It is called from demuxers on * seek/stop, and may be useful when user input changes a stream and * xine-lib has cached buffers that have yet to be played. @@ -64,10 +62,10 @@ void _x_demux_flush_engine (xine_stream_t *stream) { buf_element_t *buf; - + if( stream->gapless_switch ) return; - + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1); /* only flush/discard output ports on master streams */ @@ -79,23 +77,23 @@ void _x_demux_flush_engine (xine_stream_t *stream) { stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); } } - + stream->video_fifo->clear(stream->video_fifo); stream->audio_fifo->clear(stream->audio_fifo); - - pthread_mutex_lock(&stream->demux_mutex); + + pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_RESET_DECODER; stream->video_fifo->put (stream->video_fifo, buf); - + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_RESET_DECODER; stream->audio_fifo->put (stream->audio_fifo, buf); - - pthread_mutex_unlock(&stream->demux_mutex); - /* on seeking we must wait decoder fifos to process before doing flush. + pthread_mutex_unlock(&stream->demux_mutex); + + /* on seeking we must wait decoder fifos to process before doing flush. * otherwise we flush too early (before the old data has left decoders) */ _x_demux_control_headers_done (stream); @@ -104,7 +102,7 @@ void _x_demux_flush_engine (xine_stream_t *stream) { video_overlay_manager_t *ovl = stream->video_out->get_overlay_manager(stream->video_out); ovl->flush_events(ovl); } - + /* only flush/discard output ports on master streams */ if( stream->master == stream ) { if (stream->video_out) { @@ -117,16 +115,44 @@ void _x_demux_flush_engine (xine_stream_t *stream) { stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 0); } } - + stream->xine->port_ticket->release(stream->xine->port_ticket, 1); } +static struct timespec _x_compute_interval(unsigned int millisecs) { + struct timespec ts; +#ifdef WIN32 + FILETIME ft; + ULARGE_INTEGER ui; + + GetSystemTimeAsFileTime(&ft); + ui.u.LowPart = ft.dwLowDateTime; + ui.u.HighPart = ft.dwHighDateTime; + ui.QuadPart += millisecs * 10000; + ts.tv_sec = ui.QuadPart / 10000000; + ts.tv_sec = (ui.QuadPart % 10000000)*100; +#elif _POSIX_TIMERS > 0 + clock_gettime(CLOCK_REALTIME, &ts); + uint64_t ttimer = (uint64_t)ts.tv_sec*1000 + ts.tv_nsec/1000000 + millisecs; + ts.tv_sec = ttimer/1000; + ts.tv_nsec = (ttimer%1000)*1000000; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + uint64_t ttimer = (uint64_t)tv.tv_sec*1000 + tv.tv_usec/1000 + millisecs; + ts.tv_sec = ttimer/1000; + ts.tv_nsec = (ttimer%1000)*1000000; +#endif + return ts; +} + + void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags ) { buf_element_t *buf; - - pthread_mutex_lock(&stream->demux_mutex); + + pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_NEWPTS; @@ -140,7 +166,30 @@ void _x_demux_control_newpts( xine_stream_t *stream, int64_t pts, uint32_t flags buf->disc_off = pts; stream->audio_fifo->put (stream->audio_fifo, buf); - pthread_mutex_unlock(&stream->demux_mutex); + pthread_mutex_unlock(&stream->demux_mutex); +} + +/* avoid ao_loop being stuck in a pthread_cond_wait, waiting for data; + * return 1 if the stream is stopped + * (better fix wanted!) + */ +static int demux_unstick_ao_loop (xine_stream_t *stream) +{ +/* if (!stream->audio_thread_created) + return 0; +*/ + int status = xine_get_status (stream); + if (status != XINE_STATUS_QUIT && status != XINE_STATUS_STOP && stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_FINISHED) + return 0; +#if 0 + /* right, stream is stopped... */ + audio_buffer_t *buf = stream->audio_out->get_buffer (stream->audio_out); + buf->num_frames = 0; + buf->stream = NULL; + stream->audio_out->put_buffer (stream->audio_out, buf, stream); +#endif + lprintf("stuck\n"); + return 1; } /* sync with decoder fifos, making sure everything gets processed */ @@ -152,7 +201,7 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { /* we use demux_action_pending to wake up sleeping spu decoders */ stream->demux_action_pending = 1; - + /* allocate the buffers before grabbing the lock to prevent cyclic wait situations */ buf_video = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf_audio = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); @@ -170,8 +219,8 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { } else { header_count_audio = 0; } - - pthread_mutex_lock(&stream->demux_mutex); + + pthread_mutex_lock(&stream->demux_mutex); buf_video->type = BUF_CONTROL_HEADERS_DONE; stream->video_fifo->put (stream->video_fifo, buf_video); @@ -179,26 +228,33 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { buf_audio->type = BUF_CONTROL_HEADERS_DONE; stream->audio_fifo->put (stream->audio_fifo, buf_audio); - pthread_mutex_unlock(&stream->demux_mutex); + pthread_mutex_unlock(&stream->demux_mutex); + unsigned int max_iterations = 0; - while ((stream->header_count_audio < header_count_audio) || + while ((stream->header_count_audio < header_count_audio) || (stream->header_count_video < header_count_video)) { - struct timeval tv; - struct timespec ts; lprintf ("waiting for headers. v:%d %d a:%d %d\n", stream->header_count_video, header_count_video, - stream->header_count_audio, header_count_audio); + stream->header_count_audio, header_count_audio); + + struct timespec ts = _x_compute_interval(1000); + int ret_wait; - gettimeofday(&tv, NULL); - ts.tv_sec = tv.tv_sec + 1; - ts.tv_nsec = tv.tv_usec * 1000; /* use timedwait to workaround buggy pthread broadcast implementations */ - pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) { + xine_log(stream->xine, + XINE_LOG_MSG,_("Stuck in _x_demux_control_headers_done(). Taking the emergency exit\n")); + stream->emergency_brake = 1; + break; + } } stream->demux_action_pending = 0; - + pthread_cond_signal(&stream->demux_resume); + lprintf ("headers processed.\n"); pthread_mutex_unlock (&stream->counter_lock); @@ -207,25 +263,28 @@ void _x_demux_control_headers_done (xine_stream_t *stream) { void _x_demux_control_start( xine_stream_t *stream ) { buf_element_t *buf; + uint32_t flags = (stream->gapless_switch) ? BUF_FLAG_GAPLESS_SW : 0; - pthread_mutex_lock(&stream->demux_mutex); + pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->video_fifo->put (stream->video_fifo, buf); buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_START; + buf->decoder_flags = flags; stream->audio_fifo->put (stream->audio_fifo, buf); - pthread_mutex_unlock(&stream->demux_mutex); + pthread_mutex_unlock(&stream->demux_mutex); } void _x_demux_control_end( xine_stream_t *stream, uint32_t flags ) { buf_element_t *buf; - pthread_mutex_lock(&stream->demux_mutex); + pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_END; @@ -237,26 +296,26 @@ void _x_demux_control_end( xine_stream_t *stream, uint32_t flags ) { buf->decoder_flags = flags; stream->audio_fifo->put (stream->audio_fifo, buf); - pthread_mutex_unlock(&stream->demux_mutex); + pthread_mutex_unlock(&stream->demux_mutex); } void _x_demux_control_nop( xine_stream_t *stream, uint32_t flags ) { buf_element_t *buf; - pthread_mutex_lock(&stream->demux_mutex); + pthread_mutex_lock(&stream->demux_mutex); buf = stream->video_fifo->buffer_pool_alloc (stream->video_fifo); buf->type = BUF_CONTROL_NOP; buf->decoder_flags = flags; stream->video_fifo->put (stream->video_fifo, buf); - + buf = stream->audio_fifo->buffer_pool_alloc (stream->audio_fifo); buf->type = BUF_CONTROL_NOP; buf->decoder_flags = flags; stream->audio_fifo->put (stream->audio_fifo, buf); - pthread_mutex_unlock(&stream->demux_mutex); + pthread_mutex_unlock(&stream->demux_mutex); } static void *demux_loop (void *stream_gen) { @@ -271,7 +330,7 @@ static void *demux_loop (void *stream_gen) { pthread_mutex_lock( &stream->demux_lock ); stream->emergency_brake = 0; - + /* do-while needed to seek after demux finished */ do { @@ -284,12 +343,14 @@ static void *demux_loop (void *stream_gen) { /* someone may want to interrupt us */ if( stream->demux_action_pending ) { - pthread_mutex_unlock( &stream->demux_lock ); + struct timeval tv; + struct timespec ts; - lprintf ("sched_yield\n"); + gettimeofday(&tv, NULL); + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = (tv.tv_usec + 100000) * 1000; - sched_yield(); - pthread_mutex_lock( &stream->demux_lock ); + pthread_cond_timedwait (&stream->demux_resume, &stream->demux_lock, &ts); } } @@ -337,7 +398,7 @@ static void *demux_loop (void *stream_gen) { /* demux_thread_running is zero if demux loop has been stopped by user */ non_user = stream->demux_thread_running; stream->demux_thread_running = 0; - + _x_demux_control_end(stream, non_user); lprintf ("loop finished, end buffer sent\n"); @@ -345,13 +406,24 @@ static void *demux_loop (void *stream_gen) { pthread_mutex_unlock( &stream->demux_lock ); pthread_mutex_lock (&stream->counter_lock); - while ((stream->finished_count_audio < finished_count_audio) || + struct timespec ts; + unsigned int max_iterations = 0; + int ret_wait; + while ((stream->finished_count_audio < finished_count_audio) || (stream->finished_count_video < finished_count_video)) { lprintf ("waiting for finisheds.\n"); - pthread_cond_wait (&stream->counter_changed, &stream->counter_lock); + ts = _x_compute_interval(1000); + ret_wait = pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); + + if (ret_wait == ETIMEDOUT && demux_unstick_ao_loop (stream) && ++max_iterations > 4) { + xine_log(stream->xine, + XINE_LOG_MSG,_("Stuck in demux_loop(). Taking the emergency exit\n")); + stream->emergency_brake = 1; + break; + } } pthread_mutex_unlock (&stream->counter_lock); - + _x_handle_stream_end(stream, non_user); return NULL; } @@ -359,13 +431,14 @@ static void *demux_loop (void *stream_gen) { int _x_demux_start_thread (xine_stream_t *stream) { int err; - + lprintf ("start thread called\n"); - + stream->demux_action_pending = 1; pthread_mutex_lock( &stream->demux_lock ); stream->demux_action_pending = 0; - + pthread_cond_signal(&stream->demux_resume); + if( !stream->demux_thread_running ) { if (stream->demux_thread_created) { @@ -381,21 +454,22 @@ int _x_demux_start_thread (xine_stream_t *stream) { _x_abort(); } } - + pthread_mutex_unlock( &stream->demux_lock ); return 0; } int _x_demux_stop_thread (xine_stream_t *stream) { - + void *p; - + lprintf ("stop thread called\n"); - + stream->demux_action_pending = 1; pthread_mutex_lock( &stream->demux_lock ); stream->demux_thread_running = 0; stream->demux_action_pending = 0; + pthread_cond_signal(&stream->demux_resume); /* At that point, the demuxer has sent the last audio/video buffer, * so it's a safe place to flush the engine. @@ -404,12 +478,12 @@ int _x_demux_stop_thread (xine_stream_t *stream) { pthread_mutex_unlock( &stream->demux_lock ); lprintf ("joining thread %ld\n", stream->demux_thread ); - + if( stream->demux_thread_created ) { pthread_join (stream->demux_thread, &p); stream->demux_thread_created = 0; } - + /* * Wake up xine_play if it's waiting for a frame */ @@ -435,7 +509,7 @@ int _x_demux_read_header( input_plugin_t *input, unsigned char *buffer, off_t si read_size = input->read(input, buffer, size); input->seek(input, 0, SEEK_SET); } else if (input->get_capabilities(input) & INPUT_CAP_PREVIEW) { - buf = xine_xmalloc(MAX_PREVIEW_SIZE); + buf = malloc(MAX_PREVIEW_SIZE); read_size = input->get_optional_data(input, buf, INPUT_OPTIONAL_DATA_PREVIEW); read_size = MIN (read_size, size); memcpy(buffer, buf, read_size); @@ -547,7 +621,7 @@ int _x_action_pending (xine_stream_t *stream) { * * the other ones help enforcing that demuxers provide the information * they have about the stream, so things like the GUI slider bar can - * work as expected. + * work as expected. */ void _x_demux_send_data(fifo_buffer_t *fifo, uint8_t *data, int size, int64_t pts, uint32_t type, uint32_t decoder_flags, @@ -595,10 +669,10 @@ void _x_demux_send_data(fifo_buffer_t *fifo, uint8_t *data, int size, * * If reading fails, -1 is returned */ -int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, - int size, int64_t pts, uint32_t type, - uint32_t decoder_flags, off_t input_normpos, - int input_time, int total_time, +int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, + int size, int64_t pts, uint32_t type, + uint32_t decoder_flags, off_t input_normpos, + int input_time, int total_time, uint32_t frame_number) { buf_element_t *buf; @@ -620,7 +694,7 @@ int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, if(input->read(input, buf->content, buf->size) < buf->size) { buf->free_buffer(buf); - return -1; + return -1; } size -= buf->size; @@ -636,7 +710,7 @@ int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, fifo->put (fifo, buf); } - + return 0; } @@ -652,7 +726,7 @@ void _x_demux_send_mrl_reference (xine_stream_t *stream, int alternative, xine_mrl_reference_data_ext_t *e; xine_mrl_reference_data_t *b; } data; - int mrl_len = strlen (mrl); + const size_t mrl_len = strlen (mrl); if (!title) title = ""; @@ -663,7 +737,7 @@ void _x_demux_send_mrl_reference (xine_stream_t *stream, int alternative, event.data_length = offsetof (xine_mrl_reference_data_ext_t, mrl) + mrl_len + strlen (title) + 2; data.e = event.data = malloc (event.data_length); - + data.e->alternative = alternative; data.e->start_time = start_time; data.e->duration = duration; diff --git a/src/xine-engine/events.c b/src/xine-engine/events.c index f79187682..a51813adc 100644 --- a/src/xine-engine/events.c +++ b/src/xine-engine/events.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -94,7 +94,7 @@ void xine_event_send (xine_stream_t *stream, const xine_event_t *event) { cevent->data = NULL; } gettimeofday (&cevent->tv, NULL); - + pthread_mutex_lock (&queue->lock); xine_list_push_back (queue->events, cevent); pthread_cond_signal (&queue->new_event); @@ -135,7 +135,7 @@ void xine_event_dispose_queue (xine_event_queue_t *queue) { xine_event_t *qevent; xine_event_queue_t *q; xine_list_iterator_t ite; - + pthread_mutex_lock (&stream->event_queues_lock); ite = xine_list_front (stream->event_queues); @@ -144,7 +144,7 @@ void xine_event_dispose_queue (xine_event_queue_t *queue) { if ( ite ) { do { q = xine_list_get_value (stream->event_queues, ite); - + if ( q == queue ) break; } while( (ite = xine_list_next (stream->event_queues, ite)) ); @@ -160,17 +160,17 @@ void xine_event_dispose_queue (xine_event_queue_t *queue) { xine_list_remove (stream->event_queues, ite); pthread_mutex_unlock (&stream->event_queues_lock); - /* - * send quit event + /* + * send quit event */ qevent = (xine_event_t *)malloc(sizeof(xine_event_t)); - + qevent->type = XINE_EVENT_QUIT; qevent->stream = stream; qevent->data = NULL; qevent->data_length = 0; gettimeofday (&qevent->tv, NULL); - + pthread_mutex_lock (&queue->lock); xine_list_push_back (queue->events, qevent); pthread_cond_signal (&queue->new_event); @@ -179,15 +179,15 @@ void xine_event_dispose_queue (xine_event_queue_t *queue) { /* * join listener thread, if any */ - + if (queue->listener_thread) { void *p; pthread_join (*queue->listener_thread, &p); free (queue->listener_thread); } - + /* - * clean up pending events + * clean up pending events */ while ( (event = xine_event_get (queue)) ) { @@ -233,7 +233,7 @@ static void *listener_loop (void *queue_gen) { } -void xine_event_create_listener_thread (xine_event_queue_t *queue, +void xine_event_create_listener_thread (xine_event_queue_t *queue, xine_event_listener_cb_t callback, void *user_data) { int err; @@ -244,7 +244,7 @@ void xine_event_create_listener_thread (xine_event_queue_t *queue, if ((err = pthread_create (queue->listener_thread, NULL, listener_loop, queue)) != 0) { - xprintf (queue->stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (queue->stream->xine, XINE_VERBOSITY_NONE, "events: can't create new thread (%s)\n", strerror(err)); _x_abort(); } diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index 1ac4ed982..e45336d98 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -40,7 +40,7 @@ /* ******************* Stream Info *************************** */ /* - * Compare stream_info, private and public values, + * Compare stream_info, private and public values, * return 1 if it's identical, otherwirse 0. */ static int stream_info_is_identical(xine_stream_t *stream, int info) { @@ -105,7 +105,7 @@ uint32_t _x_stream_info_get(xine_stream_t *stream, int info) { pthread_mutex_lock(&stream->info_mutex); stream_info = stream->stream_info[info]; pthread_mutex_unlock(&stream->info_mutex); - + return stream_info; } @@ -120,7 +120,7 @@ uint32_t _x_stream_info_get_public(xine_stream_t *stream, int info) { if(info_valid(info) && (!stream_info_is_identical(stream, info))) stream_info = stream->stream_info_public[info] = stream->stream_info[info]; pthread_mutex_unlock(&stream->info_mutex); - + return stream_info; } @@ -131,13 +131,13 @@ uint32_t _x_stream_info_get_public(xine_stream_t *stream, int info) { * at the end of the string */ static void meta_info_chomp(char *str) { - int i, len; + ssize_t i, len; len = strlen(str); if (!len) return; i = len - 1; - + while ((i >= 0) && ((unsigned char)str[i] <= 32)) { str[i] = 0; i--; @@ -145,13 +145,13 @@ static void meta_info_chomp(char *str) { } /* - * Compare stream_info, public and private values, + * Compare stream_info, public and private values, * return 1 if it's identical, otherwise 0. */ static int meta_info_is_identical(xine_stream_t *stream, int info) { - + if((!(stream->meta_info_public[info] && stream->meta_info[info])) || - ((stream->meta_info_public[info] && stream->meta_info[info]) && + ((stream->meta_info_public[info] && stream->meta_info[info]) && strcmp(stream->meta_info_public[info], stream->meta_info[info]))) return 0; @@ -175,7 +175,7 @@ static int meta_valid(int info) { */ static void meta_info_set_unlocked_utf8(xine_stream_t *stream, int info, const char *value) { if(meta_valid(info)) { - + if(stream->meta_info[info]) free(stream->meta_info[info]); @@ -251,7 +251,15 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con size_t inbytesleft, outbytesleft; inbuf = (ICONV_CONST char *)value; - inbytesleft = strlen(value); + if (!strncmp (enc, "UTF-16", 6) || !strncmp (enc, "UCS-2", 5)) + { + /* strlen() won't work with UTF-16* or UCS-2* */ + inbytesleft = 0; + while (value[inbytesleft] || value[inbytesleft + 1]) + inbytesleft += 2; + } /* ... do we need to handle UCS-4? Probably not. */ + else + inbytesleft = strlen(value); outbytesleft = 4 * inbytesleft; /* estimative (max) */ outbuf = utf8_value = malloc(outbytesleft+1); @@ -267,7 +275,7 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con } } #endif - + meta_info_set_unlocked_utf8(stream, info, value); } @@ -340,11 +348,10 @@ void _x_meta_info_set_utf8(xine_stream_t *stream, int info, const char *str) { void _x_meta_info_n_set(xine_stream_t *stream, int info, const char *buf, int len) { pthread_mutex_lock(&stream->meta_mutex); if(meta_valid(info) && len) { - char *str = xine_xmalloc(len + 1); - - snprintf(str, len + 1 , "%s", buf); - meta_info_set_unlocked(stream, info, (const char *) &str[0]); - free(str); + char *str = strndup(buf, len); + + meta_info_set_unlocked(stream, info, str); + free(str); } pthread_mutex_unlock(&stream->meta_mutex); } @@ -359,8 +366,8 @@ void _x_meta_info_set_multi(xine_stream_t *stream, int info, ...) { va_list ap; char *args[1025]; char *buf; - int n, len; - + size_t n, len; + len = n = 0; va_start(ap, info); @@ -370,32 +377,32 @@ void _x_meta_info_set_multi(xine_stream_t *stream, int info, ...) { n++; } va_end(ap); - + args[n] = NULL; - + if(len) { char *p, *meta; - - p = meta = (char *) xine_xmalloc(len + 1); - + + p = meta = (char *) malloc(len + 1); + n = 0; while(args[n]) { strcpy(meta, args[n]); meta += strlen(args[n]) + 1; n++; } - + *meta = '\0'; if(stream->meta_info[info]) free(stream->meta_info[info]); - + stream->meta_info[info] = p; - + if(stream->meta_info[info] && strlen(stream->meta_info[info])) meta_info_chomp(stream->meta_info[info]); } - + } pthread_mutex_unlock(&stream->meta_mutex); } @@ -405,11 +412,11 @@ void _x_meta_info_set_multi(xine_stream_t *stream, int info, ...) { */ const char *_x_meta_info_get(xine_stream_t *stream, int info) { const char *meta_info = NULL; - + pthread_mutex_lock(&stream->meta_mutex); meta_info = stream->meta_info[info]; pthread_mutex_unlock(&stream->meta_mutex); - + return meta_info; } @@ -423,13 +430,13 @@ const char *_x_meta_info_get_public(xine_stream_t *stream, int info) { meta_info = stream->meta_info_public[info]; if(meta_valid(info) && (!meta_info_is_identical(stream, info))) { meta_info_public_reset_unlocked(stream, info); - + if(stream->meta_info[info]) stream->meta_info_public[info] = strdup(stream->meta_info[info]); meta_info = stream->meta_info_public[info]; } pthread_mutex_unlock(&stream->meta_mutex); - + return meta_info; } diff --git a/src/xine-engine/info_helper.h b/src/xine-engine/info_helper.h index d4123ba2b..666b94f08 100644 --- a/src/xine-engine/info_helper.h +++ b/src/xine-engine/info_helper.h @@ -20,7 +20,7 @@ * stream metainfo helper functions * hide some xine engine details from demuxers and reduce code duplication * - * $id$ + * $id$ */ #ifndef INFO_HELPER_H diff --git a/src/xine-engine/input_cache.c b/src/xine-engine/input_cache.c index 30b1ba4aa..e761fed38 100644 --- a/src/xine-engine/input_cache.c +++ b/src/xine-engine/input_cache.c @@ -19,7 +19,7 @@ * * Buffered Input Plugin (request optimizer). * - * The goal of this input plugin is to reduce + * The goal of this input plugin is to reduce * the number of calls to the real input plugin. */ @@ -58,7 +58,7 @@ typedef struct { } cache_input_plugin_t; -/* +/* * read data from input plugin and write it into file */ static off_t cache_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { @@ -128,13 +128,13 @@ static off_t cache_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { /* readahead bytes */ main_read = this->main_input_plugin->read(this->main_input_plugin, this->buf, this->buf_size); this->main_read_call++; - + if( main_read >= 0 ) { this->buf_len = main_read; - + if (len > this->buf_len) len = this->buf_len; - + if (len) { xine_fast_memcpy(buf + read_len, this->buf, len); this->buf_pos = len; @@ -148,7 +148,7 @@ static off_t cache_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { /* direct read */ main_read = this->main_input_plugin->read(this->main_input_plugin, buf + read_len, len); this->main_read_call++; - + if( main_read >= 0 ) read_len += main_read; else @@ -156,7 +156,7 @@ static off_t cache_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { read_len = main_read; } } - + return read_len; } @@ -190,7 +190,7 @@ static buf_element_t *cache_plugin_read_block(input_plugin_t *this_gen, fifo_buf buf = fifo->buffer_pool_alloc (fifo); if (buf) { buf->type = BUF_DEMUX_BLOCK; - + assert(todo <= buf->max_size); read_len = cache_plugin_read (this_gen, buf->content, todo); buf->size = read_len; @@ -226,11 +226,11 @@ static off_t cache_plugin_seek(input_plugin_t *this_gen, off_t offset, int origi case SEEK_CUR: rel_offset = offset; break; - + case SEEK_SET: rel_offset = offset - cur_pos; break; - + default: /* invalid origin - main input should know better */ cur_pos = this->main_input_plugin->seek(this->main_input_plugin, offset, origin); @@ -238,16 +238,16 @@ static off_t cache_plugin_seek(input_plugin_t *this_gen, off_t offset, int origi this->main_seek_call++; return cur_pos; } - + new_buf_pos = (off_t)this->buf_pos + rel_offset; lprintf("buf_len: %d, rel_offset=%"PRId64", new_buf_pos=%"PRId64"\n", - this->buf_len, rel_offset, new_buf_pos); - + this->buf_len, rel_offset, new_buf_pos); + if ((new_buf_pos < 0) || (new_buf_pos >= this->buf_len)) { if( origin == SEEK_SET ) cur_pos = this->main_input_plugin->seek(this->main_input_plugin, offset, origin); else - cur_pos = this->main_input_plugin->seek(this->main_input_plugin, + cur_pos = this->main_input_plugin->seek(this->main_input_plugin, offset - (this->buf_len - this->buf_pos), origin); this->buf_len = this->buf_pos = 0; this->main_seek_call++; @@ -262,7 +262,7 @@ static off_t cache_plugin_seek(input_plugin_t *this_gen, off_t offset, int origi static off_t cache_plugin_seek_time(input_plugin_t *this_gen, int time_offset, int origin) { cache_input_plugin_t *this = (cache_input_plugin_t *)this_gen; off_t cur_pos; - + lprintf("time_offset: %d, origin: %d\n", time_offset, origin); this->seek_call++; @@ -275,7 +275,7 @@ static off_t cache_plugin_seek_time(input_plugin_t *this_gen, int time_offset, i static off_t cache_plugin_get_current_pos(input_plugin_t *this_gen) { cache_input_plugin_t *this = (cache_input_plugin_t *)this_gen; off_t cur_pos; - + cur_pos = this->main_input_plugin->get_current_pos(this->main_input_plugin); if( this->buf_len ) { if( cur_pos >= (this->buf_len - this->buf_pos) ) @@ -290,7 +290,7 @@ static off_t cache_plugin_get_current_pos(input_plugin_t *this_gen) { static int cache_plugin_get_current_time(input_plugin_t *this_gen) { cache_input_plugin_t *this = (cache_input_plugin_t *)this_gen; int cur_time; - + cur_time = this->main_input_plugin->get_current_time(this->main_input_plugin); return cur_time; @@ -314,7 +314,7 @@ static const char* cache_plugin_get_mrl (input_plugin_t *this_gen) { return this->main_input_plugin->get_mrl(this->main_input_plugin); } -static int cache_plugin_get_optional_data (input_plugin_t *this_gen, +static int cache_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { cache_input_plugin_t *this = (cache_input_plugin_t *)this_gen; @@ -322,8 +322,8 @@ static int cache_plugin_get_optional_data (input_plugin_t *this_gen, this->main_input_plugin, data, data_type); } -/* - * dispose main input plugin and self +/* + * dispose main input plugin and self */ static void cache_plugin_dispose(input_plugin_t *this_gen) { cache_input_plugin_t *this = (cache_input_plugin_t *)this_gen; @@ -341,8 +341,8 @@ static void cache_plugin_dispose(input_plugin_t *this_gen) { } -/* - * create self instance, +/* + * create self instance, */ input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) { cache_input_plugin_t *this; @@ -356,10 +356,10 @@ input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahe lprintf("mrl: %s\n", main_plugin->get_mrl(main_plugin)); - this = (cache_input_plugin_t *)xine_xmalloc(sizeof(cache_input_plugin_t)); + this = calloc(1, sizeof(cache_input_plugin_t)); if (!this) return NULL; - + this->main_input_plugin = main_plugin; this->stream = stream; @@ -386,7 +386,7 @@ input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahe this->buf_size = DEFAULT_BUFFER_SIZE; } - this->buf = (char *)xine_xmalloc(this->buf_size); + this->buf = calloc(1, this->buf_size); if (!this->buf) { free (this); return NULL; diff --git a/src/xine-engine/input_rip.c b/src/xine-engine/input_rip.c index 0c185aa1b..faeaae62d 100644 --- a/src/xine-engine/input_rip.c +++ b/src/xine-engine/input_rip.c @@ -20,12 +20,12 @@ * Rip Input Plugin for catching streams * * It saves raw data into file as go from input plugins. - * + * * Usage: * * - activation: * xine stream_mrl#save:file.raw - * + * * - it's possible speeder saving streams in the xine without playing: * xine stream_mrl#save:file.raw\;noaudio\;novideo */ @@ -95,7 +95,7 @@ static off_t min_off(off_t a, off_t b) { return a <= b ? a : b; } -/* +/* * read data from input plugin and write it into file */ static off_t rip_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { @@ -123,7 +123,7 @@ static off_t rip_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { npreview = 0; nread = min_off(this->savepos - this->curpos, len); } - + /* size to write into file */ nwrite = len - npreview - nread; /* size to read from file */ @@ -149,7 +149,7 @@ static off_t rip_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { lprintf("%s => returned %"PRId64"" CLR_RST "\n", retlen == nread_orig + nwrite ? "" : CLR_FAIL, retlen); if (retlen < 0) { - xine_log(this->stream->xine, XINE_LOG_MSG, + xine_log(this->stream->xine, XINE_LOG_MSG, _("input_rip: reading by input plugin failed\n")); return -1; } @@ -163,10 +163,10 @@ static off_t rip_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { } this->savepos += nwrite; lprintf(" => saved %"PRId64" bytes\n", nwrite); - } else + } else nwrite = 0; } - + this->curpos += (npreview + nread + nwrite); return npreview + nread + nwrite; @@ -191,7 +191,7 @@ static uint32_t rip_plugin_get_capabilities(input_plugin_t *this_gen) { uint32_t caps; caps = this->main_input_plugin->get_capabilities(this->main_input_plugin); - + if (this->regular) caps |= INPUT_CAP_SEEKABLE; @@ -199,11 +199,11 @@ static uint32_t rip_plugin_get_capabilities(input_plugin_t *this_gen) { return caps; } -/* +/* * read a block of data from input plugin and write it into file * * This rip plugin returns block unchanged from main input plugin. But special - * cases are reading over preview or reading already saved data - it returns + * cases are reading over preview or reading already saved data - it returns * own allocated block. */ static buf_element_t *rip_plugin_read_block(input_plugin_t *this_gen, fifo_buffer_t *fifo, off_t todo) { @@ -230,7 +230,7 @@ static buf_element_t *rip_plugin_read_block(input_plugin_t *this_gen, fifo_buffe npreview = 0; nread = min_off(this->savepos - this->curpos, todo); } - + /* size to write into file */ nwrite = todo - npreview - nread; /* size to read from file */ @@ -249,7 +249,7 @@ static buf_element_t *rip_plugin_read_block(input_plugin_t *this_gen, fifo_buffe lprintf(" => get %"PRId64" bytes from the preview (block)\n", npreview); memcpy(buf->content, &this->preview[this->curpos], npreview); } - + /* re-reading from the file */ if (nread_file) { lprintf(" => read %"PRId64" bytes from the file (block)\n", nread_file); @@ -286,17 +286,17 @@ static buf_element_t *rip_plugin_read_block(input_plugin_t *this_gen, fifo_buffe if (retlen > nread_orig) { nwrite = retlen - nread_orig; if (fwrite(buf->content + this->savepos - this->curpos, nwrite, 1, this->file) != 1) { - xine_log(this->stream->xine, XINE_LOG_MSG, + xine_log(this->stream->xine, XINE_LOG_MSG, _("input_rip: error writing to file %" PRIdMAX " bytes: %s\n"), (intmax_t)(retlen - nread_orig), strerror(errno)); return NULL; } this->savepos += nwrite; lprintf(" => saved %"PRId64" bytes\n", nwrite); - } else + } else nwrite = 0; } - + this->curpos += (npreview + nread + nwrite); buf->size = npreview + nread + nwrite; @@ -323,11 +323,11 @@ static off_t rip_seek_original(rip_input_plugin_t *this, off_t reqpos) { return pos; } - + /* * seek in RIP - * - * If we are seeking back and we can read from saved file, + * + * If we are seeking back and we can read from saved file, * position of original input plugin isn't changed. */ static off_t rip_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) { @@ -339,7 +339,7 @@ static off_t rip_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) double interval = 0; lprintf("seek, offset %"PRId64", origin %d (curpos %"PRId64", savepos %"PRId64")\n", offset, origin, this->curpos, this->savepos); - + switch (origin) { case SEEK_SET: newpos = offset; break; case SEEK_CUR: newpos = this->curpos + offset; break; @@ -376,7 +376,7 @@ static off_t rip_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) if ((pos = rip_seek_original(this, reqpos)) == -1) return -1; if (pos == reqpos) this->curpos = newpos; } - + return this->curpos; } @@ -393,7 +393,7 @@ static off_t rip_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) if ((pos = rip_seek_original(this, this->savepos)) == -1) return -1; if (pos > this->savepos) xine_log(this->stream->xine, XINE_LOG_MSG, - _("input_rip: %" PRIdMAX " bytes dropped\n"), + _("input_rip: %" PRIdMAX " bytes dropped\n"), (intmax_t)(pos - this->savepos)); } } @@ -425,13 +425,13 @@ static off_t rip_plugin_seek(input_plugin_t *this_gen, off_t offset, int origin) } lprintf(" => new position %"PRId64"\n", this->curpos); - + return this->curpos; } static off_t rip_plugin_seek_time(input_plugin_t *this_gen, int time_offset, int origin) { rip_input_plugin_t *this = (rip_input_plugin_t *)this_gen; - + lprintf("seek_time, time_offset: %d, origin: %d\n", time_offset, origin); return this->main_input_plugin->seek_time(this->main_input_plugin, time_offset, origin); @@ -451,13 +451,13 @@ static off_t rip_plugin_get_current_pos(input_plugin_t *this_gen) { lprintf(CLR_FAIL "position: computed = %"PRId64", input plugin = %"PRId64"" CLR_RST "\n", this->curpos, pos); } #endif - + return this->curpos; } static int rip_plugin_get_current_time(input_plugin_t *this_gen) { rip_input_plugin_t *this = (rip_input_plugin_t *)this_gen; - + return this->main_input_plugin->get_current_time(this->main_input_plugin); } @@ -484,7 +484,7 @@ static const char* rip_plugin_get_mrl (input_plugin_t *this_gen) { return this->main_input_plugin->get_mrl(this->main_input_plugin); } -static int rip_plugin_get_optional_data (input_plugin_t *this_gen, +static int rip_plugin_get_optional_data (input_plugin_t *this_gen, void *data, int data_type) { rip_input_plugin_t *this = (rip_input_plugin_t *)this_gen; @@ -494,11 +494,11 @@ static int rip_plugin_get_optional_data (input_plugin_t *this_gen, return this->preview_size; } else return this->main_input_plugin->get_optional_data( - this->main_input_plugin, data, data_type); + this->main_input_plugin, data, data_type); } -/* - * dispose main input plugin and self +/* + * dispose main input plugin and self */ static void rip_plugin_dispose(input_plugin_t *this_gen) { rip_input_plugin_t *this = (rip_input_plugin_t *)this_gen; @@ -517,10 +517,9 @@ static void rip_plugin_dispose(input_plugin_t *this_gen) { * returns non-zero, if there was enough space */ static int dir_file_concat(char *target, size_t maxlen, const char *dir, const char *name) { - size_t len_dir, len_name, pos_name = 0; - - len_name = strlen(name); - len_dir = strlen(dir); + size_t len_name = strlen(name); + size_t len_dir = strlen(dir); + size_t pos_name = 0; /* remove slashes */ if (dir[len_dir - 1] == '/') len_dir--; @@ -541,8 +540,8 @@ static int dir_file_concat(char *target, size_t maxlen, const char *dir, const c } -/* - * create self instance, +/* + * create self instance, * target file for writing stream is specified in 'data' */ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) { @@ -572,7 +571,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f #ifndef SAVING_ALWAYS_PERMIT if ( main_plugin->get_capabilities(main_plugin) & INPUT_CAP_RIP_FORBIDDEN ) { - xine_log(stream->xine, XINE_LOG_MSG, + xine_log(stream->xine, XINE_LOG_MSG, _("input_rip: ripping/caching of this source is not permitted!\n")); _x_message(stream, XINE_MSG_SECURITY, _("xine is not allowed to save from this source. (possibly copyrighted material?)"), NULL); @@ -585,7 +584,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f return NULL; } - this = (rip_input_plugin_t *)xine_xmalloc(sizeof(rip_input_plugin_t)); + this = calloc(1, sizeof(rip_input_plugin_t)); this->main_input_plugin = main_plugin; this->stream = stream; this->curpos = 0; @@ -593,7 +592,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f fnc = strdup(filename); target_basename = basename(fnc); - dir_file_concat(target, MAX_TARGET_LEN, stream->xine->save_path, + dir_file_concat(target, MAX_TARGET_LEN, stream->xine->save_path, target_basename); strcpy(target_no, target); @@ -622,7 +621,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f lprintf("target file: %s\n", target_no); if ((this->file = fopen(target_no, mode)) == NULL) { - xine_log(this->stream->xine, XINE_LOG_MSG, + xine_log(this->stream->xine, XINE_LOG_MSG, _("input_rip: error opening file %s: %s\n"), target_no, strerror(errno)); free(this); return NULL; @@ -640,7 +639,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f this->preview_size = buf->size; this->preview = malloc(this->preview_size); memcpy(this->preview, buf->content, this->preview_size); - + buf->free_buffer(buf); } else { this->preview = malloc(MAX_PREVIEW_SIZE); @@ -652,7 +651,7 @@ input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *f if (this->preview && this->preview_size) { if (fwrite(this->preview, this->preview_size, 1, this->file) != 1) { - xine_log(this->stream->xine, XINE_LOG_MSG, + xine_log(this->stream->xine, XINE_LOG_MSG, _("input_rip: error writing to file %" PRIdMAX " bytes: %s\n"), (intmax_t)(this->preview_size), strerror(errno)); fclose(this->file); diff --git a/src/xine-engine/io_helper.c b/src/xine-engine/io_helper.c index c3654c762..b06c47709 100644 --- a/src/xine-engine/io_helper.c +++ b/src/xine-engine/io_helper.c @@ -53,14 +53,14 @@ static int _x_io_tcp_connect_ipv4(xine_stream_t *stream, const char *host, int p struct hostent *h; int i, s; - + h = gethostbyname(host); if (h == NULL) { _x_message(stream, XINE_MSG_UNKNOWN_HOST, "unable to resolve", host, NULL); return -1; } - s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s == -1) { _x_message(stream, XINE_MSG_CONNECTION_REFUSED, "failed to create socket", strerror(errno), NULL); return -1; @@ -88,12 +88,12 @@ static int _x_io_tcp_connect_ipv4(xine_stream_t *stream, const char *host, int p for (i = 0; h->h_addr_list[i]; i++) { struct in_addr ia; struct sockaddr_in sin; - + memcpy (&ia, h->h_addr_list[i], 4); sin.sin_family = AF_INET; sin.sin_addr = ia; sin.sin_port = htons(port); - + #ifndef WIN32 if (connect(s, (struct sockaddr *)&sin, sizeof(sin))==-1 && errno != EINPROGRESS) { #else @@ -106,7 +106,7 @@ static int _x_io_tcp_connect_ipv4(xine_stream_t *stream, const char *host, int p close(s); continue; } - + return s; } return -1; @@ -122,10 +122,10 @@ int _x_io_tcp_connect(xine_stream_t *stream, const char *host, int port) { struct addrinfo hints, *res, *tmpaddr; int error; char strport[16]; - + memset(&hints, 0, sizeof(hints)); hints.ai_socktype = SOCK_STREAM; - hints.ai_family = PF_UNSPEC; + hints.ai_family = PF_UNSPEC; snprintf(strport, sizeof(strport), "%d", port); @@ -135,7 +135,7 @@ int _x_io_tcp_connect(xine_stream_t *stream, const char *host, int port) { error = getaddrinfo(host, strport, &hints, &res); if (error) { - _x_message(stream, XINE_MSG_UNKNOWN_HOST, + _x_message(stream, XINE_MSG_UNKNOWN_HOST, "unable to resolve", host, NULL); return -1; } @@ -143,10 +143,10 @@ int _x_io_tcp_connect(xine_stream_t *stream, const char *host, int port) { tmpaddr = res; while (tmpaddr) { - - s = socket(tmpaddr->ai_family, SOCK_STREAM, IPPROTO_TCP); + + s = socket(tmpaddr->ai_family, SOCK_STREAM, IPPROTO_TCP); if (s == -1) { - _x_message(stream, XINE_MSG_CONNECTION_REFUSED, + _x_message(stream, XINE_MSG_CONNECTION_REFUSED, "failed to create socket", strerror(errno), NULL); tmpaddr = tmpaddr->ai_next; continue; @@ -177,12 +177,12 @@ int _x_io_tcp_connect(xine_stream_t *stream, const char *host, int port) { } #ifndef WIN32 - if (connect(s, tmpaddr->ai_addr, + if (connect(s, tmpaddr->ai_addr, tmpaddr->ai_addrlen)==-1 && errno != EINPROGRESS) { - + #else - if (connect(s, tmpaddr->ai_addr, - tmpaddr->ai_addrlen)==-1 && + if (connect(s, tmpaddr->ai_addr, + tmpaddr->ai_addrlen)==-1 && WSAGetLastError() != WSAEWOULDBLOCK) { if (stream) @@ -196,12 +196,12 @@ int _x_io_tcp_connect(xine_stream_t *stream, const char *host, int port) { } else { return s; } - + tmpaddr = tmpaddr->ai_next; } _x_message(stream, XINE_MSG_CONNECTION_REFUSED, strerror(error), NULL); - + return -1; #endif } @@ -302,14 +302,14 @@ int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) { */ int _x_io_tcp_connect_finish(xine_stream_t *stream, int fd, int timeout_msec) { int ret; - + ret = _x_io_select(stream, fd, XIO_WRITE_READY, timeout_msec); /* find out, if connection is successfull */ if (ret == XIO_READY) { socklen_t len = sizeof(int); int err; - + if ((getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &len)) == -1) { _x_message(stream, XINE_MSG_CONNECTION_REFUSED, _("failed to get status of socket"), strerror(errno), NULL); return XIO_ERROR; @@ -346,14 +346,14 @@ static off_t xio_rw_abort(xine_stream_t *stream, int fd, int cmd, char *buf, off } else { timeout = 30000; /* 30K msecs = 30 secs */ } - + while (total < todo) { sret = _x_io_select(stream, fd, state, timeout); - + if (sret != XIO_READY) return -1; - + switch (cmd) { case XIO_FILE_READ: ret = read(fd, &buf[total], todo - total); @@ -403,7 +403,7 @@ static off_t xio_rw_abort(xine_stream_t *stream, int fd, int cmd, char *buf, off if (stream) xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "io_helper: WSAGetLastError() = %d\n", WSAGetLastError()); #endif - + return ret; } total += ret; diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 71cb19d3b..9eb33f8ed 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2006 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -101,7 +101,7 @@ static const int plugin_iface_versions[] = { SPU_DECODER_IFACE_VERSION, AUDIO_OUT_IFACE_VERSION, VIDEO_OUT_DRIVER_IFACE_VERSION, - POST_PLUGIN_IFACE_VERSION + POST_PLUGIN_IFACE_VERSION }; static void _build_list_typed_plugins(plugin_catalog_t **catalog, xine_sarray_t *type) { @@ -112,7 +112,7 @@ static void _build_list_typed_plugins(plugin_catalog_t **catalog, xine_sarray_t list_size = xine_sarray_size (type); for (list_id = 0, i = 0; list_id < list_size; list_id++) { node = xine_sarray_get(type, list_id); - + /* add only unique ids to the list */ for ( j = 0; j < i; j++ ) { if( !strcmp((*catalog)->ids[j], node->info->id) ) @@ -157,9 +157,9 @@ static int get_decoder_priority(xine_t *this, plugin_node_t *node) { char key[80]; snprintf(key, sizeof(key), "engine.decoder_priorities.%s", node->info->id); - + entry = this->config->lookup_entry(this->config, key); - + if (entry && entry->num_value) /* user given priorities should definitely override defaults, so multiply them */ return entry->num_value * 100; @@ -258,14 +258,14 @@ static plugin_info_t *_get_cached_info (xine_t *this, node->file->filesize == filesize && node->file->filemtime == filemtime && !strcmp( node->file->filename, filename )) { - + return node->info; } - + /* skip previously returned items */ if( node->info == previous_info ) previous_info = NULL; - + } return NULL; } @@ -313,20 +313,19 @@ static void _insert_node (xine_t *this, const input_info_t *input_old; uint32_t *types; char key[80]; - char desc[100]; int i; _x_assert(list); _x_assert(info); if (info->API != api_version) { - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: ignoring plugin %s, wrong iface version %d (should be %d)\n"), info->id, info->API, api_version); return; } - entry = xine_xmalloc(sizeof(plugin_node_t)); - entry->info = xine_xmalloc(sizeof(plugin_info_t)); + entry = calloc(1, sizeof(plugin_node_t)); + entry->info = calloc(1, sizeof(plugin_info_t)); *(entry->info) = *info; entry->info->id = strdup(info->id); entry->info->init = info->init; @@ -339,7 +338,7 @@ static void _insert_node (xine_t *this, case PLUGIN_VIDEO_OUT: vo_old = info->special_info; - vo_new = xine_xmalloc(sizeof(vo_info_t)); + vo_new = calloc(1, sizeof(vo_info_t)); entry->priority = vo_new->priority = vo_old->priority; vo_new->visual_type = vo_old->visual_type; entry->info->special_info = vo_new; @@ -347,7 +346,7 @@ static void _insert_node (xine_t *this, case PLUGIN_AUDIO_OUT: ao_old = info->special_info; - ao_new = xine_xmalloc(sizeof(ao_info_t)); + ao_new = calloc(1, sizeof(ao_info_t)); entry->priority = ao_new->priority = ao_old->priority; entry->info->special_info = ao_new; break; @@ -356,7 +355,7 @@ static void _insert_node (xine_t *this, case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: decoder_old = info->special_info; - decoder_new = xine_xmalloc(sizeof(decoder_info_t)); + decoder_new = calloc(1, sizeof(decoder_info_t)); if (decoder_old == NULL) { if (file) xprintf (this, XINE_VERBOSITY_DEBUG, @@ -368,22 +367,21 @@ static void _insert_node (xine_t *this, info->id); _x_abort(); } - for (i=0; decoder_old->supported_types[i] != 0; ++i); - types = xine_xmalloc((i+1)*sizeof(uint32_t)); - for (i=0; decoder_old->supported_types[i] != 0; ++i){ - types[i] = decoder_old->supported_types[i]; + { + size_t supported_types_size; + for (supported_types_size=0; decoder_old->supported_types[supported_types_size] != 0; ++supported_types_size); + types = calloc((supported_types_size+1), sizeof(uint32_t)); + memcpy(types, decoder_old->supported_types, supported_types_size*sizeof(uint32_t)); + decoder_new->supported_types = types; } - decoder_new->supported_types = types; entry->priority = decoder_new->priority = decoder_old->priority; - + snprintf(key, sizeof(key), "engine.decoder_priorities.%s", info->id); - snprintf(desc, sizeof(desc), _("priority for %s decoder"), info->id); /* write the description on the heap because the config system * does not strdup() it, so we have to provide a different pointer * for each decoder */ for (i = 0; catalog->prio_desc[i]; i++); - catalog->prio_desc[i] = malloc(strlen(desc) + 1); - strcpy(catalog->prio_desc[i], desc); + asprintf(&catalog->prio_desc[i], _("priority for %s decoder"), info->id); this->config->register_num (this->config, key, 0, @@ -399,23 +397,23 @@ static void _insert_node (xine_t *this, entry->info->special_info = decoder_new; break; - + case PLUGIN_POST: post_old = info->special_info; - post_new = xine_xmalloc(sizeof(post_info_t)); + post_new = calloc(1, sizeof(post_info_t)); post_new->type = post_old->type; entry->info->special_info = post_new; break; - + case PLUGIN_DEMUX: demux_old = info->special_info; - demux_new = xine_xmalloc(sizeof(demuxer_info_t)); - + demux_new = calloc(1, sizeof(demuxer_info_t)); + if (demux_old) { entry->priority = demux_new->priority = demux_old->priority; lprintf("demux: %s, priority: %d\n", info->id, entry->priority); } else { - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: demuxer plugin %s does not provide a priority," " xine-lib will use the default priority.\n"), info->id); @@ -426,13 +424,13 @@ static void _insert_node (xine_t *this, case PLUGIN_INPUT: input_old = info->special_info; - input_new = xine_xmalloc(sizeof(input_info_t)); - + input_new = calloc(1, sizeof(input_info_t)); + if (input_old) { entry->priority = input_new->priority = input_old->priority; lprintf("input: %s, priority: %d\n", info->id, entry->priority); } else { - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: input plugin %s does not provide a priority," " xine-lib will use the default priority.\n"), info->id); @@ -463,12 +461,12 @@ static int _plugin_node_comparator(void *a, void *b) { } } -static plugin_catalog_t *_new_catalog(void){ +static plugin_catalog_t *XINE_MALLOC _new_catalog(void){ plugin_catalog_t *catalog; int i; - catalog = xine_xmalloc(sizeof(plugin_catalog_t)); + catalog = calloc(1, sizeof(plugin_catalog_t)); for (i = 0; i < PLUGIN_TYPE_MAX; i++) { catalog->plugin_lists[i] = xine_sarray_new(0, _plugin_node_comparator); @@ -487,13 +485,13 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin while ( info && info->type != PLUGIN_NONE ) { - if (file) + if (file && file->filename) xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: plugin %s found\n"), file->filename); else xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: static plugin found\n")); - + if (this->plugin_catalog->plugin_count >= PLUGIN_MAX || (this->plugin_catalog->decoder_count >= DECODER_MAX && info->type >= PLUGIN_AUDIO_DECODER && info->type <= PLUGIN_SPU_DECODER)) { @@ -527,7 +525,7 @@ static void _register_plugins_internal(xine_t *this, plugin_file_t *file, plugin } this->plugin_catalog->plugin_count++; } - + /* get next info */ if( file && !file->lib_handle ) { lprintf("get cached info\n"); @@ -556,25 +554,20 @@ static void collect_plugins(xine_t *this, char *path){ dir = opendir(path); if (dir) { struct dirent *pEntry; - size_t path_len, str_size; - char *str = NULL; - path_len = strlen(path); - str_size = path_len * 2 + 2; /* +2 for '/' and '\0' */ - str = malloc(str_size); - xine_fast_memcpy(str, path, path_len); - str[path_len] = '/'; - str[path_len + 1] = '\0'; + size_t path_len = strlen(path); + size_t str_size = path_len * 2 + 2; /* +2 for '/' and '\0' */ + char *str = malloc(str_size); + sprintf(str, "%s/", path); while ((pEntry = readdir (dir)) != NULL) { - size_t new_str_size, d_len; void *lib = NULL; plugin_info_t *info = NULL; - + struct stat statbuffer; - d_len = strlen(pEntry->d_name); - new_str_size = path_len + d_len + 2; + size_t d_len = strlen(pEntry->d_name); + size_t new_str_size = path_len + d_len + 2; if (str_size < new_str_size) { str_size = new_str_size + new_str_size / 2; str = realloc(str, str_size); @@ -599,7 +592,7 @@ static void collect_plugins(xine_t *this, char *path){ #if defined(__hpux) if(!strstr(str, ".sl") #elif defined(__CYGWIN__) || defined(WIN32) - if(!strstr(str, ".dll") + if(!strstr(str, ".dll") || strstr(str, ".dll.a") #else if(!strstr(str, ".so") #endif @@ -623,7 +616,7 @@ static void collect_plugins(xine_t *this, char *path){ if(!info && (lib = dlopen (str, RTLD_LAZY | RTLD_GLOBAL)) == NULL) { const char *error = dlerror(); /* too noisy -- but good to catch unresolved references */ - xprintf(this, XINE_VERBOSITY_LOG, + xprintf(this, XINE_VERBOSITY_LOG, _("load_plugins: cannot open plugin lib %s:\n%s\n"), str, error); } else { @@ -666,14 +659,14 @@ static void collect_plugins(xine_t *this, char *path){ * generic 2nd stage plugin loader */ -static inline int _plugin_info_equal(const plugin_info_t *a, +static inline int _plugin_info_equal(const plugin_info_t *a, const plugin_info_t *b) { - if (a->type != b->type || + if (a->type != b->type || a->API != b->API || strcasecmp(a->id, b->id) || a->version != b->version) return 0; - + switch (a->type & PLUGIN_TYPE_MASK) { case PLUGIN_VIDEO_OUT: /* FIXME: Could special_info be NULL? */ @@ -682,11 +675,11 @@ static inline int _plugin_info_equal(const plugin_info_t *a, ((vo_info_t*)b->special_info)->visual_type); } break; - + default: break; } - + return 1; } @@ -729,7 +722,7 @@ static int _load_plugin_class(xine_t *this, info++; } lprintf("plugin not found\n"); - + } else { xine_log (this, XINE_LOG_PLUGIN, _("load_plugins: Yikes! %s doesn't contain plugin info.\n"), filename); @@ -797,9 +790,9 @@ static void _load_required_plugins(xine_t *this, xine_sarray_t *list) { list_size = xine_sarray_size(list); while (list_id < list_size) { plugin_node_t *node = xine_sarray_get(list, list_id); - + if( (node->info->type & PLUGIN_MUST_PRELOAD) && !node->plugin_class ) { - + lprintf("preload plugin %s from %s\n", node->info->id, node->file->filename); if (! _load_plugin_class (this, node, NULL)) { @@ -838,7 +831,7 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { const vo_info_t *vo_info; const ao_info_t *ao_info; const post_info_t *post_info; - + int i; int list_id = 0; int list_size; @@ -855,20 +848,20 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { fprintf(fp, "api=%d\n", node->info->API ); fprintf(fp, "id=%s\n", node->info->id ); fprintf(fp, "version=%lu\n", (unsigned long) node->info->version ); - + switch (node->info->type & PLUGIN_TYPE_MASK){ - + case PLUGIN_VIDEO_OUT: vo_info = node->info->special_info; fprintf(fp, "visual_type=%d\n", vo_info->visual_type ); fprintf(fp, "vo_priority=%d\n", vo_info->priority ); break; - + case PLUGIN_AUDIO_OUT: ao_info = node->info->special_info; fprintf(fp, "ao_priority=%d\n", ao_info->priority ); break; - + case PLUGIN_AUDIO_DECODER: case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: @@ -885,7 +878,7 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { demuxer_info = node->info->special_info; fprintf(fp, "demuxer_priority=%d\n", demuxer_info->priority); break; - + case PLUGIN_INPUT: input_info = node->info->special_info; fprintf(fp, "input_priority=%d\n", input_info->priority); @@ -895,8 +888,8 @@ static void save_plugin_list(FILE *fp, xine_sarray_t *list) { post_info = node->info->special_info; fprintf(fp, "post_type=%lu\n", (unsigned long)post_info->type); break; - } - + } + fprintf(fp, "\n"); list_id++; } @@ -921,13 +914,13 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { char line[1024]; char *value; int version_ok = 0; - + node = NULL; file = NULL; while (fgets (line, 1023, fp)) { if (line[0] == '#') continue; - + if( (value = strchr(line, '\r')) || (value = strchr(line, '\n')) ) *value = (char) 0; /* eliminate any cr/lf */ @@ -941,11 +934,11 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( node ) { xine_sarray_add (plugins, node); } - node = xine_xmalloc(sizeof(plugin_node_t)); - file = xine_xmalloc(sizeof(plugin_file_t)); + node = calloc(1, sizeof(plugin_node_t)); + file = calloc(1, sizeof(plugin_file_t)); node->file = file; file->filename = strdup(line+1); - node->info = xine_xmalloc(2*sizeof(plugin_info_t)); + node->info = calloc(2, sizeof(plugin_info_t)); node->info[1].type = PLUGIN_NONE; decoder_info = NULL; vo_info = NULL; @@ -964,7 +957,7 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { if( i == CACHE_CATALOG_VERSION ) version_ok = 1; else - return; + return; } } else if (node) { if( !strcmp("size",line) ) { @@ -976,42 +969,42 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { } else if( !strcmp("type",line) ) { sscanf(value," %d",&i); node->info->type = i; - + switch (node->info->type & PLUGIN_TYPE_MASK){ - + case PLUGIN_VIDEO_OUT: node->info->special_info = vo_info = - xine_xmalloc(sizeof(vo_info_t)); + calloc(1, sizeof(vo_info_t)); break; - + case PLUGIN_AUDIO_OUT: node->info->special_info = ao_info = - xine_xmalloc(sizeof(ao_info_t)); + calloc(1, sizeof(ao_info_t)); break; - + case PLUGIN_DEMUX: node->info->special_info = demuxer_info = - xine_xmalloc(sizeof(demuxer_info_t)); + calloc(1, sizeof(demuxer_info_t)); break; case PLUGIN_INPUT: node->info->special_info = input_info = - xine_xmalloc(sizeof(input_info_t)); + calloc(1, sizeof(input_info_t)); break; case PLUGIN_AUDIO_DECODER: case PLUGIN_VIDEO_DECODER: case PLUGIN_SPU_DECODER: node->info->special_info = decoder_info = - xine_xmalloc(sizeof(decoder_info_t)); + calloc(1, sizeof(decoder_info_t)); break; - + case PLUGIN_POST: node->info->special_info = post_info = - xine_xmalloc(sizeof(post_info_t)); + calloc(1, sizeof(post_info_t)); break; - } - + } + } else if( !strcmp("api",line) ) { sscanf(value," %d",&i); node->info->API = i; @@ -1025,11 +1018,11 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { vo_info->visual_type = i; } else if( !strcmp("supported_types",line) && decoder_info ) { char *s; - + for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { s = strchr(s+1, ' '); } - decoder_info->supported_types = xine_xmalloc((i+1)*sizeof(uint32_t)); + decoder_info->supported_types = calloc((i+1), sizeof(uint32_t)); for( s = value, i = 0; s && sscanf(s," %lu",&lu) > 0; i++ ) { decoder_info->supported_types[i] = lu; s = strchr(s+1, ' '); @@ -1056,7 +1049,7 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { } } } - + if( node ) { xine_sarray_add (plugins, node); } @@ -1069,33 +1062,52 @@ static void load_plugin_list(FILE *fp, xine_sarray_t *plugins) { static void save_catalog (xine_t *this) { FILE *fp; - char *cachefile, *dirfile; + char *cachefile, *cachefile_new, *dirfile; const char *relname = CACHE_CATALOG_FILE; const char *dirname = CACHE_CATALOG_DIR; - - cachefile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(relname) + 2); - sprintf(cachefile, "%s/%s", xine_get_homedir(), relname); - + + const char *const homedir = xine_get_homedir(); + + asprintf(&cachefile, "%s/%s", homedir, relname); + asprintf(&cachefile_new, "%s.new", cachefile); + /* make sure homedir (~/.xine) exists */ - dirfile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(dirname) + 2); - sprintf(dirfile, "%s/%s", xine_get_homedir(), dirname); + asprintf(&dirfile, "%s/%s", homedir, dirname); mkdir (dirfile, 0755); free (dirfile); - if( (fp = fopen(cachefile,"w")) != NULL ) { + if( (fp = fopen(cachefile_new,"w")) != NULL ) { int i; - + fprintf(fp, "# this file is automatically created by xine, do not edit.\n\n"); fprintf(fp, "cache_catalog_version=%d\n\n", CACHE_CATALOG_VERSION); for (i = 0; i < PLUGIN_TYPE_MAX; i++) { save_plugin_list (fp, this->plugin_catalog->plugin_lists[i]); } - fclose(fp); + if (fclose(fp)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to save catalogue cache: %s\n"), err); + goto do_unlink; + } + else if (rename (cachefile_new, cachefile)) + { + const char *err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to replace catalogue cache: %s\n"), err); + do_unlink: + if (unlink (cachefile_new) && errno != ENOENT) + { + err = strerror (errno); + xine_log (this, XINE_LOG_MSG, + _("failed to remove new catalogue cache: %s\n"), err); + } + } } free(cachefile); + free(cachefile_new); } /* @@ -1104,13 +1116,11 @@ static void save_catalog (xine_t *this) { static void load_cached_catalog (xine_t *this) { FILE *fp; - char *cachefile; + char *cachefile; const char *relname = CACHE_CATALOG_FILE; - - cachefile = (char *) xine_xmalloc(strlen(xine_get_homedir()) + - strlen(relname) + 2); - sprintf(cachefile, "%s/%s", xine_get_homedir(), relname); - + + asprintf(&cachefile, "%s/%s", xine_get_homedir(), relname); + if( (fp = fopen(cachefile,"r")) != NULL ) { load_plugin_list (fp, this->plugin_catalog->cache_list); fclose(fp); @@ -1119,15 +1129,25 @@ static void load_cached_catalog (xine_t *this) { } +/* helper function for _x_scan_plugins */ +static void push_if_dir (xine_list_t *plugindirs, void *path) +{ + struct stat st; + if (!stat (path, &st) && S_ISDIR (st.st_mode)) + xine_list_push_back (plugindirs, path); + else + free (path); +} + /* * initialize catalog, load all plugins into new catalog */ void _x_scan_plugins (xine_t *this) { - - char *homedir, *plugindir, *pluginpath; - int i,j; - int lenpluginpath; - + + char *homedir, *pluginpath; + xine_list_t *plugindirs = xine_list_new (); + xine_list_iterator_t iter; + lprintf("_x_scan_plugins()\n"); if (this == NULL || this->config == NULL) { @@ -1140,45 +1160,49 @@ void _x_scan_plugins (xine_t *this) { this->plugin_catalog = _new_catalog(); load_cached_catalog (this); - if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL) { - pluginpath = strdup(pluginpath); + if ((pluginpath = getenv("XINE_PLUGIN_PATH")) != NULL && *pluginpath) { + char *p = pluginpath; + while (p && p[0]) + { + size_t len; + char *dir, *q; + + q = p; + p = strchr (p, XINE_PATH_SEPARATOR_CHAR); + if (p) { + p++; + len = p - q; + } else + len = strlen(q); + if (q[0] == '~' && q[1] == '/') + asprintf (&dir, "%s%.*s", homedir, (int)(len - 1), q + 1); + else + dir = strndup (q, len); + push_if_dir (plugindirs, dir); /* store or free it */ + } } else { - const char *str1, *str2; - int len; - - str1 = "~/.xine/plugins"; - str2 = XINE_PLUGINDIR; - len = strlen(str1) + strlen(str2) + 2; - pluginpath = xine_xmalloc(len); - snprintf(pluginpath, len, "%s" XINE_PATH_SEPARATOR_STRING "%s", str1, str2); - } - plugindir = xine_xmalloc(strlen(pluginpath)+strlen(homedir)+2); - j=0; - lenpluginpath = strlen(pluginpath); - for (i=0; i <= lenpluginpath; ++i){ - switch (pluginpath[i]){ - case XINE_PATH_SEPARATOR_CHAR: - case '\0': - plugindir[j] = '\0'; - collect_plugins(this, plugindir); - j = 0; - break; - case '~': - if (j == 0){ - strcpy(plugindir, homedir); - j = strlen(plugindir); - break; - } - default: - plugindir[j++] = pluginpath[i]; + char *dir; + int i; + asprintf (&dir, "%s/.xine/plugins", homedir); + push_if_dir (plugindirs, dir); + for (i = 0; i <= XINE_LT_AGE; ++i) + { + asprintf (&dir, "%s.%d", XINE_PLUGINROOT, XINE_LT_AGE - i); + push_if_dir (plugindirs, dir); } } - free(plugindir); - free(pluginpath); + for (iter = xine_list_front (plugindirs); iter; + iter = xine_list_next (plugindirs, iter)) + { + char *dir = xine_list_get_value (plugindirs, iter); + collect_plugins(this, dir); + free (dir); + } + xine_list_delete (plugindirs); free(homedir); save_catalog (this); - + load_required_plugins (this); map_decoders (this); @@ -1208,7 +1232,7 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) { plugin->node = node; break; } - } + } } pthread_mutex_unlock (&catalog->lock); @@ -1229,6 +1253,26 @@ void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) { } } +static int probe_mime_type (xine_t *self, plugin_node_t *node, const char *mime_type) +{ + /* catalog->lock is expected to be locked */ + if (node->plugin_class || _load_plugin_class(self, node, NULL)) + { + const unsigned int mime_type_len = strlen (mime_type); + demux_class_t *cls = (demux_class_t *)node->plugin_class; + const char *mime = cls->get_mimetypes (cls); + while (mime) + { + while (*mime == ';' || isspace (*mime)) + ++mime; + if (!strncasecmp (mime, mime_type, mime_type_len) && + (!mime[mime_type_len] || mime[mime_type_len] == ':' || mime[mime_type_len] == ';')) + return 1; + mime = strchr (mime, ';'); + } + } + return 0; +} static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int method2, input_plugin_t *input) { @@ -1251,8 +1295,6 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth while (methods[i] != -1 && !plugin) { int list_id, list_size; - stream->content_detection_method = methods[i]; - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size(catalog->plugin_lists[PLUGIN_DEMUX - 1]); @@ -1264,6 +1306,25 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: probing demux '%s'\n", node->info->id); if (node->plugin_class || _load_plugin_class(stream->xine, node, NULL)) { + const char *mime_type; + + /* If detecting by MRL, try the MIME type first (but not text/plain)... */ + stream->content_detection_method = METHOD_EXPLICIT; + if (methods[i] == METHOD_BY_EXTENSION && + stream->input_plugin->get_optional_data && + stream->input_plugin->get_optional_data (stream->input_plugin, NULL, INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + stream->input_plugin->get_optional_data (stream->input_plugin, &mime_type, INPUT_OPTIONAL_DATA_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + mime_type && strcasecmp (mime_type, "text/plain") && + probe_mime_type (stream->xine, node, mime_type) && + (plugin = ((demux_class_t *)node->plugin_class)->open_plugin (node->plugin_class, stream, input))) + { + inc_node_ref(node); + plugin->node = node; + break; + } + + /* ... then try the extension */ + stream->content_detection_method = methods[i]; if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { inc_node_ref(node); plugin->node = node; @@ -1377,7 +1438,7 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha if (strcasecmp(node->info->id, last_demux_name) == 0) { last_demux = node; } else { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugin: probing '%s' (method %d)...\n", node->info->id, stream->content_detection_method ); if (node->plugin_class || _load_plugin_class(xine, node, NULL)) { if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { @@ -1485,7 +1546,7 @@ const char *const *xine_get_browsable_input_plugin_ids(xine_t *this) { for (list_id = 0; list_id < list_size; list_id++) { input_class_t *ic; - + node = xine_sarray_get(catalog->plugin_lists[PLUGIN_INPUT - 1], list_id); if (node->plugin_class || _load_plugin_class(this, node, NULL)) { @@ -1544,7 +1605,7 @@ vo_driver_t *_x_load_video_output_plugin(xine_t *this, if (id && !strcasecmp(id, "auto")) id = NULL; - + pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); @@ -1592,7 +1653,7 @@ xine_video_port_t *xine_open_video_driver (xine_t *this, } port = _x_vo_new_port(this, driver, 0); - + return port; } @@ -1631,7 +1692,7 @@ xine_video_port_t *xine_new_framegrab_video_port (xine_t *this) { } port = _x_vo_new_port(this, driver, 1); - + return port; } @@ -1641,7 +1702,7 @@ xine_video_port_t *xine_new_framegrab_video_port (xine_t *this) { const char *const *xine_list_audio_output_plugins (xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_AUDIO_OUT - 1]); pthread_mutex_unlock (&catalog->lock); @@ -1651,7 +1712,7 @@ const char *const *xine_list_audio_output_plugins (xine_t *xine) { const char *const *xine_list_video_output_plugins (xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); pthread_mutex_unlock (&catalog->lock); @@ -1659,6 +1720,36 @@ const char *const *xine_list_video_output_plugins (xine_t *xine) { return catalog->ids; } +const char *const *xine_list_video_output_plugins_typed(xine_t *xine, uint64_t typemask) +{ + plugin_catalog_t *catalog = xine->plugin_catalog; + plugin_node_t *node; + int list_id, list_size, i; + + pthread_mutex_lock (&catalog->lock); + + list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); + + for (list_id = i = 0; list_id < list_size; list_id++) + { + node = xine_sarray_get (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1], list_id); + if (typemask & (1ULL << ((vo_info_t *)node->info->special_info)->visual_type)) + { + const char *id = node->info->id; + int j = i; + while (--j >= 0) + if (!strcmp (catalog->ids[j], id)) + goto ignore; /* already listed */ + catalog->ids[i++] = id; + } + ignore: ; + } + catalog->ids[i] = NULL; + + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; +} + static ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node, void *data) { @@ -1721,7 +1812,7 @@ xine_audio_port_t *xine_open_audio_driver (xine_t *this, const char *id, if (id && !strcasecmp(id, "auto") ) id = NULL; - + pthread_mutex_lock (&catalog->lock); driver = NULL; @@ -1747,13 +1838,13 @@ xine_audio_port_t *xine_open_audio_driver (xine_t *this, const char *id, } pthread_mutex_unlock (&catalog->lock); - + if (!driver) { if (id) xprintf (this, XINE_VERBOSITY_LOG, _("load_plugins: failed to load audio output plugin <%s>\n"), id); else - xprintf (this, XINE_VERBOSITY_LOG, + xprintf (this, XINE_VERBOSITY_LOG, _("load_plugins: audio output auto-probing didn't find any usable audio driver.\n")); return NULL; } @@ -1811,7 +1902,7 @@ char **xine_get_autoplay_mrls (xine_t *this, const char *plugin_id, if (node->plugin_class || _load_plugin_class (this, node, NULL)) { ic = (input_class_t *) node->plugin_class; - + if (!ic->get_autoplay_list) return NULL; @@ -1845,7 +1936,7 @@ xine_mrl_t **xine_get_browse_mrls (xine_t *this, const char *plugin_id, if (node->plugin_class || _load_plugin_class (this, node, NULL)) { ic = (input_class_t *) node->plugin_class; - + if (!ic->get_dir) return NULL; @@ -1877,7 +1968,7 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) { /* remove non working plugin from catalog */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: plugin %s failed to init its class.\n", node->info->id); for (j = i + 1; j < PLUGINS_PER_TYPE; j++) catalog->video_decoder_map[stream_type][j - 1] = @@ -1893,9 +1984,9 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ inc_node_ref(node); vd->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "load_plugins: plugin %s will be used for video streamtype %02x.\n", + "load_plugins: plugin %s will be used for video streamtype %02x.\n", node->info->id, stream_type); - + break; } else { /* remove non working plugin from catalog */ @@ -1948,7 +2039,7 @@ audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_typ if (!node->plugin_class && !_load_plugin_class (stream->xine, node, NULL)) { /* remove non working plugin from catalog */ - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: plugin %s failed to init its class.\n", node->info->id); for (j = i + 1; j < PLUGINS_PER_TYPE; j++) catalog->audio_decoder_map[stream_type][j - 1] = @@ -1964,7 +2055,7 @@ audio_decoder_t *_x_get_audio_decoder (xine_stream_t *stream, uint8_t stream_typ inc_node_ref(node); ad->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "load_plugins: plugin %s will be used for audio streamtype %02x.\n", + "load_plugins: plugin %s will be used for audio streamtype %02x.\n", node->info->id, stream_type); break; } else { @@ -2004,11 +2095,11 @@ int _x_decoder_available (xine_t *xine, uint32_t buftype) if ( (buftype & 0xFF000000) == BUF_VIDEO_BASE ) { if( catalog->video_decoder_map[stream_type][0] ) return 1; - } else + } else if ( (buftype & 0xFF000000) == BUF_AUDIO_BASE ) { if( catalog->audio_decoder_map[stream_type][0] ) return 1; - } else + } else if ( (buftype & 0xFF000000) == BUF_SPU_BASE ) { if( catalog->spu_decoder_map[stream_type][0] ) return 1; @@ -2035,7 +2126,7 @@ static void _display_file_plugin_list (xine_list_t *list, plugin_file_t *file) { #endif static void _unload_unref_plugins(xine_t *this, xine_sarray_t *list) { - + plugin_node_t *node; int list_id, list_size; @@ -2073,7 +2164,7 @@ void xine_plugins_garbage_collector(xine_t *self) { pthread_mutex_lock (&catalog->lock); for(i = 0; i < PLUGIN_TYPE_MAX; i++) { _unload_unref_plugins(self, self->plugin_catalog->plugin_lists[i]); - } + } #if 0 { @@ -2135,7 +2226,7 @@ spu_decoder_t *_x_get_spu_decoder (xine_stream_t *stream, uint8_t stream_type) { inc_node_ref(node); sd->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "load_plugins: plugin %s will be used for spu streamtype %02x.\n", + "load_plugins: plugin %s will be used for spu streamtype %02x.\n", node->info->id, stream_type); break; } else { @@ -2169,7 +2260,7 @@ void _x_free_spu_decoder (xine_stream_t *stream, spu_decoder_t *sd) { const char *const *xine_list_demuxer_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_DEMUX - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2179,7 +2270,7 @@ const char *const *xine_list_demuxer_plugins(xine_t *xine) { const char *const *xine_list_input_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_INPUT - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2189,7 +2280,7 @@ const char *const *xine_list_input_plugins(xine_t *xine) { const char *const *xine_list_spu_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_SPU_DECODER - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2199,7 +2290,7 @@ const char *const *xine_list_spu_plugins(xine_t *xine) { const char *const *xine_list_audio_decoder_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_AUDIO_DECODER - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2209,7 +2300,7 @@ const char *const *xine_list_audio_decoder_plugins(xine_t *xine) { const char *const *xine_list_video_decoder_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_VIDEO_DECODER - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2219,7 +2310,7 @@ const char *const *xine_list_video_decoder_plugins(xine_t *xine) { const char *const *xine_list_post_plugins(xine_t *xine) { plugin_catalog_t *catalog = xine->plugin_catalog; - + pthread_mutex_lock (&catalog->lock); _build_list_typed_plugins(&catalog, catalog->plugin_lists[PLUGIN_POST - 1]); pthread_mutex_unlock (&catalog->lock); @@ -2232,7 +2323,7 @@ const char *const *xine_list_post_plugins_typed(xine_t *xine, int type) { plugin_node_t *node; int i; int list_id, list_size; - + pthread_mutex_lock (&catalog->lock); i = 0; @@ -2287,25 +2378,25 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, plugin_node_t *node; post_plugin_t *post = NULL; int list_id, list_size; - + if( !name ) return NULL; - + pthread_mutex_lock(&catalog->lock); - + list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_POST - 1]); for (list_id = 0; list_id < list_size; list_id++) { node = xine_sarray_get (catalog->plugin_lists[PLUGIN_POST - 1], list_id); - + if (strcmp(node->info->id, name) == 0) { - + if (!node->plugin_class && !_load_plugin_class(xine, node, NULL)) { xprintf(xine, XINE_VERBOSITY_DEBUG, "load_plugins: requested post plugin %s failed to load\n", name); break; } - + post = ((post_class_t *)node->plugin_class)->open_plugin(node->plugin_class, inputs, audio_target, video_target); @@ -2314,12 +2405,12 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, xine_post_out_t *output; xine_list_iterator_t ite; int i; - + post->running_ticket = xine->port_ticket; post->xine = xine; post->node = node; inc_node_ref(node); - + /* init the lists of announced connections */ i = 0; ite = xine_list_front(post->input); @@ -2337,7 +2428,7 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, ite = xine_list_next (post->input, ite); } post->input_ids[i] = NULL; - + i = 0; ite = xine_list_front (post->output); while (ite) { @@ -2354,10 +2445,10 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, ite = xine_list_next (post->output, ite); } post->output_ids[i] = NULL; - + /* copy the post plugin type to the public part */ post->xine_post.type = ((post_info_t *)node->info->special_info)->type; - + break; } else { xprintf(xine, XINE_VERBOSITY_DEBUG, @@ -2366,9 +2457,9 @@ xine_post_t *xine_post_init(xine_t *xine, const char *name, int inputs, } } } - + pthread_mutex_unlock(&catalog->lock); - + if(post) return &post->xine_post; else { @@ -2384,73 +2475,67 @@ void xine_post_dispose(xine_t *xine, xine_post_t *post_gen) { * their disposal if they are still in use => post.c handles the counting for us */ } +/** + * @brief Concantenates an array of strings into a single + * string separated with a given string. + * + * @param strings Array of strings to concatenate. + * @param count Number of elements in the @p strings array. + * @param joining String to use to join the various strings together. + * @param final_length The pre-calculated final length of the string. + */ +static char *_x_concatenate_with_string(char const **strings, size_t count, char *joining, size_t final_length) { + size_t i; + char *const result = malloc(final_length+1); /* Better be safe */ + char *str = result; + + for(i = 0; i < count; i++, strings++) { + if ( *strings ) { + int offset = snprintf(str, final_length, "%s%s", *strings, joining); + str += offset; + final_length -= offset; + } + } + + return result; +} + /* get a list of file extensions for file types supported by xine - * the list is separated by spaces + * the list is separated by spaces * * the pointer returned can be free()ed when no longer used */ char *xine_get_file_extensions (xine_t *self) { plugin_catalog_t *catalog = self->plugin_catalog; - int len, pos; - plugin_node_t *node; - char *str; - int list_id, list_size; + int list_id; pthread_mutex_lock (&catalog->lock); - /* calc length of output */ + /* calc length of output string and create an array of strings to + concatenate */ + size_t len = 0; + const int list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + const char **extensions = calloc(list_size, sizeof(char*)); - len = 0; - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *exts; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); + plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - if((exts = cls->get_extensions(cls)) && *exts) - len += strlen(exts) + 1; + demux_class_t *const cls = (demux_class_t *)node->plugin_class; + if( (extensions[list_id] = cls->get_extensions(cls)) != NULL ) + len += strlen(extensions[list_id]) +1; } } - /* create output */ - str = malloc (len); /* '\0' space is already counted in the previous loop */ - pos = 0; + /* create output string */ + char *const result = _x_concatenate_with_string(extensions, list_size, " ", len); + free(extensions); - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); - for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *e; - int l; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { + /* Drop the last whitespace */ + result[len-1] = '\0'; - cls = (demux_class_t *)node->plugin_class; - - if((e = cls->get_extensions (cls)) && *e) { - l = strlen(e); - memcpy (&str[pos], e, l); - - pos += l; - - /* Don't add ' ' char at the end of str */ - if((pos + 1) < len) { - str[pos] = ' '; - pos++; - } - } - } - } - - str[pos] = 0; - pthread_mutex_unlock (&catalog->lock); - return str; + return result; } /* get a list of mime types supported by xine @@ -2459,65 +2544,34 @@ char *xine_get_file_extensions (xine_t *self) { char *xine_get_mime_types (xine_t *self) { plugin_catalog_t *catalog = self->plugin_catalog; - int len, pos; - plugin_node_t *node; - char *str; - int list_id, list_size; + int list_id; pthread_mutex_lock (&catalog->lock); /* calc length of output */ - len = 0; - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + /* calc length of output string and create an array of strings to + concatenate */ + size_t len = 0; + const int list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); + const char **mimetypes = calloc(list_size, sizeof(char*)); for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *s; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); + plugin_node_t *const node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - s = cls->get_mimetypes (cls); - if (s) - len += strlen(s); + demux_class_t *const cls = (demux_class_t *)node->plugin_class; + if( (mimetypes[list_id] = cls->get_mimetypes(cls)) != NULL ) + len += strlen(mimetypes[list_id]); } } - /* create output */ - - str = malloc (len+1); - pos = 0; - - list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); - - for (list_id = 0; list_id < list_size; list_id++) { - demux_class_t *cls; - const char *s; - int l; - - node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; + /* create output string */ + char *const result = _x_concatenate_with_string(mimetypes, list_size, "", len); + free(mimetypes); - s = cls->get_mimetypes (cls); - if (s) { - l = strlen(s); - memcpy (&str[pos], s, l); - - pos += l; - } - } - } - - str[pos] = 0; - pthread_mutex_unlock (&catalog->lock); - return str; + return result; } @@ -2530,47 +2584,24 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { plugin_catalog_t *catalog = self->plugin_catalog; plugin_node_t *node; char *id = NULL; - char *mime_arg, *mime_demux; - char *s; - const char *mt; int list_id, list_size; - /* create a copy and convert to lower case */ - mime_arg = strdup(mime_type); - for(s=mime_arg; *s; s++) - *s = tolower(*s); - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_DEMUX - 1]); for (list_id = 0; (list_id < list_size) && !id; list_id++) { - demux_class_t *cls; node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - cls = (demux_class_t *)node->plugin_class; - - mt = cls->get_mimetypes (cls); - if (mt) { - mime_demux = strdup(mt); - - for(s=mime_demux; *s; s++) - *s = tolower(*s); - - if( strstr(mime_demux, mime_arg) ) - id = strdup(node->info->id); - - free(mime_demux); - } + if (probe_mime_type (self, node, mime_type)) + { + free (id); + id = strdup(node->info->id); } } pthread_mutex_unlock (&catalog->lock); - free(mime_arg); - return id; } @@ -2582,7 +2613,7 @@ static void dispose_plugin_list (xine_sarray_t *list) { int list_id, list_size; if (list) { - + list_size = xine_sarray_size (list); for (list_id = 0; list_id < list_size; list_id++) { @@ -2603,12 +2634,12 @@ static void dispose_plugin_list (xine_sarray_t *list) { decoder_info = (decoder_info_t *)node->info->special_info; free (decoder_info->supported_types); - + default: free ((void *)node->info->special_info); break; } - + /* free info structure and string copies */ free (node->info->id); free (node->info); diff --git a/src/xine-engine/lrb.c b/src/xine-engine/lrb.c index 6da846a7c..89d4b2654 100644 --- a/src/xine-engine/lrb.c +++ b/src/xine-engine/lrb.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -29,8 +29,8 @@ lrb_t *lrb_new (int max_num_entries, fifo_buffer_t *fifo) { lrb_t *this; - - this = xine_xmalloc (sizeof (lrb_t)); + + this = calloc(1, sizeof(lrb_t)); this->max_num_entries = max_num_entries; this->cur_num_entries = 0; @@ -42,7 +42,7 @@ lrb_t *lrb_new (int max_num_entries, } void lrb_drop (lrb_t *this) { - + buf_element_t *buf = this->oldest; _x_assert(buf); @@ -67,7 +67,7 @@ void lrb_add (lrb_t *this, buf_element_t *buf) { } else { - if (this->cur_num_entries >= this->max_num_entries) + if (this->cur_num_entries >= this->max_num_entries) lrb_drop (this); buf->next = NULL; @@ -94,7 +94,7 @@ void lrb_feedback (lrb_t *this, fifo_buffer_t *fifo) { if (!fifo->last) fifo->last = buf; - + fifo->fifo_size++; pthread_cond_signal (&fifo->not_empty); @@ -114,6 +114,6 @@ void lrb_feedback (lrb_t *this, fifo_buffer_t *fifo) { } void lrb_flush (lrb_t *this) { - while (this->cur_num_entries) + while (this->cur_num_entries) lrb_drop (this); } diff --git a/src/xine-engine/lrb.h b/src/xine-engine/lrb.h index 491ae8843..f64e50eab 100644 --- a/src/xine-engine/lrb.h +++ b/src/xine-engine/lrb.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2001-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-engine/metronom.c b/src/xine-engine/metronom.c index 5d3e0a12d..8cd36f70f 100644 --- a/src/xine-engine/metronom.c +++ b/src/xine-engine/metronom.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -46,7 +46,7 @@ #define MAX_AUDIO_DELTA 1600 #define AUDIO_SAMPLE_NUM 32768 -#define WRAP_THRESHOLD 120000 +#define WRAP_THRESHOLD 120000 #define MAX_NUM_WRAP_DIFF 10 #define MAX_SCR_PROVIDERS 10 #define VIDEO_DRIFT_TOLERANCE 45000 @@ -63,7 +63,7 @@ /* * **************************************** - * primary SCR plugin: + * primary SCR plugin: * unix System Clock Reference * **************************************** */ @@ -88,19 +88,19 @@ static void unixscr_set_pivot (unixscr_t *this) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; xine_monotonic_clock(&tv, NULL); pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; -/* This next part introduces a one off inaccuracy - * to the scr due to rounding tv to pts. +/* This next part introduces a one off inaccuracy + * to the scr due to rounding tv to pts. */ this->cur_time.tv_sec=tv.tv_sec; this->cur_time.tv_usec=tv.tv_usec; - this->cur_pts=pts; + this->cur_pts=pts; return ; } @@ -141,7 +141,7 @@ static void unixscr_start (scr_plugin_t *scr, int64_t start_vpts) { this->cur_pts = start_vpts; pthread_mutex_unlock (&this->lock); - + unixscr_set_speed (&this->scr, XINE_FINE_SPEED_NORMAL); } @@ -150,16 +150,16 @@ static int64_t unixscr_get_current (scr_plugin_t *scr) { struct timeval tv; int64_t pts; - double pts_calc; + double pts_calc; pthread_mutex_lock (&this->lock); xine_monotonic_clock(&tv, NULL); - + pts_calc = (tv.tv_sec - this->cur_time.tv_sec) * this->speed_factor; pts_calc += (tv.tv_usec - this->cur_time.tv_usec) * this->speed_factor / 1e6; pts = this->cur_pts + pts_calc; - + pthread_mutex_unlock (&this->lock); return pts; @@ -172,12 +172,11 @@ static void unixscr_exit (scr_plugin_t *scr) { free(this); } -static scr_plugin_t* unixscr_init () { +static scr_plugin_t *XINE_MALLOC unixscr_init () { unixscr_t *this; - this = (unixscr_t *) xine_xmalloc(sizeof(unixscr_t)); - memset(this, 0, sizeof(*this)); - + this = calloc(1, sizeof(unixscr_t)); + this->scr.interface_version = 3; this->scr.get_priority = unixscr_get_priority; this->scr.set_fine_speed = unixscr_set_speed; @@ -185,15 +184,15 @@ static scr_plugin_t* unixscr_init () { this->scr.start = unixscr_start; this->scr.get_current = unixscr_get_current; this->scr.exit = unixscr_exit; - + pthread_mutex_init (&this->lock, NULL); - + unixscr_set_speed (&this->scr, XINE_SPEED_PAUSE); lprintf("xine-scr_init complete\n"); return &this->scr; } - + /* * **************************************** @@ -209,7 +208,7 @@ static void metronom_start_clock (metronom_clock_t *this, int64_t pts) { for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++) if (*scr) (*scr)->start(*scr, pts); - + this->speed = XINE_FINE_SPEED_NORMAL; } @@ -244,7 +243,7 @@ static int metronom_set_speed (metronom_clock_t *this, int speed) { int true_speed; true_speed = this->scr_master->set_fine_speed (this->scr_master, speed); - + this->speed = true_speed; for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++) @@ -268,33 +267,33 @@ static int64_t metronom_got_spu_packet (metronom_t *this, int64_t pts) { int64_t vpts; pthread_mutex_lock (&this->lock); - + if (this->master) { metronom_t *master = this->master; - + pthread_mutex_lock(&this->master->lock); pthread_mutex_unlock(&this->lock); - + this->vpts_offset = this->master->vpts_offset; this->spu_offset = this->master->spu_offset; - + /* no recursion, please */ this->master = NULL; vpts = master->got_spu_packet(this, pts); this->master = master; - + pthread_mutex_unlock(&this->master->lock); return vpts; } vpts = pts + this->vpts_offset + this->spu_offset; - + /* no vpts going backwards please */ if( vpts < this->spu_vpts ) vpts = this->spu_vpts; - + this->spu_vpts = vpts; - + pthread_mutex_unlock (&this->lock); return vpts; } @@ -388,18 +387,18 @@ static void metronom_handle_video_discontinuity (metronom_t *this, int type, pthread_mutex_unlock(&this->lock); return; } - + this->video_discontinuity_count++; pthread_cond_signal (&this->video_discontinuity_reached); - + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video discontinuity #%d, type is %d, disc_off %" PRId64 "\n", this->video_discontinuity_count, type, disc_off); - + if (this->have_audio) { while (this->audio_discontinuity_count < this->video_discontinuity_count) { - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "waiting for audio discontinuity #%d\n", + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "waiting for audio discontinuity #%d\n", this->video_discontinuity_count); pthread_cond_wait (&this->audio_discontinuity_reached, &this->lock); @@ -419,15 +418,15 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { int64_t vpts; int64_t pts = img->pts; int64_t diff; - + pthread_mutex_lock (&this->lock); if (this->master) { metronom_t *master = this->master; - + pthread_mutex_lock(&this->master->lock); pthread_mutex_unlock(&this->lock); - + if (!this->discontinuity_handled_count) { /* we are not initialized yet */ if (this->master->video_vpts > this->master->audio_vpts) @@ -440,15 +439,15 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { this->force_video_jump = 1; this->discontinuity_handled_count++; } - + this->vpts_offset = this->master->vpts_offset; this->av_offset = this->master->av_offset; - + /* no recursion, please */ this->master = NULL; master->got_video_frame(this, img); this->master = master; - + pthread_mutex_unlock(&this->master->lock); return; } @@ -479,23 +478,23 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { } this->img_cpt = 0; this->last_video_pts = pts; - - + + /* * compare predicted (this->video_vpts) and given (pts+vpts_offset) * pts values - hopefully they will be the same * if not, for small diffs try to interpolate * for big diffs: jump */ - + vpts = pts + this->vpts_offset; if (this->video_mode == VIDEO_PREDICTION_MODE) { - + diff = this->video_vpts - vpts; lprintf("video diff is %" PRId64 " (predicted %" PRId64 ", given %" PRId64 ")\n", diff, this->video_vpts, vpts); - + if ((abs (diff) > VIDEO_DRIFT_TOLERANCE) || (this->force_video_jump)) { this->force_video_jump = 0; @@ -509,7 +508,7 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { this->video_drift = diff; this->video_drift_step = diff / 30; /* this will fix video drift with a constant compensation each - frame for about 1 second of video. */ + frame for about 1 second of video. */ if (diff) lprintf("video drift, drift is %" PRId64 "\n", this->video_drift); } @@ -523,7 +522,7 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { if (this->video_mode == VIDEO_PREDICTION_MODE) { lprintf("video vpts for %10"PRId64" : %10"PRId64" (duration:%d drift:%" PRId64 " step:%" PRId64 ")\n", - pts, this->video_vpts, img->duration, this->video_drift, this->video_drift_step ); + pts, this->video_vpts, img->duration, this->video_drift, this->video_drift_step ); if (this->video_drift * this->video_drift_step > 0) { img->duration -= this->video_drift_step; @@ -536,7 +535,7 @@ static void metronom_got_video_frame (metronom_t *this, vo_frame_t *img) { * this->video_vpts is used as the next frame vpts if next frame pts=0 */ this->video_vpts += this->img_duration; - + pthread_mutex_unlock (&this->lock); } @@ -544,7 +543,7 @@ static void metronom_handle_audio_discontinuity (metronom_t *this, int type, int64_t disc_off) { pthread_mutex_lock (&this->lock); - + if (this->master) { /* slaves are currently not allowed to set discontinuities */ pthread_mutex_unlock(&this->lock); @@ -553,19 +552,19 @@ static void metronom_handle_audio_discontinuity (metronom_t *this, int type, this->audio_discontinuity_count++; pthread_cond_signal (&this->audio_discontinuity_reached); - + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio discontinuity #%d, type is %d, disc_off %" PRId64 "\n", this->audio_discontinuity_count, type, disc_off); if (this->have_video) { - + /* next_vpts_offset, in_discontinuity is handled in expect_video_discontinuity */ while ( this->audio_discontinuity_count > this->discontinuity_handled_count ) { - - xprintf(this->xine, XINE_VERBOSITY_DEBUG, "waiting for in_discontinuity update #%d\n", + + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "waiting for in_discontinuity update #%d\n", this->audio_discontinuity_count); - + pthread_cond_wait (&this->video_discontinuity_reached, &this->lock); } } else { @@ -574,11 +573,11 @@ static void metronom_handle_audio_discontinuity (metronom_t *this, int type, this->audio_samples = 0; this->audio_drift_step = 0; - + pthread_mutex_unlock (&this->lock); } -static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, +static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, int nsamples) { int64_t vpts; @@ -588,34 +587,34 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, lprintf("AUDIO pts from last= %" PRId64 "\n", pts-this->last_audio_pts); pthread_mutex_lock (&this->lock); - + if (this->master) { metronom_t *master = this->master; - + pthread_mutex_lock(&this->master->lock); pthread_mutex_unlock(&this->lock); - + if (!this->discontinuity_handled_count) { /* we are not initialized yet */ if (this->master->video_vpts > this->master->audio_vpts) this->video_vpts = this->audio_vpts = this->master->video_vpts; else this->video_vpts = this->audio_vpts = this->master->audio_vpts; - this->audio_vpts_rmndr = 0; + this->audio_vpts_rmndr = 0; /* when being attached to the first master, do not drift into * his vpts values but adopt at once */ this->force_audio_jump = 1; this->force_video_jump = 1; this->discontinuity_handled_count++; } - + this->vpts_offset = this->master->vpts_offset; - + /* no recursion, please */ this->master = NULL; vpts = master->got_audio_samples(this, pts, nsamples); this->master = master; - + pthread_mutex_unlock(&this->master->lock); return vpts; } @@ -629,7 +628,7 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, if((abs(diff) > AUDIO_DRIFT_TOLERANCE) || (this->force_audio_jump)) { this->force_audio_jump = 0; this->audio_vpts = vpts; - this->audio_vpts_rmndr = 0; + this->audio_vpts_rmndr = 0; this->audio_drift_step = 0; xprintf(this->xine, XINE_VERBOSITY_DEBUG, "audio jump, diff=%" PRId64 "\n", diff); } else { @@ -639,15 +638,15 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, diff *= AUDIO_SAMPLE_NUM; diff /= this->audio_samples * 4; - + /* drift_step is not allowed to change rate by more than 25% */ if( diff > this->pts_per_smpls/4 ) - diff = this->pts_per_smpls/4; + diff = this->pts_per_smpls/4; if( diff < -this->pts_per_smpls/4 ) diff = -this->pts_per_smpls/4; - + this->audio_drift_step = diff; - + lprintf("audio_drift = %" PRId64 ", pts_per_smpls = %" PRId64 "\n", diff, this->pts_per_smpls); } } @@ -655,12 +654,12 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, } vpts = this->audio_vpts; - /* drift here is caused by streams where nominal sample rate differs from + /* drift here is caused by streams where nominal sample rate differs from * the rate of which pts increments. fixing the audio_vpts won't do us any * good because sound card won't play it faster or slower just because * we want. however, adding the error to the vpts_offset will force video * to change it's frame rate to keep in sync with us. - * + * * Since we are using integer division below, it can happen that we lose * precision for the calculated duration in vpts for each audio buffer * (< 1 PTS, e.g. 0.25 PTS during playback of most DVDs with LPCM audio). @@ -678,7 +677,7 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, } this->audio_samples += nsamples; this->vpts_offset += nsamples * this->audio_drift_step / AUDIO_SAMPLE_NUM; - + lprintf("audio vpts for %10"PRId64" : %10"PRId64"\n", pts, vpts); pthread_mutex_unlock (&this->lock); @@ -689,7 +688,7 @@ static int64_t metronom_got_audio_samples (metronom_t *this, int64_t pts, static void metronom_set_option (metronom_t *this, int option, int64_t value) { pthread_mutex_lock (&this->lock); - + if (this->master) { /* pass the option on to the master */ this->master->set_option(this->master, option, value); @@ -745,7 +744,7 @@ static void metronom_clock_set_option (metronom_clock_t *this, } static int64_t metronom_get_option (metronom_t *this, int option) { - + if (this->master) return this->master->get_option(this->master, option); @@ -776,7 +775,7 @@ static int64_t metronom_clock_get_option (metronom_clock_t *this, int option) { static void metronom_set_master(metronom_t *this, metronom_t *master) { metronom_t *old_master = this->master; - + pthread_mutex_lock(&this->lock); /* someone might currently be copying values from the old master, * so we need his lock too */ @@ -794,7 +793,7 @@ static scr_plugin_t* get_master_scr(metronom_clock_t *this) { /* find the SCR provider with the highest priority */ for (i=0; i<MAX_SCR_PROVIDERS; i++) if (this->scr_list[i]) { scr_plugin_t *scr = this->scr_list[i]; - + if (maxprio < scr->get_priority(scr)) { select = i; maxprio = scr->get_priority(scr); @@ -811,7 +810,7 @@ static int metronom_register_scr (metronom_clock_t *this, scr_plugin_t *scr) { int i; if (scr->interface_version != 3) { - xprintf(this->xine, XINE_VERBOSITY_NONE, + xprintf(this->xine, XINE_VERBOSITY_NONE, "wrong interface version for scr provider!\n"); return -1; } @@ -833,19 +832,19 @@ static void metronom_unregister_scr (metronom_clock_t *this, scr_plugin_t *scr) /* never unregister scr_list[0]! */ for (i=1; i<MAX_SCR_PROVIDERS; i++) - if (this->scr_list[i] == scr) + if (this->scr_list[i] == scr) break; if (i >= MAX_SCR_PROVIDERS) return; /* Not found */ - + this->scr_list[i] = NULL; time = this->get_current_time(this); - + /* master could have been adjusted, others must follow now */ for (i=0; i<MAX_SCR_PROVIDERS; i++) if (this->scr_list[i]) this->scr_list[i]->adjust(this->scr_list[i], time); - + this->scr_master = get_master_scr(this); } @@ -855,13 +854,13 @@ static int metronom_sync_loop (metronom_clock_t *this) { struct timespec ts; scr_plugin_t** scr; int64_t pts; - + while (this->thread_running) { /* synchronise every 5 seconds */ pthread_mutex_lock (&this->lock); pts = this->scr_master->get_current(this->scr_master); - + for (scr = this->scr_list; scr < this->scr_list+MAX_SCR_PROVIDERS; scr++) if (*scr && *scr != this->scr_master) (*scr)->adjust(*scr, pts); @@ -889,7 +888,7 @@ static void metronom_clock_exit (metronom_clock_t *this) { scr_plugin_t** scr; this->thread_running = 0; - + pthread_mutex_lock (&this->lock); pthread_cond_signal (&this->cancel); pthread_mutex_unlock (&this->lock); @@ -909,7 +908,7 @@ static void metronom_clock_exit (metronom_clock_t *this) { metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { - metronom_t *this = xine_xmalloc (sizeof (metronom_t)); + metronom_t *this = calloc(1, sizeof (metronom_t)); this->set_audio_rate = metronom_set_audio_rate; this->got_video_frame = metronom_got_video_frame; @@ -924,7 +923,7 @@ metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { this->xine = xine; this->master = NULL; - + pthread_mutex_init (&this->lock, NULL); this->prebuffer = PREBUFFER_PTS_OFFSET; @@ -933,7 +932,7 @@ metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { this->vpts_offset = 0; /* initialize video stuff */ - + this->video_vpts = this->prebuffer; this->video_drift = 0; this->video_drift_step = 0; @@ -944,8 +943,8 @@ metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { this->img_cpt = 0; this->last_video_pts = 0; this->last_audio_pts = 0; - - + + /* initialize audio stuff */ this->have_video = have_video; @@ -954,7 +953,7 @@ metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { this->audio_vpts_rmndr = 0; this->audio_discontinuity_count = 0; pthread_cond_init (&this->audio_discontinuity_reached, NULL); - + return this; } @@ -962,9 +961,9 @@ metronom_t * _x_metronom_init (int have_video, int have_audio, xine_t *xine) { metronom_clock_t *_x_metronom_clock_init(xine_t *xine) { - metronom_clock_t *this = (metronom_clock_t *) xine_xmalloc(sizeof(metronom_clock_t)); + metronom_clock_t *this = calloc(1, sizeof(metronom_clock_t)); int err; - + this->set_option = metronom_clock_set_option; this->get_option = metronom_clock_get_option; this->start_clock = metronom_start_clock; @@ -976,19 +975,19 @@ metronom_clock_t *_x_metronom_clock_init(xine_t *xine) this->register_scr = metronom_register_scr; this->unregister_scr = metronom_unregister_scr; this->exit = metronom_clock_exit; - + this->xine = xine; this->scr_adjustable = 1; this->scr_list = calloc(MAX_SCR_PROVIDERS, sizeof(void*)); this->register_scr(this, unixscr_init()); - + pthread_mutex_init (&this->lock, NULL); pthread_cond_init (&this->cancel, NULL); - + this->thread_running = 1; if ((err = pthread_create(&this->sync_thread, NULL, - (void*(*)(void*)) metronom_sync_loop, this)) != 0) + (void*(*)(void*)) metronom_sync_loop, this)) != 0) xprintf(this->xine, XINE_VERBOSITY_NONE, "cannot create sync thread (%s)\n", strerror(err)); diff --git a/src/xine-engine/metronom.h b/src/xine-engine/metronom.h index 20e31117c..946aa0991 100644 --- a/src/xine-engine/metronom.h +++ b/src/xine-engine/metronom.h @@ -1,30 +1,30 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * metronom: general pts => virtual calculation/assoc - * + * * virtual pts: unit 1/90000 sec, always increasing * can be used for synchronization * video/audio frame with same pts also have same vpts * but pts is likely to differ from vpts * - * the basic idea is: + * the basic idea is: * video_pts + video_wrap_offset = video_vpts * audio_pts + audio_wrap_offset = audio_vpts * @@ -67,8 +67,8 @@ typedef struct scr_plugin_s scr_plugin_t; #define PREBUFFER_PTS_OFFSET 12000 /* see below */ -#define DISC_STREAMSTART 0 -#define DISC_RELATIVE 1 +#define DISC_STREAMSTART 0 +#define DISC_RELATIVE 1 #define DISC_ABSOLUTE 2 #define DISC_STREAMSEEK 3 @@ -91,9 +91,9 @@ struct metronom_s { * * this function will also update video_wrap_offset if a discontinuity * is detected (read the comentaries below about discontinuities). - * + * */ - + void (*got_video_frame) (metronom_t *self, vo_frame_t *frame); /* @@ -109,8 +109,8 @@ struct metronom_s { * */ - int64_t (*got_audio_samples) (metronom_t *self, int64_t pts, - int nsamples); + int64_t (*got_audio_samples) (metronom_t *self, int64_t pts, + int nsamples); /* * called by SPU decoder whenever a packet is delivered to it @@ -134,7 +134,7 @@ struct metronom_s { * * DISC_STREAMSTART : new stream starts, expect pts values to start * from zero immediately - * DISC_RELATIVE : typically a wrap-around, expect pts with + * DISC_RELATIVE : typically a wrap-around, expect pts with * a specified offset from the former ones soon * DISC_ABSOLUTE : typically a new menu stream (nav packets) * pts will start from given value soon @@ -152,7 +152,7 @@ struct metronom_s { */ void (*set_option) (metronom_t *self, int option, int64_t value); int64_t (*get_option) (metronom_t *self, int option); - + /* * set a master metronom * this is currently useful to sync independently generated streams @@ -160,7 +160,7 @@ struct metronom_s { * metronom */ void (*set_master) (metronom_t *self, metronom_t *master); - + void (*exit) (metronom_t *self); #ifdef METRONOM_INTERNAL @@ -168,7 +168,7 @@ struct metronom_s { * metronom internal stuff */ xine_t *xine; - + metronom_t *master; int64_t pts_per_smpls; @@ -182,7 +182,7 @@ struct metronom_s { int64_t video_drift; int64_t video_drift_step; - + int audio_samples; int64_t audio_drift_step; @@ -223,7 +223,7 @@ struct metronom_s { #define METRONOM_VPTS_OFFSET 6 #define METRONOM_PREBUFFER 7 -metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_PROTECTED; +metronom_t *_x_metronom_init (int have_video, int have_audio, xine_t *xine) XINE_MALLOC XINE_PROTECTED; /* FIXME: reorder this structure on the next cleanup to remove the dummies */ struct metronom_clock_s { @@ -293,9 +293,9 @@ struct metronom_clock_s { #ifdef METRONOM_CLOCK_INTERNAL void (*exit) (metronom_clock_t *self); - + xine_t *xine; - + scr_plugin_t *scr_master; scr_plugin_t **scr_list; pthread_t sync_thread; @@ -310,7 +310,7 @@ struct metronom_clock_s { int dummy10; int dummy11; #endif - + int speed; #ifdef METRONOM_CLOCK_INTERNAL @@ -319,7 +319,7 @@ struct metronom_clock_s { #endif }; -metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_PROTECTED; +metronom_clock_t *_x_metronom_clock_init(xine_t *xine) XINE_MALLOC XINE_PROTECTED; /* * clock options @@ -337,8 +337,8 @@ struct scr_plugin_s int (*get_priority) (scr_plugin_t *self); - /* - * set/get clock speed + /* + * set/get clock speed * * for speed constants see xine_internal.h * returns actual speed diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index ef888e7a4..94fc969bd 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -83,17 +83,6 @@ # define UCS2_ENCODING "UCS-2LE" #endif -#ifdef MAX -#undef MAX -#endif -#define MAX(a,b) ( (a) > (b) ) ? (a) : (b) - -#ifdef MIN -#undef MIN -#endif -#define MIN(a,b) ( (a) < (b) ) ? (a) : (b) - - #if (FREETYPE_MAJOR > 2) || \ (FREETYPE_MAJOR == 2 && FREETYPE_MINOR > 1) || \ (FREETYPE_MAJOR == 2 && FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 3) @@ -124,7 +113,7 @@ struct osd_font_s { uint16_t size; uint16_t num_fontchars; uint16_t loaded; -}; +}; #ifdef HAVE_FT2 struct osd_ft2context_s { @@ -132,6 +121,20 @@ struct osd_ft2context_s { FT_Face face; int size; }; + +static void osd_free_ft2 (osd_object_t *osd) +{ + if( osd->ft2 ) { + if ( osd->ft2->face ) + FT_Done_Face (osd->ft2->face); + if ( osd->ft2->library ) + FT_Done_FreeType(osd->ft2->library); + free( osd->ft2 ); + osd->ft2 = NULL; + } +} +#else +static inline void osd_free_ft2 (osd_object_t *osd __attr_unused) {} #endif /* @@ -143,28 +146,28 @@ struct osd_ft2context_s { * for the sake of simplicity) */ -static osd_object_t *osd_new_object (osd_renderer_t *this, int width, int height) { - +static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width, int height) { + osd_object_t *osd; - - pthread_mutex_lock (&this->osd_mutex); - - osd = xine_xmalloc( sizeof(osd_object_t) ); + + pthread_mutex_lock (&this->osd_mutex); + + osd = calloc(1, sizeof(osd_object_t)); osd->renderer = this; osd->next = this->osds; this->osds = osd; - + osd->width = width; osd->height = height; - osd->area = xine_xmalloc( width * height ); - + osd->area = calloc(width, height); + osd->x1 = width; osd->y1 = height; osd->x2 = 0; osd->y2 = 0; - memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0])); - memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0])); + memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0])); + memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0])); osd->handle = -1; @@ -172,11 +175,11 @@ static osd_object_t *osd_new_object (osd_renderer_t *this, int width, int height osd->cd = (iconv_t)-1; osd->encoding = NULL; #endif - - pthread_mutex_unlock (&this->osd_mutex); + + pthread_mutex_unlock (&this->osd_mutex); lprintf("osd=%p size: %dx%d\n", osd, width, height); - + return osd; } @@ -193,7 +196,7 @@ static int _osd_hide (osd_object_t *osd, int64_t vpts); * the object is not changed. there may be subsequent drawing on it. */ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { - + osd_renderer_t *this = osd->renderer; video_overlay_manager_t *ovl_manager; rle_elem_t rle, *rle_p=0; @@ -201,21 +204,21 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { uint8_t *c; lprintf("osd=%p vpts=%"PRId64"\n", osd, vpts); - + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); - + ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); - + if( osd->handle < 0 ) { if( (osd->handle = ovl_manager->get_handle(ovl_manager, 0)) == -1 ) { this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); return 0; } } - - pthread_mutex_lock (&this->osd_mutex); - - /* clip update area to allowed range */ + + pthread_mutex_lock (&this->osd_mutex); + + /* clip update area to allowed range */ if(osd->x1 > osd->width) osd->x1 = osd->width; if(osd->x2 > osd->width) @@ -229,13 +232,13 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { if(osd->y1 < 0) osd->y1 = 0; if(osd->y2 < 0) osd->y2 = 0; -#ifdef DEBUG_RLE +#ifdef DEBUG_RLE lprintf("osd_show %p rle starts\n", osd); -#endif +#endif /* check if osd is valid (something drawn on it) */ if( osd->x2 > osd->x1 && osd->y2 > osd->y1 ) { - + this->event.object.handle = osd->handle; memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) ); @@ -244,25 +247,25 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.object.overlay->y = osd->display_y + osd->y1; this->event.object.overlay->width = osd->x2 - osd->x1; this->event.object.overlay->height = osd->y2 - osd->y1; - + this->event.object.overlay->hili_top = 0; this->event.object.overlay->hili_bottom = this->event.object.overlay->height; this->event.object.overlay->hili_left = 0; this->event.object.overlay->hili_right = this->event.object.overlay->width; - + /* there will be at least that many rle objects (one for each row) */ this->event.object.overlay->num_rle = 0; /* We will never need more rle objects than columns in any row Rely on lazy page allocation to avoid us actually taking up this much RAM */ this->event.object.overlay->data_size = osd->width * osd->height; - rle_p = this->event.object.overlay->rle = + rle_p = this->event.object.overlay->rle = malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); - + for( y = osd->y1; y < osd->y2; y++ ) { -#ifdef DEBUG_RLE +#ifdef DEBUG_RLE lprintf("osd_show %p y = %d: ", osd, y); -#endif +#endif c = osd->area + y * osd->width + osd->x1; /* initialize a rle object with the first pixel's color */ @@ -272,17 +275,17 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { /* loop over the remaining pixels in the row */ for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { if( rle.color != *c ) { -#ifdef DEBUG_RLE +#ifdef DEBUG_RLE lprintf("(%d, %d), ", rle.len, rle.color); #endif *rle_p++ = rle; - this->event.object.overlay->num_rle++; + this->event.object.overlay->num_rle++; rle.color = *c; rle.len = 1; } else { rle.len++; - } + } } #ifdef DEBUG_RLE lprintf("(%d, %d)\n", rle.len, rle.color); @@ -294,12 +297,12 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { lprintf("osd_show %p rle ends\n", osd); #endif lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); - - memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); - memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); - memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); - memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); - + + memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); + memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); + memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); + memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); + this->event.event_type = OVERLAY_EVENT_SHOW; this->event.vpts = vpts; ovl_manager->add_event(ovl_manager, (void *)&this->event); @@ -307,10 +310,10 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { /* osd empty - hide it */ _osd_hide(osd, vpts); } - pthread_mutex_unlock (&this->osd_mutex); - + pthread_mutex_unlock (&this->osd_mutex); + this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); - + return 1; } @@ -332,24 +335,24 @@ static int osd_show_unscaled (osd_object_t *osd, int64_t vpts) { * send event to hide osd at given pts (0=now) * the object is not changed. there may be subsequent drawing on it. */ -static int _osd_hide (osd_object_t *osd, int64_t vpts) { +static int _osd_hide (osd_object_t *osd, int64_t vpts) { osd_renderer_t *this = osd->renderer; video_overlay_manager_t *ovl_manager; - + lprintf("osd=%p vpts=%"PRId64"\n",osd, vpts); - + if( osd->handle < 0 ) return 0; - + this->event.object.handle = osd->handle; - + /* not really needed this, but good pratice to clean it up */ memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) ); - + this->event.event_type = OVERLAY_EVENT_HIDE; this->event.vpts = vpts; - + ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); ovl_manager->add_event(ovl_manager, (void *)&this->event); @@ -395,14 +398,14 @@ static void osd_clear (osd_object_t *osd) { static void osd_point (osd_object_t *osd, int x, int y, int color) { uint8_t *c; - + lprintf("osd=%p (%d x %d)\n", osd, x, y); - + if (x < 0 || x >= osd->width) return; if (y < 0 || y >= osd->height) return; - + /* update clipping area */ osd->x1 = MIN(osd->x1, x); osd->x2 = MAX(osd->x2, (x + 1)); @@ -419,14 +422,14 @@ static void osd_point (osd_object_t *osd, int x, int y, int color) { static void osd_line (osd_object_t *osd, int x1, int y1, int x2, int y2, int color) { - + uint8_t *c; int dx, dy, t, inc, d, inc1, inc2; int swap_x = 0; int swap_y = 0; lprintf("osd=%p (%d,%d)-(%d,%d)\n",osd, x1,y1, x2,y2 ); - + /* sort line */ if (x2 < x1) { t = x1; @@ -441,7 +444,7 @@ static void osd_line (osd_object_t *osd, swap_y = 1; } - /* clip line */ + /* clip line */ if (x1 < 0) { y1 = y1 + (y2-y1) * -x1 / (x2-x1); x1 = 0; @@ -458,19 +461,19 @@ static void osd_line (osd_object_t *osd, x2 = x1 + (x2-x1) * (osd->height-y1) / (y2-y1); y2 = osd->height; } - + if (x1 >= osd->width || y1 >= osd->height) return; - + /* update clipping area */ osd->x1 = MIN( osd->x1, x1 ); osd->x2 = MAX( osd->x2, x2 ); osd->y1 = MIN( osd->y1, y1 ); osd->y2 = MAX( osd->y2, y2 ); - + dx = x2 - x1; dy = y2 - y1; - + /* unsort line */ if (swap_x) { t = x1; @@ -489,7 +492,7 @@ static void osd_line (osd_object_t *osd, t = x2; x2 = x1; x1 = t; t = y2; y2 = y1; y1 = t; } - + if( y2 > y1 ) inc = 1; else inc = -1; inc1 = 2*dy; @@ -497,11 +500,11 @@ static void osd_line (osd_object_t *osd, inc2 = 2*(dy-dx); c = osd->area + y1 * osd->width + x1; - + while(x1<x2) { *c++ = color; - + x1++; if( d<0 ) { d+=inc1; @@ -526,8 +529,8 @@ static void osd_line (osd_object_t *osd, c = osd->area + y1 * osd->width + x1; while(y1<y2) { - *c = color; - + *c = color; + c += osd->width; y1++; if( d<0 ) { @@ -552,17 +555,17 @@ static void osd_filled_rect (osd_object_t *osd, int x, y, dx, dy; lprintf("osd=%p (%d,%d)-(%d,%d)\n",osd, x1,y1, x2,y2 ); - + /* sort rectangle */ x = MIN( x1, x2 ); dx = MAX( x1, x2 ); y = MIN( y1, y2 ); dy = MAX( y1, y2 ); - + /* clip rectangle */ if (x >= osd->width || y >= osd->height) return; - + if (x < 0) { dx += x; x = 0; @@ -574,7 +577,7 @@ static void osd_filled_rect (osd_object_t *osd, dx = MIN( dx, osd->width ); dy = MIN( dy, osd->height ); - + /* update clipping area */ osd->x1 = MIN( osd->x1, x ); osd->x2 = MAX( osd->x2, dx ); @@ -600,7 +603,7 @@ static void osd_set_palette(osd_object_t *osd, const uint32_t *color, const uint } /* - * set on existing text palette + * set on existing text palette * (-1 to set user specified palette) */ @@ -619,7 +622,7 @@ static void osd_set_text_palette(osd_object_t *osd, int palette_number, memcpy(&osd->color[color_base], textpalettes_color[palette_number], sizeof(textpalettes_color[palette_number])); memcpy(&osd->trans[color_base], textpalettes_trans[palette_number], - sizeof(textpalettes_trans[palette_number])); + sizeof(textpalettes_trans[palette_number])); } @@ -655,7 +658,7 @@ static uint16_t gzread_i16(gzFile *fp) { } /* - load bitmap font into osd engine + load bitmap font into osd engine */ static int osd_renderer_load_font(osd_renderer_t *this, char *filename) { @@ -663,47 +666,47 @@ static int osd_renderer_load_font(osd_renderer_t *this, char *filename) { gzFile *fp; osd_font_t *font = NULL; int i, ret = 0; - + lprintf("name=%s\n", filename ); /* load quick & dirt font format */ /* fixme: check for all read errors... */ if( (fp = gzopen(filename,"rb")) != NULL ) { - font = xine_xmalloc( sizeof(osd_font_t) ); + font = calloc(1, sizeof(osd_font_t)); gzread(fp, font->name, sizeof(font->name) ); font->version = gzread_i16(fp); - + if( font->version == FONT_VERSION ) { - + font->size = gzread_i16(fp); font->num_fontchars = gzread_i16(fp); font->loaded = 1; - + font->fontchar = malloc( sizeof(osd_fontchar_t) * font->num_fontchars ); - + lprintf("font '%s' chars=%d\n", font->name, font->num_fontchars); - + /* load all characters */ for( i = 0; i < font->num_fontchars; i++ ) { font->fontchar[i].code = gzread_i16(fp); font->fontchar[i].width = gzread_i16(fp); font->fontchar[i].height = gzread_i16(fp); font->fontchar[i].bmp = malloc(font->fontchar[i].width*font->fontchar[i].height); - if( gzread(fp, font->fontchar[i].bmp, + if( gzread(fp, font->fontchar[i].bmp, font->fontchar[i].width*font->fontchar[i].height) <= 0 ) break; } - + /* check if all expected characters were loaded */ if( i == font->num_fontchars ) { osd_font_t *known_font; ret = 1; - + lprintf("font '%s' loaded\n",font->name); - - /* check if font is already known to us */ + + /* check if font is already known to us */ known_font = this->fonts; while( known_font ) { if( !strcasecmp(known_font->name,font->name) && @@ -711,16 +714,16 @@ static int osd_renderer_load_font(osd_renderer_t *this, char *filename) { break; known_font = known_font->next; } - + if( !known_font ) { - + /* new font, add it to list */ font->filename = strdup(filename); font->next = this->fonts; this->fonts = font; - + } else { - + if( !known_font->loaded ) { /* the font was preloaded before. * add loaded characters to the existing entry. @@ -731,7 +734,7 @@ static int osd_renderer_load_font(osd_renderer_t *this, char *filename) { known_font->fontchar = font->fontchar; free(font); } else { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("font '%s-%d' already loaded, weird.\n"), font->name, font->size); while( --i >= 0 ) { free(font->fontchar[i].bmp); @@ -739,13 +742,13 @@ static int osd_renderer_load_font(osd_renderer_t *this, char *filename) { free(font->fontchar); free(font); } - + } } else { - + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("font '%s' loading failed (%d < %d)\n") ,font->name, i, font->num_fontchars); - + while( --i >= 0 ) { free(font->fontchar[i].bmp); } @@ -771,13 +774,13 @@ static int osd_renderer_unload_font(osd_renderer_t *this, char *fontname ) { osd_font_t *font, *last; osd_object_t *osd; int i, ret = 0; - + lprintf("font '%s'\n", fontname); pthread_mutex_lock (&this->osd_mutex); osd = this->osds; - while( osd ) { + while( osd ) { if( !strcasecmp(osd->font->name, fontname) ) osd->font = NULL; osd = osd->next; @@ -789,14 +792,14 @@ static int osd_renderer_unload_font(osd_renderer_t *this, char *fontname ) { if ( !strcasecmp(font->name,fontname) ) { free( font->filename ); - + if( font->loaded ) { for( i = 0; i < font->num_fontchars; i++ ) { free( font->fontchar[i].bmp ); } free( font->fontchar ); } - + if( last ) last->next = font->next; else @@ -818,7 +821,7 @@ static int osd_renderer_unload_font(osd_renderer_t *this, char *fontname ) { #ifdef HAVE_FT2 static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int size ) { if (!osd->ft2) { - osd->ft2 = xine_xmalloc(sizeof(osd_ft2context_t)); + osd->ft2 = calloc(1, sizeof(osd_ft2context_t)); if(FT_Init_FreeType( &osd->ft2->library )) { xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: cannot initialize ft2 library\n")); @@ -827,7 +830,12 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int return 0; } } - + + if (osd->ft2->face) { + FT_Done_Face (osd->ft2->face); + osd->ft2->face = NULL; + } + #ifdef HAVE_FONTCONFIG do { FcPattern *pat = NULL, *match = NULL; @@ -840,7 +848,7 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int match = FcFontMatch(NULL, pat, &result); FcPatternDestroy(pat); - + if ( ! match ) { FcFontSetDestroy(fs); xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, @@ -870,7 +878,7 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int /* try load font from current directory */ if ( !FT_New_Face(osd->ft2->library, fontname, 0, &osd->ft2->face) ) goto end; - + /* try load font from home directory */ snprintf(pathname, 1024, "%s/.xine/fonts/%s", xine_get_homedir(), fontname); if ( !FT_New_Face(osd->ft2->library, pathname, 0, &osd->ft2->face) ) @@ -881,20 +889,18 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int if ( !FT_New_Face(osd->ft2->library, pathname, 0, &osd->ft2->face) ) goto end; - xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, + xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: error loading font %s with ft2\n"), fontname); } - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; end: if (FT_Set_Pixel_Sizes(osd->ft2->face, 0, size)) { xprintf(osd->renderer->stream->xine, XINE_VERBOSITY_LOG, _("osd: error setting font size (no scalable font?)\n")); - free(osd->ft2); - osd->ft2 = NULL; + osd_free_ft2 (osd); return 0; } @@ -907,11 +913,11 @@ static int osd_set_font_freetype2( osd_object_t *osd, const char *fontname, int set the font of osd object */ -static int osd_set_font( osd_object_t *osd, const char *fontname, int size) { +static int osd_set_font( osd_object_t *osd, const char *fontname, int size) { int ret = 1; lprintf("osd=%p font '%s'\n", osd, fontname); - + pthread_mutex_lock (&osd->renderer->osd_mutex); #ifdef HAVE_FT2 @@ -926,7 +932,7 @@ static int osd_set_font( osd_object_t *osd, const char *fontname, int size) { font = osd->renderer->fonts; while( font ) { - if( !strcasecmp(font->name, fontname) && (size>=font->size) + if( !strcasecmp(font->name, fontname) && (size>=font->size) && (best<font->size)) { ret = 1; osd->font = font; @@ -942,7 +948,7 @@ static int osd_set_font( osd_object_t *osd, const char *fontname, int size) { ret = osd_renderer_load_font(osd->renderer, osd->font->filename); if(!ret) osd->font = NULL; - } + } } pthread_mutex_unlock (&osd->renderer->osd_mutex); @@ -972,29 +978,29 @@ static int osd_search(osd_fontchar_t *array, size_t n, uint16_t code) { if (array[right].code == code) return right; - else + else return ALIAS_CHARACTER_FONT < n ? ALIAS_CHARACTER_FONT : n; #else size_t i; - + for( i = 0; i < n; i++ ) { if( font->fontchar[i].code == unicode ) break; } - if (i < n) + if (i < n) return i; - else + else return ALIAS_CHARACTER_FONT < n ? ALIAS_CHARACTER_FONT : n; #endif } #ifdef HAVE_ICONV -/* - * get next unicode value +/* + * get next unicode value */ -static uint16_t osd_iconv_getunicode(xine_t *xine, +static uint16_t osd_iconv_getunicode(xine_t *xine, iconv_t cd, const char *encoding, ICONV_CONST char **inbuf, size_t *inbytesleft) { uint16_t unicode; @@ -1046,7 +1052,7 @@ static void osd_free_encoding(osd_object_t *osd) { /* - * set encoding of text + * set encoding of text * * NULL ... no conversion (iso-8859-1) * "" ... locale encoding @@ -1111,7 +1117,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, #endif lprintf("osd=%p (%d,%d) \"%s\"\n", osd, x1, y1, text); - + /* some sanity checks for the color indices */ if( color_base < 0 ) color_base = 0; @@ -1127,7 +1133,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, #ifdef HAVE_FT2 if (osd->ft2) proceed = 1; #endif - + if (proceed == 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: font isn't defined\n")); pthread_mutex_unlock(&this->osd_mutex); @@ -1140,10 +1146,10 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, inbuf = text; inbytesleft = strlen(text); - + while( inbytesleft ) { #ifdef HAVE_ICONV - unicode = osd_iconv_getunicode(this->stream->xine, osd->cd, osd->encoding, + unicode = osd_iconv_getunicode(this->stream->xine, osd->cd, osd->encoding, (ICONV_CONST char **)&inbuf, &inbytesleft); #else unicode = inbuf[0]; @@ -1201,7 +1207,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, while (s < src + slot->bitmap.width) { if ((d >= dst) && (d < dst + osd->width) && *s) *d = (uint8_t)(*s/25) + (uint8_t) color_base; - + d++; s++; } @@ -1220,15 +1226,15 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, #endif i = osd_search(font->fontchar, font->num_fontchars, unicode); - - lprintf("font '%s' [%d, U+%04X == U+%04X] %dx%d -> %d,%d\n", font->name, i, - unicode, font->fontchar[i].code, font->fontchar[i].width, + + lprintf("font '%s' [%d, U+%04X == U+%04X] %dx%d -> %d,%d\n", font->name, i, + unicode, font->fontchar[i].code, font->fontchar[i].width, font->fontchar[i].height, x1, y1); - + if ( i != font->num_fontchars ) { dst = osd->area + y1 * osd->width; src = font->fontchar[i].bmp; - + for( y = 0; y < font->fontchar[i].height; y++ ) { uint8_t *s = src; uint8_t *d = dst + x1; @@ -1240,7 +1246,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, while (s < src + font->fontchar[i].width) { if((d >= dst) && (d < dst + osd->width) && (*s > 1)) /* skip drawing transparency */ *d = *s + (uint8_t) color_base; - + d++; s++; } @@ -1248,12 +1254,12 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, dst += osd->width; } x1 += font->fontchar[i].width - (font->fontchar[i].width * FONT_OVERLAP); - + if( x1 > osd->x2 ) osd->x2 = x1; - if( y1 + font->fontchar[i].height > osd->y2 ) + if( y1 + font->fontchar[i].height > osd->y2 ) osd->y2 = y1 + font->fontchar[i].height; } - + #ifdef HAVE_FT2 } /* !(osd->ft2) */ #endif @@ -1285,7 +1291,7 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in #endif lprintf("osd=%p \"%s\"\n", osd, text); - + pthread_mutex_lock (&this->osd_mutex); { @@ -1295,7 +1301,7 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in #ifdef HAVE_FT2 if (osd->ft2) proceed = 1; #endif - + if (proceed == 0) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, _("osd: font isn't defined\n")); pthread_mutex_unlock(&this->osd_mutex); @@ -1308,10 +1314,10 @@ static int osd_get_text_size(osd_object_t *osd, const char *text, int *width, in inbuf = text; inbytesleft = strlen(text); - + while( inbytesleft ) { #ifdef HAVE_ICONV - unicode = osd_iconv_getunicode(this->stream->xine, osd->cd, osd->encoding, + unicode = osd_iconv_getunicode(this->stream->xine, osd->cd, osd->encoding, (ICONV_CONST char **)&inbuf, &inbytesleft); #else unicode = inbuf[0]; @@ -1402,7 +1408,7 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) { int len; len = strlen (entry->d_name); - + if ( (len > 12) && !strncmp (&entry->d_name[len-12], ".xinefont.gz", 12)) { s = strdup(entry->d_name); @@ -1410,21 +1416,18 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) { if( p ) { osd_font_t *font; - char *pathname; *p++ = '\0'; - font = xine_xmalloc( sizeof(osd_font_t) ); - + font = calloc(1, sizeof(osd_font_t) ); + strncpy(font->name, s, sizeof(font->name)); font->size = atoi(p); - lprintf("font '%s' size %d is preloaded\n", + lprintf("font '%s' size %d is preloaded\n", font->name, font->size); - pathname = (char *) xine_xmalloc(strlen(path) + strlen(entry->d_name) + 2); - sprintf (pathname, "%s/%s", path, entry->d_name); - font->filename = pathname; - + asprintf (&font->filename, "%s/%s", path, entry->d_name); + font->next = this->fonts; this->fonts = font; } @@ -1441,30 +1444,30 @@ static void osd_preload_fonts (osd_renderer_t *this, char *path) { */ static void osd_free_object (osd_object_t *osd_to_close) { - + osd_renderer_t *this = osd_to_close->renderer; video_overlay_manager_t *ovl_manager; osd_object_t *osd, *last; if( osd_to_close->handle >= 0 ) { osd_hide(osd_to_close,0); - + this->event.object.handle = osd_to_close->handle; - + /* not really needed this, but good pratice to clean it up */ memset( this->event.object.overlay, 0, sizeof(this->event.object.overlay) ); this->event.event_type = OVERLAY_EVENT_FREE_HANDLE; this->event.vpts = 0; - + this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out); ovl_manager->add_event(ovl_manager, (void *)&this->event); this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); - + osd_to_close->handle = -1; /* handle will be freed */ } - - pthread_mutex_lock (&this->osd_mutex); + + pthread_mutex_lock (&this->osd_mutex); last = NULL; osd = this->osds; @@ -1472,17 +1475,9 @@ static void osd_free_object (osd_object_t *osd_to_close) { if ( osd == osd_to_close ) { free( osd->area ); -#ifdef HAVE_FT2 - if( osd->ft2 ) { - if ( osd->ft2->library ) - FT_Done_FreeType(osd->ft2->library); - - free( osd->ft2 ); - } -#endif - + osd_free_ft2 (osd); osd_free_encoding(osd); - + if( last ) last->next = osd->next; else @@ -1494,7 +1489,7 @@ static void osd_free_object (osd_object_t *osd_to_close) { last = osd; osd = osd->next; } - pthread_mutex_unlock (&this->osd_mutex); + pthread_mutex_unlock (&this->osd_mutex); } static void osd_renderer_close (osd_renderer_t *this) { @@ -1552,7 +1547,7 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, } static uint32_t osd_get_capabilities (osd_object_t *osd) { - + osd_renderer_t *this = osd->renderer; uint32_t capabilities = 0; @@ -1565,8 +1560,8 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) { VO_CAP_UNSCALED_OVERLAY) capabilities |= XINE_OSD_CAP_UNSCALED; this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); - - return capabilities; + + return capabilities; } @@ -1579,9 +1574,9 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { osd_renderer_t *this; char str[1024]; - this = xine_xmalloc(sizeof(osd_renderer_t)); + this = calloc(1, sizeof(osd_renderer_t)); this->stream = stream; - this->event.object.overlay = xine_xmalloc( sizeof(vo_overlay_t) ); + this->event.object.overlay = calloc(1, sizeof(vo_overlay_t)); pthread_mutex_init (&this->osd_mutex, NULL); @@ -1597,13 +1592,13 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { this->textpalette = this->stream->xine->config->register_enum (this->stream->xine->config, "ui.osd.text_palette", 0, - textpalettes_str, + textpalettes_str, _("palette (foreground-border-background) to use for subtitles and OSD"), _("The palette for on-screen-display and some subtitle formats that do " "not specify any colouring themselves. The palettes are listed in the " "form: foreground-border-background."), 10, update_text_palette, this); - + /* * set up function pointer */ diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index 38b5d1fdd..768fcb418 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -48,11 +48,11 @@ struct osd_object_s { int width, height; /* work area dimentions */ uint8_t *area; /* work area */ int display_x,display_y; /* where to display it in screen */ - + /* clipping box inside work area */ int x1, y1; int x2, y2; - + uint32_t color[OVL_PALETTE_SIZE]; /* color lookup table */ uint8_t trans[OVL_PALETTE_SIZE]; /* mixer key table */ @@ -62,7 +62,7 @@ struct osd_object_s { iconv_t cd; /* iconv handle of encoding */ char *encoding; /* name of encoding */ #endif - + osd_font_t *font; osd_ft2context_t *ft2; }; @@ -102,17 +102,17 @@ struct osd_renderer_s { */ int (*hide) (osd_object_t *osd, int64_t vpts ); - /* + /* * draw point. */ void (*point) (osd_object_t *osd, int x, int y, int color); - + /* * Bresenham line implementation on osd object */ void (*line) (osd_object_t *osd, int x1, int y1, int x2, int y2, int color ); - + /* * filled rectangle */ @@ -125,7 +125,7 @@ struct osd_renderer_s { void (*set_palette) (osd_object_t *osd, const uint32_t *color, const uint8_t *trans ); /* - * set on existing text palette + * set on existing text palette * (-1 to set used specified palette) * * color_base specifies the first color index to use for this text @@ -136,11 +136,11 @@ struct osd_renderer_s { */ void (*set_text_palette) (osd_object_t *osd, int palette_number, int color_base ); - + /* * get palette (color and transparency) */ - void (*get_palette) (osd_object_t *osd, uint32_t *color, + void (*get_palette) (osd_object_t *osd, uint32_t *color, uint8_t *trans); /* @@ -167,20 +167,20 @@ struct osd_renderer_s { * no \n yet * * The text is assigned the colors starting at the index specified by - * color_base up to the size of the text palette. + * color_base up to the size of the text palette. * * Use OSD_TEXT1, OSD_TEXT2, ... for some preasssigned color indices. */ - int (*render_text) (osd_object_t *osd, int x1, int y1, + int (*render_text) (osd_object_t *osd, int x1, int y1, const char *text, int color_base); /* * get width and height of how text will be renderized */ - int (*get_text_size) (osd_object_t *osd, const char *text, + int (*get_text_size) (osd_object_t *osd, const char *text, int *width, int *height); - /* + /* * close osd rendering engine * loaded fonts are unloaded * osd objects are closed @@ -191,7 +191,7 @@ struct osd_renderer_s { * clear an osd object (empty drawing area) */ void (*clear) (osd_object_t *osd ); - + /* * paste a bitmap with optional palette mapping */ @@ -210,7 +210,7 @@ struct osd_renderer_s { * see xine.h for defined XINE_OSD_CAP_ values. */ uint32_t (*get_capabilities) (osd_object_t *osd); - + /* private stuff */ pthread_mutex_t osd_mutex; @@ -218,7 +218,7 @@ struct osd_renderer_s { osd_object_t *osds; /* instances of osd */ osd_font_t *fonts; /* loaded fonts */ int textpalette; /* default textpalette */ - + xine_stream_t *stream; }; @@ -226,11 +226,11 @@ struct osd_renderer_s { /* * initialize the osd rendering engine */ -osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ); +osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) XINE_MALLOC; /* - * The size of a text palette + * The size of a text palette */ #define TEXT_PALETTE_SIZE 11 @@ -251,29 +251,29 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ); #define OSD_TEXT9 (8 * TEXT_PALETTE_SIZE) #define OSD_TEXT10 (9 * TEXT_PALETTE_SIZE) -/* +/* * Defined palettes for rendering osd text * (more can be added later) - */ + */ #define NUMBER_OF_TEXT_PALETTES 4 #define TEXTPALETTE_WHITE_BLACK_TRANSPARENT 0 #define TEXTPALETTE_WHITE_NONE_TRANSPARENT 1 #define TEXTPALETTE_WHITE_NONE_TRANSLUCID 2 #define TEXTPALETTE_YELLOW_BLACK_TRANSPARENT 3 - + #ifdef __OSD_C__ - + /* This text descriptions are used for config screen */ static const char *textpalettes_str[NUMBER_OF_TEXT_PALETTES+1] = { "white-black-transparent", "white-none-transparent", "white-none-translucid", - "yellow-black-transparent", + "yellow-black-transparent", NULL}; -/* +/* Palette entries as used by osd fonts: 0: not used by font, always transparent @@ -284,10 +284,10 @@ static const char *textpalettes_str[NUMBER_OF_TEXT_PALETTES+1] = { 6: font border. if the font is to be displayed without border this will probably be adjusted to font background or near. 7-9: transition between border and foreground - 10: font color (foreground) + 10: font color (foreground) */ -/* +/* The palettes below were made by hand, ie, i just throw values that seemed to do the transitions i wanted. This can surelly be improved a lot. [Miguel] diff --git a/src/xine-engine/plugin_catalog.h b/src/xine-engine/plugin_catalog.h index a28321760..010ec53bb 100644 --- a/src/xine-engine/plugin_catalog.h +++ b/src/xine-engine/plugin_catalog.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -60,16 +60,16 @@ typedef struct { struct plugin_catalog_s { xine_sarray_t *plugin_lists[PLUGIN_TYPE_MAX]; - + xine_sarray_t *cache_list; xine_list_t *file_list; plugin_node_t *audio_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; plugin_node_t *video_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; plugin_node_t *spu_decoder_map[DECODER_MAX][PLUGINS_PER_TYPE]; - + const char *ids[PLUGIN_MAX]; - + /* memory block for the decoder priority config entry descriptions */ char *prio_desc[DECODER_MAX]; diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c index 5d8d67037..276934788 100644 --- a/src/xine-engine/post.c +++ b/src/xine-engine/post.c @@ -1,23 +1,23 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ - + /* * some helper functions for post plugins */ @@ -30,13 +30,10 @@ void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_inputs) { - int audio_inputs_size = (num_audio_inputs + 1) * sizeof(xine_audio_port_t *); - int video_inputs_size = (num_video_inputs + 1) * sizeof(xine_video_port_t *); - post->input = xine_list_new(); post->output = xine_list_new(); - post->xine_post.audio_input = (xine_audio_port_t **)xine_xmalloc(audio_inputs_size); - post->xine_post.video_input = (xine_video_port_t **)xine_xmalloc(video_inputs_size); + post->xine_post.audio_input = calloc(num_audio_inputs + 1, sizeof(xine_audio_port_t *)); + post->xine_post.video_input = calloc(num_video_inputs + 1, sizeof(xine_video_port_t *)); } @@ -44,7 +41,7 @@ void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_input static uint32_t post_video_get_capabilities(xine_video_port_t *port_gen) { post_video_port_t *port = (post_video_port_t *)port_gen; uint32_t caps; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); caps = port->original_port->get_capabilities(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -53,7 +50,7 @@ static uint32_t post_video_get_capabilities(xine_video_port_t *port_gen) { static void post_video_open(xine_video_port_t *port_gen, xine_stream_t *stream) { post_video_port_t *port = (post_video_port_t *)port_gen; - + _x_post_rewire(port->post); _x_post_inc_usage(port); if (port->port_lock) pthread_mutex_lock(port->port_lock); @@ -62,31 +59,31 @@ static void post_video_open(xine_video_port_t *port_gen, xine_stream_t *stream) port->stream = stream; } -static vo_frame_t *post_video_get_frame(xine_video_port_t *port_gen, uint32_t width, +static vo_frame_t *post_video_get_frame(xine_video_port_t *port_gen, uint32_t width, uint32_t height, double ratio, int format, int flags) { post_video_port_t *port = (post_video_port_t *)port_gen; vo_frame_t *frame; - + _x_post_rewire(port->post); if (port->port_lock) pthread_mutex_lock(port->port_lock); frame = port->original_port->get_frame(port->original_port, width, height, ratio, format, flags); if (port->port_lock) pthread_mutex_unlock(port->port_lock); - + if (frame && (!port->intercept_frame || port->intercept_frame(port, frame))) { _x_post_inc_usage(port); if (port->frame_lock) pthread_mutex_lock(port->frame_lock); frame = _x_post_intercept_video_frame(frame, port); if (port->frame_lock) pthread_mutex_unlock(port->frame_lock); } - + return frame; } static vo_frame_t *post_video_get_last_frame(xine_video_port_t *port_gen) { post_video_port_t *port = (post_video_port_t *)port_gen; vo_frame_t *frame; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); frame = port->original_port->get_last_frame(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -95,15 +92,15 @@ static vo_frame_t *post_video_get_last_frame(xine_video_port_t *port_gen) { static void post_video_enable_ovl(xine_video_port_t *port_gen, int ovl_enable) { post_video_port_t *port = (post_video_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->enable_ovl(port->original_port, ovl_enable); if (port->port_lock) pthread_mutex_unlock(port->port_lock); } - + static void post_video_close(xine_video_port_t *port_gen, xine_stream_t *stream) { post_video_port_t *port = (post_video_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->close(port->original_port, stream); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -113,7 +110,7 @@ static void post_video_close(xine_video_port_t *port_gen, xine_stream_t *stream) static void post_video_exit(xine_video_port_t *port_gen) { post_video_port_t *port = (post_video_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->exit(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -122,11 +119,11 @@ static void post_video_exit(xine_video_port_t *port_gen) { static video_overlay_manager_t *post_video_get_overlay_manager(xine_video_port_t *port_gen) { post_video_port_t *port = (post_video_port_t *)port_gen; video_overlay_manager_t *manager; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); manager = port->original_port->get_overlay_manager(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); - + if (port->intercept_ovl && port->intercept_ovl(port)) { if (manager && !port->original_manager) /* this is the first access to overlay manager */ @@ -141,7 +138,7 @@ static video_overlay_manager_t *post_video_get_overlay_manager(xine_video_port_t static void post_video_flush(xine_video_port_t *port_gen) { post_video_port_t *port = (post_video_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->flush(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -151,7 +148,7 @@ static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream, int *width, int *height, int64_t *img_duration) { post_video_port_t *port = (post_video_port_t *)port_gen; int status; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); status = port->original_port->status(port->original_port, stream, width, height, img_duration); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -161,7 +158,7 @@ static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream, static int post_video_get_property(xine_video_port_t *port_gen, int property) { post_video_port_t *port = (post_video_port_t *)port_gen; int prop; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); prop = port->original_port->get_property(port->original_port, property); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -171,7 +168,7 @@ static int post_video_get_property(xine_video_port_t *port_gen, int property) { static int post_video_set_property(xine_video_port_t *port_gen, int property, int value) { post_video_port_t *port = (post_video_port_t *)port_gen; int val; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); val = port->original_port->set_property(port->original_port, property, value); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -186,32 +183,32 @@ static int post_video_rewire(xine_post_out_t *output_gen, void *data) { post_plugin_t *this = output->post; int64_t img_duration; int width, height; - + if (!new_port) return 0; - + this->running_ticket->revoke(this->running_ticket, 1); - + if (input_port->original_port->status(input_port->original_port, input_port->stream, &width, &height, &img_duration)) { (new_port->open) (new_port, input_port->stream); input_port->original_port->close(input_port->original_port, input_port->stream); } input_port->original_port = new_port; - + this->running_ticket->issue(this->running_ticket, 1); - + return 1; } post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *original, post_in_t **input, post_out_t **output) { - post_video_port_t *port = (post_video_port_t *)xine_xmalloc(sizeof(post_video_port_t)); - + post_video_port_t *port = calloc(1, sizeof(post_video_port_t)); + if (!port) return NULL; - + port->new_port.get_capabilities = post_video_get_capabilities; port->new_port.open = post_video_open; port->new_port.get_frame = post_video_get_frame; @@ -225,17 +222,17 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ port->new_port.get_property = post_video_get_property; port->new_port.set_property = post_video_set_property; port->new_port.driver = original->driver; - + port->original_port = original; port->new_frame = &port->frame_storage; port->new_manager = &port->manager_storage; port->post = post; - + pthread_mutex_init(&port->usage_lock, NULL); pthread_mutex_init(&port->free_frames_lock, NULL); - + if (input) { - *input = (post_in_t *)xine_xmalloc(sizeof(post_in_t)); + *input = calloc(1, sizeof(post_in_t)); if (!*input) return port; (*input)->xine_in.name = "video in"; (*input)->xine_in.type = XINE_POST_DATA_VIDEO; @@ -243,9 +240,9 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ (*input)->post = post; xine_list_push_back(post->input, *input); } - + if (output) { - *output = (post_out_t *)xine_xmalloc(sizeof(post_out_t)); + *output = calloc(1, sizeof(post_out_t)); if (!*output) return port; (*output)->xine_out.name = "video out"; (*output)->xine_out.type = XINE_POST_DATA_VIDEO; @@ -255,7 +252,7 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ (*output)->user_data = port; xine_list_push_back(post->output, *output); } - + return port; } @@ -263,7 +260,7 @@ post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_ /* dummy intercept functions for frames */ static void post_frame_free(vo_frame_t *vo_img) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); if (--vo_img->lock_counter == 0) { /* this frame is free */ @@ -282,7 +279,7 @@ static void post_frame_free(vo_frame_t *vo_img) { static void post_frame_proc_slice(vo_frame_t *vo_img, uint8_t **src) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); _x_post_frame_copy_down(vo_img, vo_img->next); vo_img->next->proc_slice(vo_img->next, src); @@ -292,7 +289,7 @@ static void post_frame_proc_slice(vo_frame_t *vo_img, uint8_t **src) { static void post_frame_proc_frame(vo_frame_t *vo_img) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); _x_post_frame_copy_down(vo_img, vo_img->next); vo_img->next->proc_frame(vo_img->next); @@ -302,7 +299,7 @@ static void post_frame_proc_frame(vo_frame_t *vo_img) { static void post_frame_field(vo_frame_t *vo_img, int which_field) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); _x_post_frame_copy_down(vo_img, vo_img->next); vo_img->next->field(vo_img->next, which_field); @@ -313,7 +310,7 @@ static void post_frame_field(vo_frame_t *vo_img, int which_field) { static int post_frame_draw(vo_frame_t *vo_img, xine_stream_t *stream) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); int skip; - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); _x_post_frame_copy_down(vo_img, vo_img->next); skip = vo_img->next->draw(vo_img->next, stream); @@ -324,7 +321,7 @@ static int post_frame_draw(vo_frame_t *vo_img, xine_stream_t *stream) { static void post_frame_lock(vo_frame_t *vo_img) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); _x_post_frame_copy_down(vo_img, vo_img->next); vo_img->lock_counter++; @@ -335,7 +332,7 @@ static void post_frame_lock(vo_frame_t *vo_img) { static void post_frame_dispose(vo_frame_t *vo_img) { post_video_port_t *port = _x_post_video_frame_to_port(vo_img); - + if (port->frame_lock) pthread_mutex_lock(port->frame_lock); vo_img = _x_post_restore_video_frame(vo_img, port); vo_img->dispose(vo_img); @@ -346,24 +343,24 @@ static void post_frame_dispose(vo_frame_t *vo_img) { vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) { vo_frame_t *new_frame; - + /* get a free frame slot */ pthread_mutex_lock(&port->free_frames_lock); if (port->free_frame_slots) { new_frame = port->free_frame_slots; port->free_frame_slots = new_frame->next; } else { - new_frame = (vo_frame_t *)xine_xmalloc(sizeof(vo_frame_t)); + new_frame = calloc(1, sizeof(vo_frame_t)); } pthread_mutex_unlock(&port->free_frames_lock); - + /* make a copy and attach the original */ xine_fast_memcpy(new_frame, frame, sizeof(vo_frame_t)); new_frame->next = frame; if (new_frame->stream) _x_refcounter_inc(new_frame->stream->refcounter); - + /* modify the frame with the intercept functions */ new_frame->port = &port->new_port; new_frame->proc_frame = @@ -380,7 +377,7 @@ vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t * port->new_frame->free ? port->new_frame->free : post_frame_free; new_frame->dispose = port->new_frame->dispose ? port->new_frame->dispose : post_frame_dispose; - + if (!port->new_frame->draw) { /* draw will most likely modify the frame, so the decoder * should only request preprocessing when there is no new draw */ @@ -389,17 +386,17 @@ vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t * if (frame->proc_slice && !new_frame->proc_slice) new_frame->proc_slice = post_frame_proc_slice; } - + return new_frame; } vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) { /* the first attched context is the original frame */ vo_frame_t *original = frame->next; - + /* propagate any changes */ _x_post_frame_copy_down(frame, original); - + if (frame->stream) _x_refcounter_dec(frame->stream->refcounter); @@ -408,7 +405,7 @@ vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *po frame->next = port->free_frame_slots; port->free_frame_slots = frame; pthread_mutex_unlock(&port->free_frames_lock); - + return original; } @@ -449,7 +446,7 @@ void _x_post_frame_copy_up(vo_frame_t *to, vo_frame_t *from) { to->vpts = from->vpts; to->duration = from->duration; to->stream = from->stream; - + if (to->extra_info != from->extra_info) _x_extra_info_merge(to->extra_info, from->extra_info); } @@ -465,14 +462,14 @@ void _x_post_frame_u_turn(vo_frame_t *frame, xine_stream_t *stream) { if (stream) { _x_extra_info_merge(frame->extra_info, stream->video_decoder_extra_info); stream->metronom->got_video_frame(stream->metronom, frame); - } + } } /* dummy intercept functions that just pass the call on to the original overlay manager */ static void post_overlay_init(video_overlay_manager_t *ovl_gen) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); port->original_manager->init(port->original_manager); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -480,7 +477,7 @@ static void post_overlay_init(video_overlay_manager_t *ovl_gen) { static void post_overlay_dispose(video_overlay_manager_t *ovl_gen) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); port->original_manager->dispose(port->original_manager); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -489,7 +486,7 @@ static void post_overlay_dispose(video_overlay_manager_t *ovl_gen) { static int32_t post_overlay_get_handle(video_overlay_manager_t *ovl_gen, int object_type) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); int32_t handle; - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); handle = port->original_manager->get_handle(port->original_manager, object_type); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -498,7 +495,7 @@ static int32_t post_overlay_get_handle(video_overlay_manager_t *ovl_gen, int obj static void post_overlay_free_handle(video_overlay_manager_t *ovl_gen, int32_t handle) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); port->original_manager->free_handle(port->original_manager, handle); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -507,7 +504,7 @@ static void post_overlay_free_handle(video_overlay_manager_t *ovl_gen, int32_t h static int32_t post_overlay_add_event(video_overlay_manager_t *ovl_gen, void *event) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); int32_t result; - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); result = port->original_manager->add_event(port->original_manager, event); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -516,7 +513,7 @@ static int32_t post_overlay_add_event(video_overlay_manager_t *ovl_gen, void *ev static void post_overlay_flush_events(video_overlay_manager_t *ovl_gen) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); port->original_manager->flush_events(port->original_manager); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -525,17 +522,17 @@ static void post_overlay_flush_events(video_overlay_manager_t *ovl_gen) { static int post_overlay_redraw_needed(video_overlay_manager_t *ovl_gen, int64_t vpts) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); int redraw; - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); redraw = port->original_manager->redraw_needed(port->original_manager, vpts); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); return redraw; } -static void post_overlay_multiple_overlay_blend(video_overlay_manager_t *ovl_gen, int64_t vpts, +static void post_overlay_multiple_overlay_blend(video_overlay_manager_t *ovl_gen, int64_t vpts, vo_driver_t *output, vo_frame_t *vo_img, int enabled) { post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen); - + if (port->manager_lock) pthread_mutex_lock(port->manager_lock); port->original_manager->multiple_overlay_blend(port->original_manager, vpts, output, vo_img, enabled); if (port->manager_lock) pthread_mutex_unlock(port->manager_lock); @@ -559,7 +556,7 @@ void _x_post_intercept_overlay_manager(video_overlay_manager_t *original, post_v port->new_manager->redraw_needed = post_overlay_redraw_needed; if (!port->new_manager->multiple_overlay_blend) port->new_manager->multiple_overlay_blend = post_overlay_multiple_overlay_blend; - + port->original_manager = original; } @@ -568,7 +565,7 @@ void _x_post_intercept_overlay_manager(video_overlay_manager_t *original, post_v static uint32_t post_audio_get_capabilities(xine_audio_port_t *port_gen) { post_audio_port_t *port = (post_audio_port_t *)port_gen; uint32_t caps; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); caps = port->original_port->get_capabilities(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -578,7 +575,7 @@ static uint32_t post_audio_get_capabilities(xine_audio_port_t *port_gen) { static int post_audio_get_property(xine_audio_port_t *port_gen, int property) { post_audio_port_t *port = (post_audio_port_t *)port_gen; int prop; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); prop = port->original_port->get_property(port->original_port, property); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -588,7 +585,7 @@ static int post_audio_get_property(xine_audio_port_t *port_gen, int property) { static int post_audio_set_property(xine_audio_port_t *port_gen, int property, int value) { post_audio_port_t *port = (post_audio_port_t *)port_gen; int val; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); val = port->original_port->set_property(port->original_port, property, value); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -599,7 +596,7 @@ static int post_audio_open(xine_audio_port_t *port_gen, xine_stream_t *stream, uint32_t bits, uint32_t rate, int mode) { post_audio_port_t *port = (post_audio_port_t *)port_gen; int result; - + _x_post_rewire(port->post); _x_post_inc_usage(port); if (port->port_lock) pthread_mutex_lock(port->port_lock); @@ -615,7 +612,7 @@ static int post_audio_open(xine_audio_port_t *port_gen, xine_stream_t *stream, static audio_buffer_t *post_audio_get_buffer(xine_audio_port_t *port_gen) { post_audio_port_t *port = (post_audio_port_t *)port_gen; audio_buffer_t *buf; - + _x_post_rewire(port->post); if (port->port_lock) pthread_mutex_lock(port->port_lock); buf = port->original_port->get_buffer(port->original_port); @@ -626,15 +623,15 @@ static audio_buffer_t *post_audio_get_buffer(xine_audio_port_t *port_gen) { static void post_audio_put_buffer(xine_audio_port_t *port_gen, audio_buffer_t *buf, xine_stream_t *stream) { post_audio_port_t *port = (post_audio_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->put_buffer(port->original_port, buf, stream); if (port->port_lock) pthread_mutex_unlock(port->port_lock); } - + static void post_audio_close(xine_audio_port_t *port_gen, xine_stream_t *stream) { post_audio_port_t *port = (post_audio_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->close(port->original_port, stream); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -644,7 +641,7 @@ static void post_audio_close(xine_audio_port_t *port_gen, xine_stream_t *stream) static void post_audio_exit(xine_audio_port_t *port_gen) { post_audio_port_t *port = (post_audio_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->exit(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -668,7 +665,7 @@ static int post_audio_control(xine_audio_port_t *port_gen, int cmd, ...) { static void post_audio_flush(xine_audio_port_t *port_gen) { post_audio_port_t *port = (post_audio_port_t *)port_gen; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); port->original_port->flush(port->original_port); if (port->port_lock) pthread_mutex_unlock(port->port_lock); @@ -678,7 +675,7 @@ static int post_audio_status(xine_audio_port_t *port_gen, xine_stream_t *stream, uint32_t *bits, uint32_t *rate, int *mode) { post_audio_port_t *port = (post_audio_port_t *)port_gen; int result; - + if (port->port_lock) pthread_mutex_lock(port->port_lock); result = port->original_port->status(port->original_port, stream, bits, rate, mode); *bits = port->bits; @@ -696,31 +693,31 @@ static int post_audio_rewire(xine_post_out_t *output_gen, void *data) { post_plugin_t *this = output->post; uint32_t bits, rate; int mode; - + if (!new_port) return 0; - + this->running_ticket->revoke(this->running_ticket, 1); - + if (input_port->original_port->status(input_port->original_port, input_port->stream, &bits, &rate, &mode)) { (new_port->open) (new_port, input_port->stream, bits, rate, mode); input_port->original_port->close(input_port->original_port, input_port->stream); } input_port->original_port = new_port; - + this->running_ticket->issue(this->running_ticket, 1); - + return 1; } post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *original, post_in_t **input, post_out_t **output) { - post_audio_port_t *port = (post_audio_port_t *)xine_xmalloc(sizeof(post_audio_port_t)); - + post_audio_port_t *port = calloc(1, sizeof(post_audio_port_t)); + if (!port) return NULL; - + port->new_port.open = post_audio_open; port->new_port.get_buffer = post_audio_get_buffer; port->new_port.put_buffer = post_audio_put_buffer; @@ -732,14 +729,14 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ port->new_port.control = post_audio_control; port->new_port.flush = post_audio_flush; port->new_port.status = post_audio_status; - + port->original_port = original; port->post = post; - + pthread_mutex_init(&port->usage_lock, NULL); - + if (input) { - *input = (post_in_t *)xine_xmalloc(sizeof(post_in_t)); + *input = calloc(1, sizeof(post_in_t)); if (!*input) return port; (*input)->xine_in.name = "audio in"; (*input)->xine_in.type = XINE_POST_DATA_AUDIO; @@ -747,9 +744,9 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ (*input)->post = post; xine_list_push_back(post->input, *input); } - + if (output) { - *output = (post_out_t *)xine_xmalloc(sizeof(post_out_t)); + *output = calloc(1, sizeof(post_out_t)); if (!*output) return port; (*output)->xine_out.name = "audio out"; (*output)->xine_out.type = XINE_POST_DATA_AUDIO; @@ -759,14 +756,14 @@ post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_ (*output)->user_data = port; xine_list_push_back(post->output, *output); } - + return port; } int _x_post_dispose(post_plugin_t *this) { int i, in_use = 0; - + /* acquire all usage locks */ for (i = 0; this->xine_post.audio_input[i]; i++) { post_audio_port_t *port = (post_audio_port_t *)this->xine_post.audio_input[i]; @@ -776,11 +773,11 @@ int _x_post_dispose(post_plugin_t *this) { post_video_port_t *port = (post_video_port_t *)this->xine_post.video_input[i]; pthread_mutex_lock(&port->usage_lock); } - + /* we can set this witout harm, because it is always checked with * usage lock held */ this->dispose_pending = 1; - + /* check counters */ for (i = 0; this->xine_post.audio_input[i]; i++) { post_audio_port_t *port = (post_audio_port_t *)this->xine_post.audio_input[i]; @@ -796,7 +793,7 @@ int _x_post_dispose(post_plugin_t *this) { break; } } - + /* free the locks */ for (i = 0; this->xine_post.audio_input[i]; i++) { post_audio_port_t *port = (post_audio_port_t *)this->xine_post.audio_input[i]; @@ -806,20 +803,20 @@ int _x_post_dispose(post_plugin_t *this) { post_video_port_t *port = (post_video_port_t *)this->xine_post.video_input[i]; pthread_mutex_unlock(&port->usage_lock); } - + if (!in_use) { xine_post_in_t *input; xine_post_out_t *output; xine_list_iterator_t ite; - + /* we can really dispose it */ - + free(this->xine_post.audio_input); free(this->xine_post.video_input); /* these were allocated in the plugin loader */ free(this->input_ids); free(this->output_ids); - + for (ite = xine_list_front(this->input); ite; ite = xine_list_next(this->input, ite)) { input = xine_list_get_value(this->input, ite); @@ -828,16 +825,16 @@ int _x_post_dispose(post_plugin_t *this) { { post_video_port_t *port = (post_video_port_t *)input->data; vo_frame_t *first, *second; - + pthread_mutex_destroy(&port->usage_lock); pthread_mutex_destroy(&port->free_frames_lock); - + second = NULL; for (first = port->free_frame_slots; first; second = first, first = first->next) free(second); free(second); - + free(port); free(input); } @@ -845,9 +842,9 @@ int _x_post_dispose(post_plugin_t *this) { case XINE_POST_DATA_AUDIO: { post_audio_port_t *port = (post_audio_port_t *)input->data; - + pthread_mutex_destroy(&port->usage_lock); - + free(port); free(input); } @@ -870,18 +867,18 @@ int _x_post_dispose(post_plugin_t *this) { break; } } - + xine_list_delete(this->input); xine_list_delete(this->output); - + /* since the plugin loader does not know, when the plugin gets disposed, * we have to handle the reference counter here */ pthread_mutex_lock(&this->xine->plugin_catalog->lock); ((plugin_node_t *)this->node)->ref--; pthread_mutex_unlock(&this->xine->plugin_catalog->lock); - + return 1; } - + return 0; } diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h index b06c7930a..d37c52908 100644 --- a/src/xine-engine/post.h +++ b/src/xine-engine/post.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -53,14 +53,14 @@ struct post_class_s { post_plugin_t* (*open_plugin) (post_class_t *this, int inputs, xine_audio_port_t **audio_target, xine_video_port_t **video_target); - + /* * return short, human readable identifier for this plugin class */ char* (*get_identifier) (post_class_t *this); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ char* (*get_description) (post_class_t *this); @@ -76,25 +76,25 @@ struct post_plugin_s { /* public part of the plugin */ xine_post_t xine_post; - + /* * the connections announced by the plugin * the plugin must fill these with xine_post_{in,out}_t on init */ xine_list_t *input; xine_list_t *output; - + /* * close down, free all resources */ void (*dispose) (post_plugin_t *this); - + /* has dispose been called */ int dispose_pending; - + /* plugins don't have to init the stuff below */ - - /* + + /* * the running ticket * * the plugin must assure to check for ticket revocation in @@ -105,11 +105,11 @@ struct post_plugin_s { * the running ticket is assigned to you by the engine */ xine_ticket_t *running_ticket; - + /* this is needed by the engine to decrement the reference counter * on disposal of the plugin, but since this is useful, we expose it */ xine_t *xine; - + /* used when the user requests a list of all inputs/outputs */ const char **input_ids; const char **output_ids; @@ -125,10 +125,10 @@ struct post_in_s { /* public part of the input */ xine_post_in_t xine_in; - + /* backward reference so that you have access to the post plugin */ post_plugin_t *post; - + /* you can fill this to your liking */ void *user_data; }; @@ -137,10 +137,10 @@ struct post_out_s { /* public part of the output */ xine_post_out_t xine_out; - + /* backward reference so that you have access to the post plugin */ post_plugin_t *post; - + /* you can fill this to your liking */ void *user_data; }; @@ -164,52 +164,52 @@ struct post_video_port_s { /* the new public port with replaced function pointers */ xine_video_port_t new_port; - + /* the original port to call its functions from inside yours */ xine_video_port_t *original_port; - + /* if you want to decide yourself, whether a given frame should * be intercepted, fill in this function; get_frame() acts as * a template method and asks your function; return a boolean; * the default is to intercept all frames */ int (*intercept_frame)(post_video_port_t *self, vo_frame_t *frame); - + /* the new frame function pointers */ vo_frame_t *new_frame; - + /* if you want to decide yourself, whether the overlay manager should * be intercepted, fill in this function; get_overlay_manager() acts as * a template method and asks your function; return a boolean; * the default is _not_ to intercept the overlay manager */ int (*intercept_ovl)(post_video_port_t *self); - + /* the new public overlay manager with replaced function pointers */ video_overlay_manager_t *new_manager; - + /* the original manager to call its functions from inside yours */ video_overlay_manager_t *original_manager; - + /* usage counter: how many objects are floating around that need * these pointers to exist */ int usage_count; pthread_mutex_t usage_lock; - + /* the stream we are being fed by; NULL means no stream is connected; * this may be an anonymous stream */ xine_stream_t *stream; - + /* point to a mutex here, if you need some synchronization */ pthread_mutex_t *port_lock; pthread_mutex_t *frame_lock; pthread_mutex_t *manager_lock; - + /* backward reference so that you have access to the post plugin * when the call only gives you the port */ post_plugin_t *post; - + /* you can fill this to your liking */ void *user_data; - + #ifdef POST_INTERNAL /* some of the above members are to be directly included here, but * adding the structures would mean that post_video_port_t becomes @@ -217,13 +217,13 @@ struct post_video_port_s { * above and have them point into the memory provided here; * note that the overlay manager needs to be first so that we can * reconstruct the post_video_port_t* from overlay manager calls */ - + /* any change here requires a change in _x_post_ovl_manager_to_port() * below! */ - + video_overlay_manager_t manager_storage; vo_frame_t frame_storage; - + /* this is used to keep a linked list of free vo_frame_t's */ vo_frame_t *free_frame_slots; pthread_mutex_t free_frames_lock; @@ -283,31 +283,31 @@ struct post_audio_port_s { /* the new public port with replaced function pointers */ xine_audio_port_t new_port; - + /* the original port to call its functions from inside yours */ xine_audio_port_t *original_port; - + /* usage counter: how many objects are floating around that need * these pointers to exist */ int usage_count; pthread_mutex_t usage_lock; - + /* the stream we are being fed by; NULL means no stream is connected; * this may be an anonymous stream */ xine_stream_t *stream; - + /* some values remembered by port->open() */ uint32_t bits; uint32_t rate; uint32_t mode; - + /* point to a mutex here, if you need some synchronization */ pthread_mutex_t *port_lock; - + /* backward reference so that you have access to the post plugin * when the call only gives you the port */ post_plugin_t *post; - + /* you can fill this to your liking */ void *user_data; }; @@ -369,7 +369,7 @@ do { \ } while(0) -/* macros to create parameter descriptors */ +/* macros to create parameter descriptors */ #define START_PARAM_DESCR( param_t ) \ static param_t temp_s; \ diff --git a/src/xine-engine/refcounter.c b/src/xine-engine/refcounter.c index 539abf3ed..23da4bdbc 100644 --- a/src/xine-engine/refcounter.c +++ b/src/xine-engine/refcounter.c @@ -1,28 +1,33 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "refcounter" #define LOG_VERBOSE /* #define LOG */ - + #include "xine_internal.h" #include "refcounter.h" @@ -30,7 +35,7 @@ refcounter_t* _x_new_refcounter(void *object, void (*destructor)(void *)) { refcounter_t *new_refcounter; - new_refcounter = (refcounter_t *) xine_xmalloc (sizeof (refcounter_t)); + new_refcounter = (refcounter_t *) calloc(1, sizeof(refcounter_t)); new_refcounter->count = 1; new_refcounter->object = object; new_refcounter->destructor = destructor; @@ -48,7 +53,7 @@ int _x_refcounter_inc(refcounter_t *refcounter) _x_abort(); res = ++refcounter->count; pthread_mutex_unlock(&refcounter->lock); - + return res; } @@ -63,7 +68,7 @@ int _x_refcounter_dec(refcounter_t *refcounter) lprintf("calling destructor of object %p\n", refcounter->object); refcounter->destructor(refcounter->object); } - + return res; } diff --git a/src/xine-engine/refcounter.h b/src/xine-engine/refcounter.h index 87abd6321..f157d8b6c 100644 --- a/src/xine-engine/refcounter.h +++ b/src/xine-engine/refcounter.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -20,10 +20,6 @@ #ifndef HAVE_REFCOUNTER_H #define HAVE_REFCOUNTER_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> typedef struct { @@ -35,7 +31,7 @@ typedef struct { typedef void (*refcounter_destructor)(void*); -refcounter_t* _x_new_refcounter(void *object, refcounter_destructor destructor) XINE_PROTECTED; +refcounter_t* _x_new_refcounter(void *object, refcounter_destructor destructor) XINE_MALLOC XINE_PROTECTED; int _x_refcounter_inc(refcounter_t *refcounter) XINE_PROTECTED; diff --git a/src/xine-engine/resample.c b/src/xine-engine/resample.c index 43911c401..dcf14a215 100644 --- a/src/xine-engine/resample.c +++ b/src/xine-engine/resample.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -30,7 +30,7 @@ /* contributed by paul flinders */ void _x_audio_out_resample_mono(int16_t *last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) { unsigned int osample; @@ -54,11 +54,11 @@ void _x_audio_out_resample_mono(int16_t *last_sample, int s2; int16_t os; uint32_t t = isample&0xffff; - + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ s1 = input_samples[(isample >> 16)]; s2 = input_samples[(isample >> 16)+1]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[osample] = os; @@ -68,7 +68,7 @@ void _x_audio_out_resample_mono(int16_t *last_sample, } void _x_audio_out_resample_stereo(int16_t *last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) { unsigned int osample; @@ -93,17 +93,17 @@ void _x_audio_out_resample_stereo(int16_t *last_sample, int s2; int16_t os; uint32_t t = isample&0xffff; - + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ s1 = input_samples[(isample >> 16)*2]; s2 = input_samples[(isample >> 16)*2+2]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[osample * 2] = os; s1 = input_samples[(isample >> 16)*2+1]; s2 = input_samples[(isample >> 16)*2+3]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 2 )+1] = os; isample += istep; @@ -113,7 +113,7 @@ void _x_audio_out_resample_stereo(int16_t *last_sample, void _x_audio_out_resample_4channel(int16_t *last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) { unsigned int osample; @@ -140,29 +140,29 @@ void _x_audio_out_resample_4channel(int16_t *last_sample, int s2; int16_t os; uint32_t t = isample&0xffff; - + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ s1 = input_samples[(isample >> 16)*4]; s2 = input_samples[(isample >> 16)*4+4]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[osample * 4] = os; s1 = input_samples[(isample >> 16)*4+1]; s2 = input_samples[(isample >> 16)*4+5]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 4 )+1] = os; s1 = input_samples[(isample >> 16)*4+2]; s2 = input_samples[(isample >> 16)*4+6]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 4 )+2] = os; s1 = input_samples[(isample >> 16)*4+3]; s2 = input_samples[(isample >> 16)*4+7]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 4 )+3] = os; @@ -173,7 +173,7 @@ void _x_audio_out_resample_4channel(int16_t *last_sample, void _x_audio_out_resample_5channel(int16_t *last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) { unsigned int osample; @@ -201,35 +201,35 @@ void _x_audio_out_resample_5channel(int16_t *last_sample, int s2; int16_t os; uint32_t t = isample&0xffff; - + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ s1 = input_samples[(isample >> 16)*5]; s2 = input_samples[(isample >> 16)*5+5]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[osample * 5] = os; s1 = input_samples[(isample >> 16)*5+1]; s2 = input_samples[(isample >> 16)*5+6]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 5 )+1] = os; s1 = input_samples[(isample >> 16)*5+2]; s2 = input_samples[(isample >> 16)*5+7]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 5 )+2] = os; s1 = input_samples[(isample >> 16)*5+3]; s2 = input_samples[(isample >> 16)*5+8]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 5 )+3] = os; s1 = input_samples[(isample >> 16)*5+4]; s2 = input_samples[(isample >> 16)*5+9]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 5 )+4] = os; @@ -240,7 +240,7 @@ void _x_audio_out_resample_5channel(int16_t *last_sample, void _x_audio_out_resample_6channel(int16_t *last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) { unsigned int osample; @@ -269,41 +269,41 @@ void _x_audio_out_resample_6channel(int16_t *last_sample, int s2; int16_t os; uint32_t t = isample&0xffff; - + /* don't "optimize" the (isample >> 16)*2 to (isample >> 15) */ s1 = input_samples[(isample >> 16)*6]; s2 = input_samples[(isample >> 16)*6+6]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[osample * 6] = os; s1 = input_samples[(isample >> 16)*6+1]; s2 = input_samples[(isample >> 16)*6+7]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 6 )+1] = os; s1 = input_samples[(isample >> 16)*6+2]; s2 = input_samples[(isample >> 16)*6+8]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 6 )+2] = os; s1 = input_samples[(isample >> 16)*6+3]; s2 = input_samples[(isample >> 16)*6+9]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 6 )+3] = os; s1 = input_samples[(isample >> 16)*6+4]; s2 = input_samples[(isample >> 16)*6+10]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 6 )+4] = os; s1 = input_samples[(isample >> 16)*6+5]; s2 = input_samples[(isample >> 16)*6+11]; - + os = (s1 * (0x10000-t)+ s2 * t) >> 16; output_samples[(osample * 6 )+5] = os; @@ -312,48 +312,48 @@ void _x_audio_out_resample_6channel(int16_t *last_sample, memcpy (last_sample, &input_samples[in_samples*6-6], 6 * sizeof (last_sample[0])); } -void _x_audio_out_resample_8to16(int8_t* input_samples, +void _x_audio_out_resample_8to16(int8_t* input_samples, int16_t* output_samples, uint32_t samples) { while( samples-- ) { int16_t os; - + os = *input_samples++; os = (os - 0x80) << 8; *output_samples++ = os; } } -void _x_audio_out_resample_16to8(int16_t* input_samples, +void _x_audio_out_resample_16to8(int16_t* input_samples, int8_t* output_samples, uint32_t samples) { while( samples-- ) { int16_t os; - + os = *input_samples++; os = (os >> 8) + 0x80; *output_samples++ = os; } } -void _x_audio_out_resample_monotostereo(int16_t* input_samples, +void _x_audio_out_resample_monotostereo(int16_t* input_samples, int16_t* output_samples, uint32_t frames) { while( frames-- ) { int16_t os; - + os = *input_samples++; *output_samples++ = os; *output_samples++ = os; } } -void _x_audio_out_resample_stereotomono(int16_t* input_samples, +void _x_audio_out_resample_stereotomono(int16_t* input_samples, int16_t* output_samples, uint32_t frames) { while( frames-- ) { int16_t os; - + os = (*input_samples++)>>1; os += (*input_samples++)>>1; *output_samples++ = os; diff --git a/src/xine-engine/resample.h b/src/xine-engine/resample.h index 40b4de486..842434cf0 100644 --- a/src/xine-engine/resample.h +++ b/src/xine-engine/resample.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -28,35 +28,35 @@ #define RESAMPLE_MAX_CHANNELS 6 void _x_audio_out_resample_stereo(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; void _x_audio_out_resample_mono(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; void _x_audio_out_resample_4channel(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; void _x_audio_out_resample_5channel(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; void _x_audio_out_resample_6channel(int16_t* last_sample, - int16_t* input_samples, uint32_t in_samples, + int16_t* input_samples, uint32_t in_samples, int16_t* output_samples, uint32_t out_samples) XINE_PROTECTED; -void _x_audio_out_resample_8to16(int8_t* input_samples, +void _x_audio_out_resample_8to16(int8_t* input_samples, int16_t* output_samples, uint32_t samples) XINE_PROTECTED; -void _x_audio_out_resample_16to8(int16_t* input_samples, +void _x_audio_out_resample_16to8(int16_t* input_samples, int8_t* output_samples, uint32_t samples) XINE_PROTECTED; -void _x_audio_out_resample_monotostereo(int16_t* input_samples, +void _x_audio_out_resample_monotostereo(int16_t* input_samples, int16_t* output_samples, uint32_t frames) XINE_PROTECTED; -void _x_audio_out_resample_stereotomono(int16_t* input_samples, +void _x_audio_out_resample_stereotomono(int16_t* input_samples, int16_t* output_samples, uint32_t frames) XINE_PROTECTED; - + #endif diff --git a/src/xine-engine/scratch.c b/src/xine-engine/scratch.c index 38b606b84..39bb5927a 100644 --- a/src/xine-engine/scratch.c +++ b/src/xine-engine/scratch.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -37,7 +37,7 @@ #include "xineutils.h" #include "scratch.h" -static void __attribute__((__format__(__printf__, 2, 0))) +static void XINE_FORMAT_PRINTF(2, 0) scratch_printf (scratch_buffer_t *this, const char *format, va_list argp) { time_t t; @@ -50,12 +50,11 @@ static void __attribute__((__format__(__printf__, 2, 0))) localtime_r (&t, &tm); if ( ! this->lines[this->cur] ) - this->lines[this->cur] = xine_xmalloc(SCRATCH_LINE_LEN_MAX+1); + this->lines[this->cur] = malloc(SCRATCH_LINE_LEN_MAX+1); if ( ! this->lines[this->cur] ) return; - strftime (this->lines[this->cur], SCRATCH_LINE_LEN_MAX, "%X: ", &tm); - l = strlen (this->lines[this->cur]); + l = strftime (this->lines[this->cur], SCRATCH_LINE_LEN_MAX, "%X: ", &tm); vsnprintf (this->lines[this->cur] + l, SCRATCH_LINE_LEN_MAX - l, format, argp); lprintf ("printing format %s to line %d\n", format, this->cur); @@ -86,14 +85,14 @@ static char **scratch_get_content (scratch_buffer_t *this) { static void scratch_dispose (scratch_buffer_t *this) { int i; - + pthread_mutex_lock (&this->lock); for(i = 0; i < this->num_lines; i++ ) { free(this->ordered[i]); free(this->lines[i]); } - + free (this->lines); free (this->ordered); @@ -105,15 +104,11 @@ static void scratch_dispose (scratch_buffer_t *this) { scratch_buffer_t *_x_new_scratch_buffer (int num_lines) { scratch_buffer_t *this; - int i; - - this = xine_xmalloc (sizeof (scratch_buffer_t)); - this->lines = xine_xmalloc (sizeof (char *) * (num_lines + 1)); - this->ordered = xine_xmalloc (sizeof (char *) * (num_lines + 1)); + this = calloc(1, sizeof(scratch_buffer_t)); - for (i = 0; i <= num_lines; i++) - this->lines[i] = this->ordered[i] = NULL; + this->lines = calloc ((num_lines + 1), sizeof(char*)); + this->ordered = calloc ((num_lines + 1), sizeof(char*)); this->scratch_printf = scratch_printf; this->get_content = scratch_get_content; diff --git a/src/xine-engine/scratch.h b/src/xine-engine/scratch.h index c0e591d31..c0c927b97 100644 --- a/src/xine-engine/scratch.h +++ b/src/xine-engine/scratch.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -32,10 +32,7 @@ typedef struct scratch_buffer_s scratch_buffer_t; struct scratch_buffer_s { - void -#if __GNUC__ >= 3 - __attribute__((__format__(__printf__, 2, 0))) -#endif + void XINE_FORMAT_PRINTF(2, 0) (*scratch_printf) (scratch_buffer_t *this, const char *format, va_list ap); char **(*get_content) (scratch_buffer_t *this); @@ -51,6 +48,6 @@ struct scratch_buffer_s { pthread_mutex_t lock; }; -scratch_buffer_t *_x_new_scratch_buffer (int num_lines) XINE_PROTECTED; +scratch_buffer_t *_x_new_scratch_buffer (int num_lines) XINE_MALLOC XINE_PROTECTED; #endif diff --git a/src/xine-engine/spu_decoder.h b/src/xine-engine/spu_decoder.h index 66ab5e54a..4897a32a2 100644 --- a/src/xine-engine/spu_decoder.h +++ b/src/xine-engine/spu_decoder.h @@ -4,7 +4,7 @@ * Copyright (C) James Courtier-Dutton James@superbug.demon.co.uk - July 2001 * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -14,10 +14,10 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to - * the Free Software Foundation, + * the Free Software Foundation, * */ @@ -47,30 +47,30 @@ struct spu_decoder_class_s { * open a new instance of this plugin class */ spu_decoder_t* (*open_plugin) (spu_decoder_class_t *this, xine_stream_t *stream); - + /* * return short, human readable identifier for this plugin class */ char* (*get_identifier) (spu_decoder_class_t *this); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ char* (*get_description) (spu_decoder_class_t *this); - + /* * free all class-related resources */ void (*dispose) (spu_decoder_class_t *this); }; - - + + struct spu_decoder_s { /* * decode data from buf and feed the overlay to overlay manager - */ + */ void (*decode_data) (spu_decoder_t *this, buf_element_t *buf); /* @@ -78,7 +78,7 @@ struct spu_decoder_s { * SPU data not related to recently decoded data) */ void (*reset) (spu_decoder_t *this); - + /* * inform decoder that a time reference discontinuity has happened. * that is, it must forget any currently held pts value diff --git a/src/xine-engine/tvmode.c b/src/xine-engine/tvmode.c index 099bdb808..1d6660f4f 100644 --- a/src/xine-engine/tvmode.c +++ b/src/xine-engine/tvmode.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-engine/video_decoder.c b/src/xine-engine/video_decoder.c index c88e01714..0756fc5b2 100644 --- a/src/xine-engine/video_decoder.c +++ b/src/xine-engine/video_decoder.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2005 the xine project * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -45,13 +45,13 @@ static void update_spu_decoder (xine_stream_t *stream, int type) { int streamtype = (type>>16) & 0xFF; - + if( stream->spu_decoder_streamtype != streamtype || !stream->spu_decoder_plugin ) { - + if (stream->spu_decoder_plugin) _x_free_spu_decoder (stream, stream->spu_decoder_plugin); - + stream->spu_decoder_streamtype = streamtype; stream->spu_decoder_plugin = _x_get_spu_decoder (stream, streamtype); @@ -63,27 +63,27 @@ int _x_spu_decoder_sleep(xine_stream_t *stream, int64_t next_spu_vpts) { int64_t time, wait; int thread_vacant = 1; - + /* we wait until one second before the next SPU is due */ next_spu_vpts -= 90000; - + do { if (next_spu_vpts) time = stream->xine->clock->get_current_time(stream->xine->clock); else time = 0; - + /* wait in pieces of one half second */ if (next_spu_vpts - time < SPU_SLEEP_INTERVAL) wait = next_spu_vpts - time; else wait = SPU_SLEEP_INTERVAL; - + if (wait > 0) xine_usec_sleep(wait * 11); - + if (stream->xine->port_ticket->ticket_revoked) stream->xine->port_ticket->renew(stream->xine->port_ticket, 0); - + /* never wait, if we share the thread with a video decoder */ thread_vacant = !stream->video_decoder_plugin; /* we have to return if video out calls for the decoder */ @@ -92,9 +92,9 @@ int _x_spu_decoder_sleep(xine_stream_t *stream, int64_t next_spu_vpts) /* we have to return if the demuxer needs us to release a buffer */ if (thread_vacant) thread_vacant = !stream->demux_action_pending; - + } while (wait == SPU_SLEEP_INTERVAL && thread_vacant); - + return thread_vacant; } @@ -117,7 +117,7 @@ static void *video_decoder_loop (void *stream_gen) { */ nice(-1); #endif /* WIN32 */ - + if (prof_video_decode == -1) prof_video_decode = xine_profiler_allocate_slot ("video decoder"); if (prof_spu_decode == -1) @@ -125,15 +125,15 @@ static void *video_decoder_loop (void *stream_gen) { while (running) { - lprintf ("getting buffer...\n"); + lprintf ("getting buffer...\n"); buf = stream->video_fifo->get (stream->video_fifo); - + _x_extra_info_merge( stream->video_decoder_extra_info, buf->extra_info ); stream->video_decoder_extra_info->seek_count = stream->video_seek_count; - - lprintf ("got buffer 0x%08x\n", buf->type); - + + lprintf ("got buffer 0x%08x\n", buf->type); + switch (buf->type & 0xffff0000) { case BUF_CONTROL_HEADERS_DONE: pthread_mutex_lock (&stream->counter_lock); @@ -143,34 +143,34 @@ static void *video_decoder_loop (void *stream_gen) { break; case BUF_CONTROL_START: - + /* decoder dispose might call port functions */ running_ticket->acquire(running_ticket, 0); - + if (stream->video_decoder_plugin) { _x_free_video_decoder (stream, stream->video_decoder_plugin); stream->video_decoder_plugin = NULL; } - + if (stream->spu_decoder_plugin) { _x_free_spu_decoder (stream, stream->spu_decoder_plugin); stream->spu_decoder_plugin = NULL; stream->spu_track_map_entries = 0; } - + running_ticket->release(running_ticket, 0); - - if( !stream->gapless_switch ) - stream->metronom->handle_video_discontinuity (stream->metronom, + + if( !(buf->decoder_flags & BUF_FLAG_GAPLESS_SW) ) + stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSTART, 0); - + buftype_unknown = 0; break; case BUF_CONTROL_SPU_CHANNEL: { xine_event_t ui_event; - + /* We use widescreen spu as the auto selection, because widescreen * display is common. SPU decoders can choose differently if it suits * them. */ @@ -179,7 +179,7 @@ static void *video_decoder_loop (void *stream_gen) { stream->spu_channel_pan_scan = buf->decoder_info[2]; if (stream->spu_channel_user == -1) stream->spu_channel = stream->spu_channel_auto; - + /* Inform UI of SPU channel changes */ ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED; ui_event.data_length = 0; @@ -189,7 +189,7 @@ static void *video_decoder_loop (void *stream_gen) { break; case BUF_CONTROL_END: - + /* flush decoder frames if stream finished naturally (non-user stop) */ if( buf->decoder_flags ) { running_ticket->acquire(running_ticket, 0); @@ -210,12 +210,12 @@ static void *video_decoder_loop (void *stream_gen) { */ while(1) { int num_bufs, num_streams; - + running_ticket->acquire(running_ticket, 0); num_bufs = stream->video_out->get_property(stream->video_out, VO_PROP_BUFS_IN_FIFO); num_streams = stream->video_out->get_property(stream->video_out, VO_PROP_NUM_STREAMS); running_ticket->release(running_ticket, 0); - + if( num_bufs > 0 && num_streams == 1 && !stream->early_finish_event && stream->master == stream ) xine_usec_sleep (10000); @@ -229,7 +229,7 @@ static void *video_decoder_loop (void *stream_gen) { stream->finished_count_video++; - lprintf ("reached end marker # %d\n", + lprintf ("reached end marker # %d\n", stream->finished_count_video); pthread_cond_broadcast (&stream->counter_changed); @@ -246,7 +246,7 @@ static void *video_decoder_loop (void *stream_gen) { pthread_cond_timedwait (&stream->counter_changed, &stream->counter_lock, &ts); } } - + pthread_mutex_unlock (&stream->counter_lock); /* Wake up xine_play if it's waiting for a frame */ @@ -261,7 +261,7 @@ static void *video_decoder_loop (void *stream_gen) { case BUF_CONTROL_QUIT: /* decoder dispose might call port functions */ running_ticket->acquire(running_ticket, 0); - + if (stream->video_decoder_plugin) { _x_free_video_decoder (stream, stream->video_decoder_plugin); stream->video_decoder_plugin = NULL; @@ -297,7 +297,7 @@ static void *video_decoder_loop (void *stream_gen) { running_ticket->release(running_ticket, 0); } break; - + case BUF_CONTROL_DISCONTINUITY: lprintf ("discontinuity ahead\n"); @@ -309,11 +309,11 @@ static void *video_decoder_loop (void *stream_gen) { stream->video_decoder_plugin->discontinuity (stream->video_decoder_plugin); running_ticket->release(running_ticket, 0); } - + stream->metronom->handle_video_discontinuity (stream->metronom, DISC_RELATIVE, buf->disc_off); break; - + case BUF_CONTROL_NEWPTS: lprintf ("new pts %"PRId64"\n", buf->disc_off); @@ -325,14 +325,14 @@ static void *video_decoder_loop (void *stream_gen) { stream->video_decoder_plugin->discontinuity (stream->video_decoder_plugin); running_ticket->release(running_ticket, 0); } - + if (buf->decoder_flags & BUF_FLAG_SEEK) { stream->metronom->handle_video_discontinuity (stream->metronom, DISC_STREAMSEEK, buf->disc_off); } else { stream->metronom->handle_video_discontinuity (stream->metronom, DISC_ABSOLUTE, buf->disc_off); - } + } break; - + case BUF_CONTROL_AUDIO_CHANNEL: { xine_event_t ui_event; @@ -345,7 +345,7 @@ static void *video_decoder_loop (void *stream_gen) { case BUF_CONTROL_NOP: break; - + default: if ( (buf->type & 0xFF000000) == BUF_VIDEO_BASE ) { @@ -354,43 +354,43 @@ static void *video_decoder_loop (void *stream_gen) { break; xine_profiler_start_count (prof_video_decode); - + running_ticket->acquire(running_ticket, 0); - + /* - printf ("video_decoder: got package %d, decoder_info[0]:%d\n", + printf ("video_decoder: got package %d, decoder_info[0]:%d\n", buf, buf->decoder_info[0]); - */ - + */ + streamtype = (buf->type>>16) & 0xFF; - + if( buf->type != buftype_unknown && (stream->video_decoder_streamtype != streamtype || !stream->video_decoder_plugin) ) { - + if (stream->video_decoder_plugin) { _x_free_video_decoder (stream, stream->video_decoder_plugin); } - + stream->video_decoder_streamtype = streamtype; stream->video_decoder_plugin = _x_get_video_decoder (stream, streamtype); - + _x_stream_info_set(stream, XINE_STREAM_INFO_VIDEO_HANDLED, (stream->video_decoder_plugin != NULL)); } if (stream->video_decoder_plugin) - stream->video_decoder_plugin->decode_data (stream->video_decoder_plugin, buf); - - if (buf->type != buftype_unknown && + stream->video_decoder_plugin->decode_data (stream->video_decoder_plugin, buf); + + if (buf->type != buftype_unknown && !_x_stream_info_get(stream, XINE_STREAM_INFO_VIDEO_HANDLED)) { - xine_log (stream->xine, XINE_LOG_MSG, + xine_log (stream->xine, XINE_LOG_MSG, _("video_decoder: no plugin available to handle '%s'\n"), _x_buf_video_name( buf->type ) ); - + if( !_x_meta_info_get(stream, XINE_META_INFO_VIDEOCODEC)) _x_meta_info_set_utf8(stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name( buf->type )); - + buftype_unknown = buf->type; - + /* fatal error - dispose plugin */ if (stream->video_decoder_plugin) { _x_free_video_decoder (stream, stream->video_decoder_plugin); @@ -401,7 +401,7 @@ static void *video_decoder_loop (void *stream_gen) { if (running_ticket->ticket_revoked) running_ticket->renew(running_ticket, 0); running_ticket->release(running_ticket, 0); - + xine_profiler_stop_count (prof_video_decode); } else if ( (buf->type & 0xFF000000) == BUF_SPU_BASE ) { @@ -414,15 +414,15 @@ static void *video_decoder_loop (void *stream_gen) { xine_profiler_start_count (prof_spu_decode); running_ticket->acquire(running_ticket, 0); - + update_spu_decoder(stream, buf->type); /* update track map */ i = 0; - while ( (i<stream->spu_track_map_entries) && (stream->spu_track_map[i]<buf->type) ) + while ( (i<stream->spu_track_map_entries) && (stream->spu_track_map[i]<buf->type) ) i++; - + if ( (i==stream->spu_track_map_entries) || (stream->spu_track_map[i] != buf->type) ) { xine_event_t ui_event; @@ -458,15 +458,15 @@ static void *video_decoder_loop (void *stream_gen) { if (running_ticket->ticket_revoked) running_ticket->renew(running_ticket, 0); running_ticket->release(running_ticket, 0); - + xine_profiler_stop_count (prof_spu_decode); } else if (buf->type != buftype_unknown) { - xine_log (stream->xine, XINE_LOG_MSG, + xine_log (stream->xine, XINE_LOG_MSG, _("video_decoder: error, unknown buffer type: %08x\n"), buf->type ); buftype_unknown = buf->type; } - + break; } @@ -478,13 +478,13 @@ static void *video_decoder_loop (void *stream_gen) { } int _x_video_decoder_init (xine_stream_t *stream) { - + if (stream->video_out == NULL) { stream->video_fifo = _x_dummy_fifo_buffer_new (5, 8192); stream->spu_track_map_entries = 0; return 1; } else { - + pthread_attr_t pth_attrs; struct sched_param pth_params; int err, num_buffers; @@ -495,7 +495,7 @@ int _x_video_decoder_init (xine_stream_t *stream) { * We provide buffers of 8k size instead of 2k for demuxers sending * larger chunks. */ - + num_buffers = stream->xine->config->register_num (stream->xine->config, "engine.buffers.video_num_buffers", 500, @@ -505,15 +505,15 @@ int _x_video_decoder_init (xine_stream_t *stream) { "mean smoother playback for unreliable inputs, but " "also increased latency and memory consumption."), 20, NULL, NULL); - + stream->video_fifo = _x_fifo_buffer_new (num_buffers, 8192); if (stream->video_fifo == NULL) { xine_log(stream->xine, XINE_LOG_MSG, "video_decoder: can't allocated video fifo\n"); return 0; } - + stream->spu_track_map_entries = 0; - + pthread_attr_init(&pth_attrs); pthread_attr_getschedparam(&pth_attrs, &pth_params); pth_params.sched_priority = sched_get_priority_min(SCHED_OTHER); @@ -529,7 +529,7 @@ int _x_video_decoder_init (xine_stream_t *stream) { pthread_attr_destroy(&pth_attrs); return 0; } - + pthread_attr_destroy(&pth_attrs); } return 1; @@ -561,7 +561,7 @@ void _x_video_decoder_shutdown (xine_stream_t *stream) { lprintf ("shutdown...4\n"); } - + stream->video_fifo->dispose (stream->video_fifo); stream->video_fifo = NULL; } diff --git a/src/xine-engine/video_decoder.h b/src/xine-engine/video_decoder.h index 7b13159a3..f7068cc13 100644 --- a/src/xine-engine/video_decoder.h +++ b/src/xine-engine/video_decoder.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -47,14 +47,14 @@ struct video_decoder_class_s { * open a new instance of this plugin class */ video_decoder_t* (*open_plugin) (video_decoder_class_t *this, xine_stream_t *stream); - + /* * return short, human readable identifier for this plugin class */ char* (*get_identifier) (video_decoder_class_t *this); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ char* (*get_description) (video_decoder_class_t *this); @@ -69,8 +69,8 @@ struct video_decoder_class_s { struct video_decoder_s { /* - * decode data from buf and feed decoded frames to - * video output + * decode data from buf and feed decoded frames to + * video output */ void (*decode_data) (video_decoder_t *this, buf_element_t *buf); @@ -79,13 +79,13 @@ struct video_decoder_s { * video data not related to recently decoded data) */ void (*reset) (video_decoder_t *this); - + /* * inform decoder that a time reference discontinuity has happened. * that is, it must forget any currently held pts value */ void (*discontinuity) (video_decoder_t *this); - + /* * flush out any frames that are still stored in the decoder */ @@ -94,7 +94,7 @@ struct video_decoder_s { /* * close down, free all resources */ - void (*dispose) (video_decoder_t *this); + void (*dispose) (video_decoder_t *this); void *node; /*used by plugin loader */ diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index a8464ac40..0b6d8f7a1 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -57,10 +57,10 @@ #define FIRST_FRAME_POLL_DELAY 3000 #define FIRST_FRAME_MAX_POLL 10 /* poll n times at most */ -/* experimental optimization: try to allocate frames from free queue +/* experimental optimization: try to allocate frames from free queue * in the same format as requested (avoid unnecessary free/alloc in * vo driver). up to 25% less cpu load using deinterlace with film mode. - */ + */ #define EXPERIMENTAL_FRAME_QUEUE_OPTIMIZATION 1 static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ); @@ -77,7 +77,7 @@ typedef struct { } img_buf_fifo_t; typedef struct { - + xine_video_port_t vo; /* public part */ vo_driver_t *driver; @@ -86,7 +86,7 @@ typedef struct { metronom_clock_t *clock; xine_list_t *streams; pthread_mutex_t streams_lock; - + img_buf_fifo_t *free_img_buf_queue; img_buf_fifo_t *display_img_buf_queue; @@ -105,7 +105,7 @@ typedef struct { uint32_t redraw_needed:3; int discard_frames; - + pthread_t video_thread; int num_frames_delivered; @@ -118,7 +118,7 @@ typedef struct { int warn_threshold_exceeded; /* pts value when decoder delivered last video frame */ - int64_t last_delivery_pts; + int64_t last_delivery_pts; video_overlay_manager_t *overlay_source; @@ -139,11 +139,11 @@ typedef struct { * frame queue (fifo) util functions */ -static img_buf_fifo_t *vo_new_img_buf_queue () { +static img_buf_fifo_t *XINE_MALLOC vo_new_img_buf_queue () { img_buf_fifo_t *queue; - queue = (img_buf_fifo_t *) xine_xmalloc (sizeof (img_buf_fifo_t)); + queue = (img_buf_fifo_t *) calloc(1, sizeof(img_buf_fifo_t)); if( queue ) { queue->first = NULL; queue->last = NULL; @@ -215,7 +215,7 @@ static vo_frame_t *vo_remove_from_img_buf_queue_int (img_buf_fifo_t *queue, int img = img->next; i++; } - + if( width && height ) { if( !img ) { if( queue->num_buffers == 1 && !blocking && queue->num_buffers_max > 8) { @@ -263,7 +263,7 @@ static vo_frame_t *vo_remove_from_img_buf_queue_int (img_buf_fifo_t *queue, int if( img == queue->last ) queue->last = previous; } - + img->next = NULL; if (!queue->first) { queue->last = NULL; @@ -272,7 +272,7 @@ static vo_frame_t *vo_remove_from_img_buf_queue_int (img_buf_fifo_t *queue, int queue->num_buffers--; } } - + return img; } @@ -303,7 +303,7 @@ static vo_frame_t *vo_remove_from_img_buf_queue_nonblock (img_buf_fifo_t *queue, * functions to maintain lock_counter */ static void vo_frame_inc_lock (vo_frame_t *img) { - + pthread_mutex_lock (&img->mutex); img->lock_counter++; @@ -312,11 +312,11 @@ static void vo_frame_inc_lock (vo_frame_t *img) { } static void vo_frame_dec_lock (vo_frame_t *img) { - + pthread_mutex_lock (&img->mutex); img->lock_counter--; - if (!img->lock_counter) { + if (!img->lock_counter) { vos_t *this = (vos_t *) img->port; if (img->stream) _x_refcounter_dec(img->stream->refcounter); @@ -333,11 +333,11 @@ static void vo_frame_driver_proc(vo_frame_t *img) img->proc_frame(img); } if (img->proc_called) return; - + if (img->proc_slice) { int height = img->height; uint8_t* src[3]; - + switch (img->format) { case XINE_IMGFMT_YV12: src[0] = img->base[0]; @@ -362,7 +362,7 @@ static void vo_frame_driver_proc(vo_frame_t *img) } /* - * + * * functions called by video decoder: * * get_frame => alloc frame for rendering @@ -393,7 +393,7 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen, /* some decoders report strange ratios */ if (ratio <= 0.0) ratio = (double)width / (double)height; - + pthread_mutex_lock (&img->mutex); img->lock_counter = 1; img->width = width; @@ -418,11 +418,11 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen, /* let driver ensure this image has the right format */ - this->driver->update_frame_format (this->driver, img, width, height, + this->driver->update_frame_format (this->driver, img, width, height, ratio, format, flags); pthread_mutex_unlock (&img->mutex); - + lprintf ("get_frame (%d x %d) done\n", width, height); return img; @@ -439,11 +439,11 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { /* handle anonymous streams like NULL for easy checking */ if (stream == XINE_ANON_STREAM) stream = NULL; - + img->stream = stream; this->current_width = img->width; this->current_height = img->height; - + if (stream) { _x_refcounter_inc(stream->refcounter); _x_extra_info_merge( img->extra_info, stream->video_decoder_extra_info ); @@ -465,13 +465,13 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { this->num_frames_delivered++; diff = pic_vpts - cur_vpts; - + /* avoid division by zero */ if( img->duration <= 0 ) duration = DEFAULT_FRAME_DURATION; else duration = img->duration; - + /* Frame dropping slow start: * The engine starts to drop frames if there are less than frame_drop_limit * frames in advance. There might be a problem just after a seek because @@ -497,7 +497,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { if (this->display_img_buf_queue->num_buffers >= this->frame_drop_limit || frames_to_skip < 0) frames_to_skip = 0; - + /* Do not drop frames immediately, but remember this as suggestion and give * decoder a further chance to supply frames. * This avoids unnecessary frame drops in situations where there is only @@ -515,7 +515,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { lprintf ("delivery diff : %" PRId64 ", current vpts is %" PRId64 ", %d frames to skip\n", diff, cur_vpts, frames_to_skip); - + } else { frames_to_skip = 0; @@ -528,18 +528,18 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { if (!img->bad_frame) { - + int img_already_locked = 0; xine_list_iterator_t ite; - + /* add cropping requested by frontend */ img->crop_left += this->crop_left; img->crop_right += this->crop_right; img->crop_top += this->crop_top; img->crop_bottom += this->crop_bottom; - + /* perform cropping when vo driver does not support it */ - if( (img->crop_left || img->crop_top || + if( (img->crop_left || img->crop_top || img->crop_right || img->crop_bottom) && (this->grab_only || !(this->driver->get_capabilities (this->driver) & VO_CAP_CROP)) ) { @@ -556,11 +556,11 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { img->crop_bottom = 0; } } - + /* do not call proc_*() for frames that will be dropped */ if( !frames_to_skip && !img->proc_called ) vo_frame_driver_proc(img); - + /* * put frame into FIFO-Buffer */ @@ -594,7 +594,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { if (!img_already_locked) vo_frame_inc_lock( img ); vo_append_to_img_buf_queue (this->display_img_buf_queue, img); - + } else { lprintf ("bad_frame\n"); @@ -626,7 +626,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { /* make sure threshold has being consistently exceeded - 5 times in a row * (that is, this is not just a small burst of dropped frames). */ - send_event = (this->warn_threshold_exceeded == 5 && + send_event = (this->warn_threshold_exceeded == 5 && !this->warn_threshold_event_sent); this->warn_threshold_event_sent = send_event; @@ -635,7 +635,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { ite = xine_list_next(this->streams, ite)) { stream = xine_list_get_value(this->streams, ite); if (stream == XINE_ANON_STREAM) continue; - _x_stream_info_set(stream, XINE_STREAM_INFO_SKIPPED_FRAMES, + _x_stream_info_set(stream, XINE_STREAM_INFO_SKIPPED_FRAMES, 1000 * this->num_frames_skipped / this->num_frames_delivered); _x_stream_info_set(stream, XINE_STREAM_INFO_DISCARDED_FRAMES, 1000 * this->num_frames_discarded / this->num_frames_delivered); @@ -663,8 +663,8 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { if( this->num_frames_skipped || this->num_frames_discarded ) { xine_log(this->xine, XINE_LOG_MSG, - _("%d frames delivered, %d frames skipped, %d frames discarded\n"), - this->num_frames_delivered, + _("%d frames delivered, %d frames skipped, %d frames discarded\n"), + this->num_frames_delivered, this->num_frames_skipped, this->num_frames_discarded); } @@ -672,7 +672,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { this->num_frames_discarded = 0; this->num_frames_skipped = 0; } - + return frames_to_skip; } @@ -682,9 +682,9 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { * */ -/* duplicate_frame(): this function is used to keep playing frames - * while video is still or player paused. - * +/* duplicate_frame(): this function is used to keep playing frames + * while video is still or player paused. + * * frame allocation inside vo loop is dangerous: * we must never wait for a free frame -> deadlock condition. * to avoid deadlocks we don't use vo_remove_from_img_buf_queue() @@ -709,7 +709,7 @@ static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) { else { this->free_img_buf_queue->num_buffers--; } - + pthread_mutex_lock (&dupl->mutex); dupl->lock_counter = 1; dupl->width = img->width; @@ -726,16 +726,16 @@ static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) { dupl->crop_bottom = img->crop_bottom; dupl->overlay_offset_x = img->overlay_offset_x; dupl->overlay_offset_y = img->overlay_offset_y; - - this->driver->update_frame_format (this->driver, dupl, dupl->width, dupl->height, + + this->driver->update_frame_format (this->driver, dupl, dupl->width, dupl->height, dupl->ratio, dupl->format, dupl->flags); pthread_mutex_unlock (&dupl->mutex); - + if (dupl->proc_duplicate_frame_data) { dupl->proc_duplicate_frame_data(dupl,img); } else { - + switch (img->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( @@ -761,8 +761,8 @@ static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) { img->width, img->height); break; } - } - + } + dupl->bad_frame = 0; dupl->pts = 0; dupl->vpts = 0; @@ -773,10 +773,10 @@ static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) { dupl->stream = NULL; memcpy( dupl->extra_info, img->extra_info, sizeof(extra_info_t) ); - + /* delay frame processing for now, we might not even need it (eg. frame will be discarded) */ /* vo_frame_driver_proc(dupl); */ - + return dupl; } @@ -789,7 +789,7 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { int duration; pthread_mutex_lock(&this->display_img_buf_queue->mutex); - + img = this->display_img_buf_queue->first; /* @@ -806,7 +806,7 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { /* * before displaying the first frame without - * "metronom prebuffering" we should make sure it's + * "metronom prebuffering" we should make sure it's * not used as a decoder reference anymore. */ if( img->lock_counter == 1 ) { @@ -828,21 +828,21 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { duration = DEFAULT_FRAME_DURATION; } else duration = img->duration; - + pts = img->vpts; diff = cur_vpts - pts; - + if (diff > duration || this->discard_frames) { - + if( !this->discard_frames ) { xine_log(this->xine, XINE_LOG_MSG, _("video_out: throwing away image with pts %" PRId64 " because it's too old (diff : %" PRId64 ").\n"), pts, diff); this->num_frames_discarded++; } - + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); - + if (img->stream) { pthread_mutex_lock( &img->stream->current_extra_info_lock ); _x_extra_info_merge( img->stream->current_extra_info, img->extra_info ); @@ -851,21 +851,21 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { /* when flushing frames, keep the first one as backup */ if( this->discard_frames ) { - + if (!this->img_backup) { this->img_backup = img; } else { vo_frame_dec_lock( img ); - } - + } + } else { /* - * last frame? back it up for + * last frame? back it up for * still frame creation */ - + if (!this->display_img_buf_queue->first) { - + if (this->img_backup) { lprintf("overwriting frame backup\n"); @@ -875,20 +875,20 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { lprintf("possible still frame (old)\n"); this->img_backup = img; - - /* wait 4 frames before drawing this one. + + /* wait 4 frames before drawing this one. this allow slower systems to recover. */ - this->redraw_needed = 4; + this->redraw_needed = 4; } else { vo_frame_dec_lock( img ); } } img = this->display_img_buf_queue->first; - + } else break; } - + pthread_mutex_unlock(&this->display_img_buf_queue->mutex); } @@ -897,16 +897,16 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) { */ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, int64_t *next_frame_vpts) { - + vo_frame_t *img; pthread_mutex_lock(&this->display_img_buf_queue->mutex); - + img = this->display_img_buf_queue->first; *next_frame_vpts = 0; - /* + /* * still frame detection: */ @@ -931,11 +931,11 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, /* extra info of the backup is thrown away, because it is not up to date */ _x_extra_info_reset(img->extra_info); } - + return img; } else { - + if( this->redraw_needed ) this->redraw_needed--; @@ -967,13 +967,13 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, vo_frame_dec_lock( this->img_backup ); this->img_backup = NULL; } - - /* - * last frame? make backup for possible still image + + /* + * last frame? make backup for possible still image */ pthread_mutex_lock( &this->free_img_buf_queue->mutex ); if (img && !img->next) { - + if (!img->stream || _x_stream_info_get(img->stream, XINE_STREAM_INFO_VIDEO_HAS_STILL) || !img->stream->video_fifo || @@ -989,7 +989,7 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, /* * remove frame from display queue and show it */ - + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); pthread_mutex_unlock(&this->display_img_buf_queue->mutex); @@ -997,7 +997,7 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, } } -static void overlay_and_display_frame (vos_t *this, +static void overlay_and_display_frame (vos_t *this, vo_frame_t *img, int64_t vpts) { xine_stream_t *stream; xine_list_iterator_t ite; @@ -1009,19 +1009,19 @@ static void overlay_and_display_frame (vos_t *this, */ if(!img->proc_called ) vo_frame_driver_proc(img); - + if (img->stream) { int64_t diff; pthread_mutex_lock( &img->stream->current_extra_info_lock ); diff = img->extra_info->vpts - img->stream->current_extra_info->vpts; - if ((diff > 3000) || (diff<-300000)) + if ((diff > 3000) || (diff<-300000)) _x_extra_info_merge( img->stream->current_extra_info, img->extra_info ); pthread_mutex_unlock( &img->stream->current_extra_info_lock ); } if (this->overlay_source) { - this->overlay_source->multiple_overlay_blend (this->overlay_source, - vpts, + this->overlay_source->multiple_overlay_blend (this->overlay_source, + vpts, this->driver, img, this->video_loop_running && this->overlay_enabled); } @@ -1034,7 +1034,7 @@ static void overlay_and_display_frame (vos_t *this, this->last_frame = img; this->driver->display_frame (this->driver, img); - + /* * Wake up xine_play if it's waiting for a frame */ @@ -1054,16 +1054,16 @@ static void overlay_and_display_frame (vos_t *this, pthread_mutex_unlock(&this->streams_lock); } - this->redraw_needed = 0; + this->redraw_needed = 0; } static void check_redraw_needed (vos_t *this, int64_t vpts) { if (this->overlay_source) { if( this->overlay_source->redraw_needed (this->overlay_source, vpts) ) - this->redraw_needed = 1; + this->redraw_needed = 1; } - + if( this->driver->redraw_needed (this->driver) ) this->redraw_needed = 1; } @@ -1071,36 +1071,36 @@ static void check_redraw_needed (vos_t *this, int64_t vpts) { /* special loop for paused mode * needed to update screen due overlay changes, resize, window * movement, brightness adjusting etc. - */ + */ static void paused_loop( vos_t *this, int64_t vpts ) { vo_frame_t *img; - + pthread_mutex_lock( &this->free_img_buf_queue->mutex ); /* prevent decoder thread from allocating new frames */ this->free_img_buf_queue->locked_for_read = 1; - + while (this->clock->speed == XINE_SPEED_PAUSE && this->video_loop_running) { - + /* we need at least one free frame to keep going */ if( this->display_img_buf_queue->first && !this->free_img_buf_queue->first ) { - + img = vo_remove_from_img_buf_queue (this->display_img_buf_queue); img->next = NULL; this->free_img_buf_queue->first = img; this->free_img_buf_queue->last = img; this->free_img_buf_queue->num_buffers = 1; } - + /* set img_backup to play the same frame several times */ if( this->display_img_buf_queue->first && !this->img_backup ) { this->img_backup = vo_remove_from_img_buf_queue (this->display_img_buf_queue); this->redraw_needed = 1; } - + check_redraw_needed( this, vpts ); - + if( this->redraw_needed && this->img_backup ) { img = duplicate_frame (this, this->img_backup ); if( img ) { @@ -1109,16 +1109,16 @@ static void paused_loop( vos_t *this, int64_t vpts ) pthread_mutex_unlock( &this->free_img_buf_queue->mutex ); overlay_and_display_frame (this, img, vpts); pthread_mutex_lock( &this->free_img_buf_queue->mutex ); - } + } } - + pthread_mutex_unlock( &this->free_img_buf_queue->mutex ); xine_usec_sleep (20000); pthread_mutex_lock( &this->free_img_buf_queue->mutex ); } - + this->free_img_buf_queue->locked_for_read = 0; - + if( this->free_img_buf_queue->first ) pthread_cond_signal (&this->free_img_buf_queue->not_empty); pthread_mutex_unlock( &this->free_img_buf_queue->mutex ); @@ -1131,7 +1131,7 @@ static void *video_out_loop (void *this_gen) { vos_t *this = (vos_t *) this_gen; int64_t next_frame_vpts = 0; int64_t usec_to_sleep; - + #ifndef WIN32 /* nice(-value) will fail silently for normal users. * however when running as root this may provide smoother @@ -1145,7 +1145,7 @@ static void *video_out_loop (void *this_gen) { * here it is - the heart of xine (or rather: one of the hearts * of xine) : the video output loop */ - + lprintf ("loop starting...\n"); while ( this->video_loop_running ) { @@ -1185,7 +1185,7 @@ static void *video_out_loop (void *this_gen) { diff = vpts - this->last_delivery_pts; if (diff > 30000 && !this->display_img_buf_queue->first) { xine_list_iterator_t ite; - + pthread_mutex_lock(&this->streams_lock); for (ite = xine_list_front(this->streams); ite; ite = xine_list_next(this->streams, ite)) { @@ -1193,9 +1193,9 @@ static void *video_out_loop (void *this_gen) { if (stream == XINE_ANON_STREAM) continue; if (stream->video_decoder_plugin && stream->video_fifo) { buf_element_t *buf; - + lprintf ("flushing current video decoder plugin\n"); - + buf = stream->video_fifo->buffer_pool_try_alloc (stream->video_fifo); if( buf ) { buf->type = BUF_CONTROL_FLUSH_DECODER; @@ -1215,12 +1215,12 @@ static void *video_out_loop (void *this_gen) { next_frame_vpts = img->vpts + img->duration; } /* else next_frame_vpts is returned by get_next_frame */ - + lprintf ("next_frame_vpts is %" PRId64 "\n", next_frame_vpts); - + do { vpts = this->clock->get_current_time (this->clock); - + if (this->clock->speed == XINE_SPEED_PAUSE) paused_loop (this, vpts); @@ -1237,11 +1237,11 @@ static void *video_out_loop (void *this_gen) { usec_to_sleep = MAX_USEC_TO_SLEEP; lprintf ("%" PRId64 " usec to sleep at master vpts %" PRId64 "\n", usec_to_sleep, vpts); - + if ( (next_frame_vpts - vpts) > 2*90000 ) xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out: vpts/clock error, next_vpts=%" PRId64 " cur_vpts=%" PRId64 "\n", next_frame_vpts,vpts); - + if (usec_to_sleep > 0) xine_usec_sleep (usec_to_sleep); @@ -1254,7 +1254,7 @@ static void *video_out_loop (void *this_gen) { /* * throw away undisplayed frames */ - + pthread_mutex_lock(&this->display_img_buf_queue->mutex); img = this->display_img_buf_queue->first; while (img) { @@ -1297,9 +1297,9 @@ int xine_get_next_video_frame (xine_video_port_t *this_gen, xine_usec_sleep (5000); continue; } - + /* FIXME: ugly, use conditions and locks instead? */ - + pthread_mutex_lock(&this->display_img_buf_queue->mutex); img = this->display_img_buf_queue->first; if (!img) { @@ -1316,7 +1316,7 @@ int xine_get_next_video_frame (xine_video_port_t *this_gen, /* * remove frame from display queue and show it */ - + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); pthread_mutex_unlock(&this->display_img_buf_queue->mutex); @@ -1335,7 +1335,7 @@ int xine_get_next_video_frame (xine_video_port_t *this_gen, return 1; } -void xine_free_video_frame (xine_video_port_t *port, +void xine_free_video_frame (xine_video_port_t *port, xine_video_frame_t *frame) { vo_frame_t *img = (vo_frame_t *) frame->xine_frame; @@ -1377,7 +1377,7 @@ static void vo_close (xine_video_port_t *this_gen, xine_stream_t *stream) { this->overlay_source->flush_events (this->overlay_source); this->video_opened = 0; - + /* unregister stream */ pthread_mutex_lock(&this->streams_lock); for (ite = xine_list_front(this->streams); ite; @@ -1400,17 +1400,17 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { case VO_PROP_DISCARD_FRAMES: ret = this->discard_frames; break; - + case VO_PROP_BUFS_IN_FIFO: ret = this->video_loop_running ? this->display_img_buf_queue->num_buffers : -1; break; - + case VO_PROP_NUM_STREAMS: pthread_mutex_lock(&this->streams_lock); ret = xine_list_size(this->streams); pthread_mutex_unlock(&this->streams_lock); break; - + /* * handle XINE_PARAM_xxx properties (convert from driver's range) */ @@ -1426,7 +1426,7 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { case XINE_PARAM_VO_CROP_BOTTOM: ret = this->crop_bottom; break; - + case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -1444,12 +1444,12 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { if (range_v > 0) ret = ((v-min_v) * 65536 + 32768) / range_v; - else + else ret = 0; pthread_mutex_unlock( &this->driver_lock ); } break; - + default: pthread_mutex_lock( &this->driver_lock ); ret = this->driver->get_property(this->driver, property & 0xffffff); @@ -1463,7 +1463,7 @@ static int vo_set_property (xine_video_port_t *this_gen, int property, int value int ret; switch (property) { - + case VO_PROP_DISCARD_FRAMES: /* recursive discard frames setting */ pthread_mutex_lock(&this->display_img_buf_queue->mutex); @@ -1473,19 +1473,19 @@ static int vo_set_property (xine_video_port_t *this_gen, int property, int value this->discard_frames--; pthread_mutex_unlock(&this->display_img_buf_queue->mutex); ret = this->discard_frames; - + /* discard buffers here because we have no output thread */ if (this->grab_only && this->discard_frames) { vo_frame_t *img; - + pthread_mutex_lock(&this->display_img_buf_queue->mutex); - + while ((img = this->display_img_buf_queue->first)) { - + lprintf ("flushing out frame\n"); - + img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); - + vo_frame_dec_lock (img); } pthread_mutex_unlock(&this->display_img_buf_queue->mutex); @@ -1515,32 +1515,32 @@ static int vo_set_property (xine_video_port_t *this_gen, int property, int value value = 0; ret = this->crop_bottom = value; break; - + case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: case XINE_PARAM_VO_BRIGHTNESS: if (!this->grab_only) { int v, min_v, max_v, range_v; - + pthread_mutex_lock( &this->driver_lock ); - + this->driver->get_property_min_max (this->driver, - property & 0xffffff, - &min_v, &max_v); - + property & 0xffffff, + &min_v, &max_v); + range_v = max_v - min_v + 1; - + v = (value * range_v + (range_v/2)) / 65536 + min_v; - + this->driver->set_property(this->driver, property & 0xffffff, v); pthread_mutex_unlock( &this->driver_lock ); ret = value; } else ret = 0; break; - - + + default: if (!this->grab_only) { pthread_mutex_lock( &this->driver_lock ); @@ -1574,7 +1574,7 @@ static int vo_status (xine_video_port_t *this_gen, xine_stream_t *stream, } } pthread_mutex_unlock(&this->streams_lock); - + return ret; } @@ -1619,7 +1619,7 @@ static void vo_exit (xine_video_port_t *this_gen) { if (this->overlay_source) { this->overlay_source->dispose (this->overlay_source); } - + xine_list_delete(this->streams); pthread_mutex_destroy(&this->streams_lock); @@ -1635,7 +1635,7 @@ static vo_frame_t *vo_get_last_frame (xine_video_port_t *this_gen) { } /* - * overlay stuff + * overlay stuff */ static video_overlay_manager_t *vo_get_overlay_manager (xine_video_port_t *this_gen) { @@ -1645,7 +1645,7 @@ static video_overlay_manager_t *vo_get_overlay_manager (xine_video_port_t *this_ static void vo_enable_overlay (xine_video_port_t *this_gen, int overlay_enabled) { vos_t *this = (vos_t *) this_gen; - + if (overlay_enabled) { /* we always ENable ... */ this->overlay_enabled = 1; @@ -1678,7 +1678,7 @@ static void vo_flush (xine_video_port_t *this_gen) { pthread_mutex_lock(&this->display_img_buf_queue->mutex); this->discard_frames++; pthread_mutex_unlock(&this->display_img_buf_queue->mutex); - + /* do not try this in paused mode */ while(this->clock->speed != XINE_SPEED_PAUSE) { pthread_mutex_lock(&this->display_img_buf_queue->mutex); @@ -1688,7 +1688,7 @@ static void vo_flush (xine_video_port_t *this_gen) { break; xine_usec_sleep (20000); /* pthread_cond_t could be used here */ } - + pthread_mutex_lock(&this->display_img_buf_queue->mutex); this->discard_frames--; pthread_mutex_unlock(&this->display_img_buf_queue->mutex); @@ -1703,29 +1703,29 @@ static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ) { vo_frame_t *dupl; dupl = vo_get_frame ( this_gen, - img->width - img->crop_left - img->crop_right, + img->width - img->crop_left - img->crop_right, img->height - img->crop_top - img->crop_bottom, img->ratio, img->format, img->flags | VO_BOTH_FIELDS); - + dupl->progressive_frame = img->progressive_frame; dupl->repeat_first_field = img->repeat_first_field; dupl->top_field_first = img->top_field_first; dupl->overlay_offset_x = img->overlay_offset_x; dupl->overlay_offset_y = img->overlay_offset_y; - + switch (img->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( /* Y */ - img->base[0] + img->crop_top * img->pitches[0] + + img->base[0] + img->crop_top * img->pitches[0] + img->crop_left, img->pitches[0], dupl->base[0], dupl->pitches[0], /* U */ - img->base[1] + img->crop_top/2 * img->pitches[1] + + img->base[1] + img->crop_top/2 * img->pitches[1] + img->crop_left/2, img->pitches[1], dupl->base[1], dupl->pitches[1], /* V */ - img->base[2] + img->crop_top/2 * img->pitches[2] + + img->base[2] + img->crop_top/2 * img->pitches[2] + img->crop_left/2, img->pitches[2], dupl->base[2], dupl->pitches[2], /* width x height */ @@ -1742,7 +1742,7 @@ static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ) { dupl->width, dupl->height); break; } - + dupl->bad_frame = 0; dupl->pts = img->pts; dupl->vpts = img->vpts; @@ -1755,10 +1755,10 @@ static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ) { if (img->stream) _x_refcounter_inc(img->stream->refcounter); memcpy( dupl->extra_info, img->extra_info, sizeof(extra_info_t) ); - + /* delay frame processing for now, we might not even need it (eg. frame will be discarded) */ /* vo_frame_driver_proc(dupl); */ - + return dupl; } @@ -1771,16 +1771,16 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon int num_frame_buffers; - this = xine_xmalloc (sizeof (vos_t)) ; + this = calloc(1, sizeof(vos_t)) ; this->xine = xine; this->clock = xine->clock; this->driver = driver; this->streams = xine_list_new(); - + pthread_mutex_init(&this->streams_lock, NULL); pthread_mutex_init(&this->driver_lock, NULL ); - + this->vo.open = vo_open; this->vo.get_frame = vo_get_frame; this->vo.get_last_frame = vo_get_last_frame; @@ -1804,7 +1804,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon this->last_frame = NULL; this->img_backup = NULL; - + this->overlay_source = _x_video_overlay_new_manager(xine); this->overlay_source->init (this->overlay_source); this->overlay_enabled = 1; @@ -1826,7 +1826,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon num_frame_buffers = i; /* we need at least 5 frames */ - if (num_frame_buffers<5) + if (num_frame_buffers<5) num_frame_buffers = 5; /* Choose a frame_drop_limit which matches num_frame_buffers. @@ -1858,7 +1858,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon img->proc_duplicate_frame_data = NULL; img->id = i; - + img->port = &this->vo; img->free = vo_frame_dec_lock; img->lock = vo_frame_inc_lock; @@ -1870,13 +1870,13 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon img); } - this->warn_skipped_threshold = + this->warn_skipped_threshold = xine->config->register_num (xine->config, "engine.performance.warn_skipped_threshold", 10, _("percentage of skipped frames to tolerate"), _("When more than this percentage of frames are not shown, because they " "were not decoded in time, xine sends a notification."), 20, NULL, NULL); - this->warn_discarded_threshold = + this->warn_discarded_threshold = xine->config->register_num (xine->config, "engine.performance.warn_discarded_threshold", 10, _("percentage of discarded frames to tolerate"), _("When more than this percentage of frames are not shown, because they " @@ -1903,14 +1903,14 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon this->video_loop_running = 1; this->video_opened = 0; this->grab_only = 0; - + pthread_attr_init(&pth_attrs); pthread_attr_setscope(&pth_attrs, PTHREAD_SCOPE_SYSTEM); - + if ((err = pthread_create (&this->video_thread, &pth_attrs, video_out_loop, this)) != 0) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_out: can't create thread (%s)\n", strerror(err)); + xprintf (this->xine, XINE_VERBOSITY_NONE, "video_out: can't create thread (%s)\n", strerror(err)); /* FIXME: how does this happen ? */ xprintf (this->xine, XINE_VERBOSITY_LOG, _("video_out: sorry, this should not happen. please restart xine.\n")); @@ -1918,7 +1918,7 @@ xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabon } else xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_out: thread created\n"); - + pthread_attr_destroy(&pth_attrs); } diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 4d9c80565..b1a517565 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -1,24 +1,24 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * - * xine version of video_out.h + * xine version of video_out.h * * vo_frame : frame containing yuv data and timing info, * transferred between video_decoder and video_output @@ -36,10 +36,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <pthread.h> #ifdef XINE_COMPILE @@ -51,7 +47,7 @@ extern "C" { #endif -typedef struct vo_frame_s vo_frame_t; +typedef struct vo_frame_s vo_frame_t; typedef struct vo_driver_s vo_driver_t; typedef struct video_driver_class_s video_driver_class_t; typedef struct vo_overlay_s vo_overlay_t; @@ -84,7 +80,7 @@ struct vo_frame_s { /* tell video driver that the decoder starts a new field */ void (*field) (vo_frame_t *vo_img, int which_field); - /* append this frame to the display queue, + /* append this frame to the display queue, returns number of frames to skip if decoder is late */ /* when the frame does not originate from a stream, it is legal to pass an anonymous stream */ int (*draw) (vo_frame_t *vo_img, xine_stream_t *stream); @@ -112,7 +108,7 @@ struct vo_frame_s { /* yv12 (planar) base[0]: y, base[1]: u, base[2]: v */ /* yuy2 (interleaved) base[0]: yuyv..., base[1]: --, base[2]: -- */ - uint8_t *base[3]; + uint8_t *base[3]; int pitches[3]; /* info that can be used for interlaced output (e.g. tv-out) */ @@ -123,13 +119,13 @@ struct vo_frame_s { */ int progressive_frame; int picture_coding_type; - + /* cropping to be done */ int crop_left, crop_right, crop_top, crop_bottom; /* extra info coming from input or demuxers */ - extra_info_t *extra_info; - + extra_info_t *extra_info; + /* additional information to be able to duplicate frames: */ int width, height; double ratio; /* aspect ratio */ @@ -138,7 +134,7 @@ struct vo_frame_s { int drawn; /* used by decoder, frame has already been drawn */ int flags; /* remember the frame flags */ int proc_called; /* track use of proc_*() methods */ - + /* Used to carry private data for accelerated plugins.*/ void *accel_data; @@ -146,18 +142,18 @@ struct vo_frame_s { xine_video_port_t *port; vo_driver_t *driver; xine_stream_t *stream; - + /* displacement for overlays */ int overlay_offset_x, overlay_offset_y; - - /* + + /* * that part is used only by video_out.c for frame management * obs: changing anything here will require recompiling vo drivers */ struct vo_frame_s *next; int lock_counter; pthread_mutex_t mutex; /* protect access to lock_count */ - + int id; /* debugging - track this frame */ int is_first; }; @@ -177,8 +173,8 @@ struct xine_video_port_s { * (e.g. you are a post plugin) it is legal to pass an anonymous stream */ void (*open) (xine_video_port_t *self, xine_stream_t *stream); - /* - * get_frame - allocate an image buffer from display driver + /* + * get_frame - allocate an image buffer from display driver * * params : width == width of video to display. * height == height of video to display. @@ -186,16 +182,16 @@ struct xine_video_port_s { * format == FOURCC descriptor of image format * flags == field/prediction flags */ - vo_frame_t* (*get_frame) (xine_video_port_t *self, uint32_t width, - uint32_t height, double ratio, + vo_frame_t* (*get_frame) (xine_video_port_t *self, uint32_t width, + uint32_t height, double ratio, int format, int flags); /* retrieves the last displayed frame (useful for taking snapshots) */ vo_frame_t* (*get_last_frame) (xine_video_port_t *self); - + /* overlay stuff */ void (*enable_ovl) (xine_video_port_t *self, int ovl_enable); - + /* get overlay manager */ video_overlay_manager_t* (*get_overlay_manager) (xine_video_port_t *self); @@ -208,11 +204,11 @@ struct xine_video_port_s { */ int (*get_property) (xine_video_port_t *self, int property); int (*set_property) (xine_video_port_t *self, int property, int value); - + /* return true if port is opened for this stream, stream can be anonymous */ - int (*status) (xine_video_port_t *self, xine_stream_t *stream, + int (*status) (xine_video_port_t *self, xine_stream_t *stream, int *width, int *height, int64_t *img_duration); - + /* video driver is no longer used by decoder => close */ /* when you are not a full-blown stream, but still need to close the port * (e.g. you are a post plugin) it is legal to pass an anonymous stream */ @@ -235,9 +231,9 @@ struct xine_video_port_s { #define VO_PROP_BRIGHTNESS 5 #define VO_PROP_COLORKEY 6 #define VO_PROP_AUTOPAINT_COLORKEY 7 -#define VO_PROP_ZOOM_X 8 -#define VO_PROP_PAN_SCAN 9 -#define VO_PROP_TVMODE 10 +#define VO_PROP_ZOOM_X 8 +#define VO_PROP_PAN_SCAN 9 +#define VO_PROP_TVMODE 10 #define VO_PROP_MAX_NUM_FRAMES 11 #define VO_PROP_ZOOM_Y 13 #define VO_PROP_DISCARD_FRAMES 14 /* not used by drivers */ @@ -303,7 +299,7 @@ struct vo_driver_s { */ vo_frame_t* (*alloc_frame) (vo_driver_t *self); - /* + /* * check if the given image fullfills the format specified * (re-)allocate memory if necessary */ @@ -334,7 +330,7 @@ struct vo_driver_s { * these can be used by the gui directly: */ int (*get_property) (vo_driver_t *self, int property); - int (*set_property) (vo_driver_t *self, + int (*set_property) (vo_driver_t *self, int property, int value); void (*get_property_min_max) (vo_driver_t *self, int property, int *min, int *max); @@ -349,7 +345,7 @@ struct vo_driver_s { void *data); /* check if a redraw is needed (due to resize) - * this is only used for still frames, normal video playback + * this is only used for still frames, normal video playback * must call that inside display_frame() function. */ int (*redraw_needed) (vo_driver_t *self); @@ -358,7 +354,7 @@ struct vo_driver_s { * free all resources, close driver */ void (*dispose) (vo_driver_t *self); - + void *node; /* needed by plugin_loader */ }; @@ -368,14 +364,14 @@ struct video_driver_class_s { * open a new instance of this plugin class */ vo_driver_t* (*open_plugin) (video_driver_class_t *self, const void *visual); - + /* * return short, human readable identifier for this plugin class */ char* (*get_identifier) (video_driver_class_t *self); /* - * return human readable (verbose = 1 line) description for + * return human readable (verbose = 1 line) description for * this plugin class */ char* (*get_description) (video_driver_class_t *self); @@ -401,7 +397,7 @@ struct vo_overlay_s { int y; /* y start of subpicture area */ int width; /* width of subpicture area */ int height; /* height of subpicture area */ - + uint32_t color[OVL_PALETTE_SIZE]; /* color lookup table */ uint8_t trans[OVL_PALETTE_SIZE]; /* mixer key table */ int rgb_clut; /* true if clut was converted to rgb */ @@ -414,7 +410,7 @@ struct vo_overlay_s { uint32_t hili_color[OVL_PALETTE_SIZE]; uint8_t hili_trans[OVL_PALETTE_SIZE]; int hili_rgb_clut; /* true if clut was converted to rgb */ - + int unscaled; /* true if it should be blended unscaled */ }; @@ -427,20 +423,20 @@ struct vo_overlay_s { */ struct video_overlay_manager_s { void (*init) (video_overlay_manager_t *this_gen); - + void (*dispose) (video_overlay_manager_t *this_gen); - + int32_t (*get_handle) (video_overlay_manager_t *this_gen, int object_type ); - + void (*free_handle) (video_overlay_manager_t *this_gen, int32_t handle); - + int32_t (*add_event) (video_overlay_manager_t *this_gen, void *event); - + void (*flush_events) (video_overlay_manager_t *this_gen ); - + int (*redraw_needed) (video_overlay_manager_t *this_gen, int64_t vpts ); - - void (*multiple_overlay_blend) (video_overlay_manager_t *this_gen, int64_t vpts, + + void (*multiple_overlay_blend) (video_overlay_manager_t *this_gen, int64_t vpts, vo_driver_t *output, vo_frame_t *vo_img, int enabled); }; @@ -448,7 +444,7 @@ struct video_overlay_manager_s { * build a video_out_port from * a given video driver */ -xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabonly) XINE_PROTECTED; +xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabonly) XINE_MALLOC XINE_PROTECTED; #ifdef __cplusplus } diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index c189fa56b..3216950e8 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -1,23 +1,27 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <unistd.h> #include <string.h> @@ -47,15 +51,15 @@ typedef struct video_overlay_showing_s { typedef struct video_overlay_s { video_overlay_manager_t video_overlay; - + xine_t *xine; - pthread_mutex_t events_mutex; + pthread_mutex_t events_mutex; video_overlay_events_t events[MAX_EVENTS]; - pthread_mutex_t objects_mutex; + pthread_mutex_t objects_mutex; video_overlay_object_t objects[MAX_OBJECTS]; pthread_mutex_t showing_mutex; - video_overlay_showing_t showing[MAX_SHOWING]; + video_overlay_showing_t showing[MAX_SHOWING]; int showing_changed; } video_overlay_t; @@ -63,24 +67,24 @@ typedef struct video_overlay_s { static void add_showing_handle( video_overlay_t *this, int32_t handle ) { int i; - + pthread_mutex_lock( &this->showing_mutex ); this->showing_changed++; - + for( i = 0; i < MAX_SHOWING; i++ ) if( this->showing[i].handle == handle ) break; /* already showing */ - + if( i == MAX_SHOWING ) { for( i = 0; i < MAX_SHOWING && this->showing[i].handle >= 0; i++ ) ; - + if( i != MAX_SHOWING ) this->showing[i].handle = handle; else xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_overlay: error: no showing slots available\n"); } - + pthread_mutex_unlock( &this->showing_mutex ); } @@ -90,13 +94,13 @@ static void remove_showing_handle( video_overlay_t *this, int32_t handle ) pthread_mutex_lock( &this->showing_mutex ); this->showing_changed++; - + for( i = 0; i < MAX_SHOWING; i++ ) { if( this->showing[i].handle == handle ) { this->showing[i].handle = -1; } } - + pthread_mutex_unlock( &this->showing_mutex ); } @@ -106,34 +110,34 @@ static void remove_events_handle( video_overlay_t *this, int32_t handle, int loc if( lock ) pthread_mutex_lock( &this->events_mutex ); - + this_event=0; do { last_event=this_event; this_event=this->events[last_event].next_event; - - while( this_event && + + while( this_event && this->events[this_event].event->object.handle == handle ) { /* remove event from pts list */ this->events[last_event].next_event= this->events[this_event].next_event; - /* free its overlay */ - if( this->events[this_event].event->object.overlay ) { + /* free its overlay */ + if( this->events[this_event].event->object.overlay ) { if( this->events[this_event].event->object.overlay->rle ) free( this->events[this_event].event->object.overlay->rle ); free(this->events[this_event].event->object.overlay); this->events[this_event].event->object.overlay = NULL; } - + /* mark as free */ this->events[this_event].next_event = 0; this->events[this_event].event->event_type = OVERLAY_EVENT_NULL; - + this_event=this->events[last_event].next_event; } } while ( this_event ); - + if( lock ) pthread_mutex_unlock( &this->events_mutex ); } @@ -145,35 +149,35 @@ static void remove_events_handle( video_overlay_t *this, int32_t handle, int loc static int32_t video_overlay_get_handle(video_overlay_manager_t *this_gen, int object_type ) { video_overlay_t *this = (video_overlay_t *) this_gen; int n; - + pthread_mutex_lock( &this->objects_mutex ); - + for( n=0; n < MAX_OBJECTS && this->objects[n].handle > -1; n++ ) ; - + if (n == MAX_OBJECTS) { n = -1; } else { this->objects[n].handle = n; this->objects[n].object_type = object_type; } - + pthread_mutex_unlock( &this->objects_mutex ); return n; } -/* +/* free a handle from the object pool (internal function) */ static void internal_video_overlay_free_handle(video_overlay_t *this, int32_t handle) { - + pthread_mutex_lock( &this->objects_mutex ); if( this->objects[handle].overlay ) { if( this->objects[handle].overlay->rle ) free( this->objects[handle].overlay->rle ); free( this->objects[handle].overlay ); - this->objects[handle].overlay = NULL; + this->objects[handle].overlay = NULL; } this->objects[handle].handle = -1; @@ -195,11 +199,11 @@ static void video_overlay_free_handle(video_overlay_manager_t *this_gen, int32_t static void video_overlay_reset (video_overlay_t *this) { int i; - + pthread_mutex_lock (&this->events_mutex); for (i=0; i < MAX_EVENTS; i++) { if (this->events[i].event == NULL) { - this->events[i].event = xine_xmalloc (sizeof(video_overlay_event_t)); + this->events[i].event = calloc(1, sizeof(video_overlay_event_t)); #ifdef LOG_DEBUG printf ("video_overlay: MALLOC2: this->events[%d].event %p, len=%d\n", i, @@ -208,17 +212,17 @@ static void video_overlay_reset (video_overlay_t *this) { #endif } this->events[i].event->event_type = 0; /* Empty slot */ - this->events[i].next_event = 0; + this->events[i].next_event = 0; } pthread_mutex_unlock (&this->events_mutex); - + for( i = 0; i < MAX_SHOWING; i++ ) this->showing[i].handle = -1; - + for (i=0; i < MAX_OBJECTS; i++) { internal_video_overlay_free_handle(this, i); } - + this->showing_changed = 0; } @@ -230,7 +234,7 @@ static void video_overlay_init (video_overlay_manager_t *this_gen) { pthread_mutex_init (&this->events_mutex,NULL); pthread_mutex_init (&this->objects_mutex,NULL); pthread_mutex_init (&this->showing_mutex,NULL); - + video_overlay_reset(this); } @@ -252,13 +256,13 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void uint32_t last_event,this_event,new_event; pthread_mutex_lock (&this->events_mutex); - + /* We skip the 0 entry because that is used as a pointer to the first event.*/ /* Find a free event slot */ - for( new_event = 1; new_event<MAX_EVENTS && + for( new_event = 1; new_event<MAX_EVENTS && this->events[new_event].event->event_type > 0; new_event++ ) ; - + if (new_event < MAX_EVENTS) { /* Find position in event queue to be added. */ this_event=0; @@ -270,7 +274,7 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void this->events[last_event].next_event=new_event; this->events[new_event].next_event=this_event; - + /* memcpy everything except the actual image */ if ( this->events[new_event].event == NULL ) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_overlay: error: event slot is NULL!\n"); @@ -283,7 +287,7 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void if ( this->events[new_event].event->object.overlay ) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_overlay: add_event: event->object.overlay was not freed!\n"); } - + if( event->object.overlay ) { int i; for(i = 0; i < OVL_PALETTE_SIZE; i++) { @@ -293,8 +297,8 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void event->object.overlay->hili_trans[i] = OVL_MAX_OPACITY; } - this->events[new_event].event->object.overlay = xine_xmalloc (sizeof(vo_overlay_t)); - xine_fast_memcpy(this->events[new_event].event->object.overlay, + this->events[new_event].event->object.overlay = calloc(1, sizeof(vo_overlay_t)); + xine_fast_memcpy(this->events[new_event].event->object.overlay, event->object.overlay, sizeof(vo_overlay_t)); /* We took the callers rle and data, therefore it will be our job to free it */ @@ -307,9 +311,9 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_overlay:No spare subtitle event slots\n"); new_event = -1; } - + pthread_mutex_unlock (&this->events_mutex); - + return new_event; } @@ -331,7 +335,7 @@ static void video_overlay_print_overlay( vo_overlay_t *ovl ) { printf ("video_overlay: \thili_trans [%d %d %d %d]\n", ovl->hili_trans[0], ovl->hili_trans[1], ovl->hili_trans[2], ovl->hili_trans[3]); return; -} +} #endif /* @@ -343,9 +347,9 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { int32_t handle; uint32_t this_event; int processed = 0; - + pthread_mutex_lock (&this->events_mutex); - + this_event=this->events[0].next_event; while ( this_event && (vpts > this->events[this_event].event->vpts || vpts == 0) ) { @@ -371,21 +375,21 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { */ remove_showing_handle(this,handle); internal_video_overlay_free_handle(this, handle); - + this->objects[handle].handle = handle; if( this->objects[handle].overlay ) { xprintf(this->xine, XINE_VERBOSITY_DEBUG, "video_overlay: error: object->overlay was not freed!\n"); } - this->objects[handle].overlay = + this->objects[handle].overlay = this->events[this_event].event->object.overlay; - this->objects[handle].pts = + this->objects[handle].pts = this->events[this_event].event->object.pts; this->events[this_event].event->object.overlay = NULL; - + add_showing_handle( this, handle ); } break; - + case OVERLAY_EVENT_HIDE: #ifdef LOG_DEBUG printf ("video_overlay: HIDE SPU NOW\n"); @@ -395,17 +399,17 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { if( this->events[this_event].event->object.overlay->rle != NULL ) free( this->events[this_event].event->object.overlay->rle ); free(this->events[this_event].event->object.overlay); - this->events[this_event].event->object.overlay = NULL; + this->events[this_event].event->object.overlay = NULL; } remove_showing_handle( this, handle ); break; - + case OVERLAY_EVENT_FREE_HANDLE: #ifdef LOG_DEBUG printf ("video_overlay: FREE SPU NOW\n"); #endif /* free any overlay associated with this event */ - if( this->events[this_event].event->object.overlay != NULL) { + if( this->events[this_event].event->object.overlay != NULL) { if( this->events[this_event].event->object.overlay->rle != NULL ) free( this->events[this_event].event->object.overlay->rle ); free(this->events[this_event].event->object.overlay); @@ -419,7 +423,7 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { internal_video_overlay_free_handle( this, handle ); break; - + case OVERLAY_EVENT_MENU_BUTTON: /* mixes palette and copy clip coords */ #ifdef LOG_DEBUG @@ -429,10 +433,10 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { /* This code drops buttons, where the button PTS derived from the NAV * packet on DVDs does not match the SPU PTS. Practical experience shows, * that this is not necessary and causes problems with some DVDs */ - if ( (this->events[this_event].event->object.pts != + if ( (this->events[this_event].event->object.pts != this->objects[handle].pts) ) { - xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "video_overlay:MENU BUTTON DROPPED menu pts=%lld spu pts=%lld\n", + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "video_overlay:MENU BUTTON DROPPED menu pts=%lld spu pts=%lld\n", this->events[this_event].event->object.pts, this->objects[handle].pts); break; @@ -442,7 +446,7 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { (this->objects[handle].overlay) ) { vo_overlay_t *overlay = this->objects[handle].overlay; vo_overlay_t *event_overlay = this->events[this_event].event->object.overlay; - + #ifdef LOG_DEBUG printf ("video_overlay:overlay present\n"); #endif @@ -473,84 +477,84 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) { free( this->events[this_event].event->object.overlay->rle ); this->events[this_event].event->object.overlay->rle = NULL; } - + if (this->events[this_event].event->object.overlay != NULL) { free (this->events[this_event].event->object.overlay); this->events[this_event].event->object.overlay = NULL; } break; - + default: xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_overlay: unhandled event type\n"); break; } - - this->events[0].next_event = this->events[this_event].next_event; + + this->events[0].next_event = this->events[this_event].next_event; this->events[this_event].next_event = 0; this->events[this_event].event->event_type = 0; - + this_event=this->events[0].next_event; } - + pthread_mutex_unlock (&this->events_mutex); return processed; } - -/* This is called from video_out.c + +/* This is called from video_out.c * must call output->overlay_blend for each active overlay. */ -static void video_overlay_multiple_overlay_blend (video_overlay_manager_t *this_gen, int64_t vpts, +static void video_overlay_multiple_overlay_blend (video_overlay_manager_t *this_gen, int64_t vpts, vo_driver_t *output, vo_frame_t *vo_img, int enabled) { video_overlay_t *this = (video_overlay_t *) this_gen; int i; int32_t handle; - /* Look at next events, if current video vpts > first event on queue, process the event - * else just continue + /* Look at next events, if current video vpts > first event on queue, process the event + * else just continue */ video_overlay_event( this, vpts ); - - /* Scan through 5 entries and display any present. + + /* Scan through 5 entries and display any present. */ pthread_mutex_lock( &this->showing_mutex ); if( output->overlay_begin ) output->overlay_begin(output, vo_img, this->showing_changed); - + for( i = 0; enabled && output->overlay_blend && i < MAX_SHOWING; i++ ) { - handle=this->showing[i].handle; + handle=this->showing[i].handle; if (handle >= 0 ) { output->overlay_blend(output, vo_img, this->objects[handle].overlay); } } - + if( output->overlay_end ) output->overlay_end(output, vo_img); - + this->showing_changed = 0; - + pthread_mutex_unlock( &this->showing_mutex ); } -/* this should be called on stream end or stop to make sure every +/* this should be called on stream end or stop to make sure every hide event is processed. */ static void video_overlay_flush_events(video_overlay_manager_t *this_gen ) { video_overlay_t *this = (video_overlay_t *) this_gen; - + video_overlay_event( this, 0 ); } -/* this is called from video_out.c on still frames to check +/* this is called from video_out.c on still frames to check if a redraw is needed. */ static int video_overlay_redraw_needed(video_overlay_manager_t *this_gen, int64_t vpts ) { video_overlay_t *this = (video_overlay_t *) this_gen; - + video_overlay_event( this, vpts ); return this->showing_changed; } @@ -571,7 +575,7 @@ static void video_overlay_dispose(video_overlay_manager_t *this_gen) { free (this->events[i].event); } } - + for (i=0; i < MAX_OBJECTS; i++) internal_video_overlay_free_handle(this, i); @@ -587,7 +591,7 @@ video_overlay_manager_t *_x_video_overlay_new_manager (xine_t *xine) { video_overlay_t *this; - this = (video_overlay_t *) xine_xmalloc (sizeof (video_overlay_t)); + this = (video_overlay_t *) calloc(1, sizeof(video_overlay_t)); this->xine = xine; this->video_overlay.init = video_overlay_init; diff --git a/src/xine-engine/video_overlay.h b/src/xine-engine/video_overlay.h index d580a1e83..f2deb8a2b 100644 --- a/src/xine-engine/video_overlay.h +++ b/src/xine-engine/video_overlay.h @@ -2,17 +2,17 @@ * Copyright (C) 2000-2003 the xine project * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -50,7 +50,7 @@ #define OVL_PALETTE_SIZE 256 typedef struct vo_buttons_s { - int32_t type; /* 0:Button not valid, + int32_t type; /* 0:Button not valid, 1:Button Valid, no auto_action, 2:Button Valid, auto_action. */ @@ -61,10 +61,10 @@ typedef struct vo_buttons_s { int32_t hili_bottom; int32_t hili_left; int32_t hili_right; - int32_t up; - int32_t down; - int32_t left; - int32_t right; + int32_t up; + int32_t down; + int32_t left; + int32_t right; uint32_t select_color[OVL_PALETTE_SIZE]; uint8_t select_trans[OVL_PALETTE_SIZE]; xine_event_t select_event; @@ -74,7 +74,7 @@ typedef struct vo_buttons_s { int32_t hili_rgb_clut; /* true if clut was converted to rgb*/ /* FIXME: Probably not needed ^^^ */ } vo_buttons_t; - + typedef struct video_overlay_object_s { int32_t handle; /* Used to match Show and Hide events. */ uint32_t object_type; /* 0=Subtitle, 1=Menu */ @@ -98,6 +98,6 @@ typedef struct video_overlay_event_s { video_overlay_object_t object; /* The image data. */ } video_overlay_event_t; -video_overlay_manager_t *_x_video_overlay_new_manager(xine_t *) XINE_PROTECTED; +video_overlay_manager_t *_x_video_overlay_new_manager(xine_t *) XINE_MALLOC XINE_PROTECTED; #endif diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c index ff30c47a6..e2b7ac9e4 100644 --- a/src/xine-engine/vo_scale.c +++ b/src/xine-engine/vo_scale.c @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -22,6 +22,10 @@ * Takes into account aspect ratio correction and zooming. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <string.h> #include <math.h> @@ -49,14 +53,14 @@ void _x_vo_scale_compute_ideal_size (vo_scale_t *this) { this->video_pixel_aspect = this->gui_pixel_aspect; } else { - - /* + + /* * aspect ratio */ - + image_ratio = (double) (this->delivered_width - (this->crop_left + this->crop_right)) / (double) (this->delivered_height - (this->crop_top + this->crop_bottom)); - + switch (this->user_ratio) { case XINE_VO_ASPECT_AUTO: desired_ratio = this->delivered_ratio; @@ -76,7 +80,7 @@ void _x_vo_scale_compute_ideal_size (vo_scale_t *this) { } this->video_pixel_aspect = desired_ratio / image_ratio; - + _x_assert(this->gui_pixel_aspect != 0.0); if (fabs (this->video_pixel_aspect / this->gui_pixel_aspect - 1.0) @@ -85,7 +89,7 @@ void _x_vo_scale_compute_ideal_size (vo_scale_t *this) { } #if 0 - + /* onefield_xv divide by 2 the number of lines */ if (this->deinterlace_enabled && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) @@ -103,17 +107,17 @@ void _x_vo_scale_compute_ideal_size (vo_scale_t *this) { */ void _x_vo_scale_compute_output_size (vo_scale_t *this) { - + int cropped_width, cropped_height; double x_factor, y_factor, aspect; - + cropped_width = this->delivered_width - (this->crop_left + this->crop_right); - cropped_height = this->delivered_height - (this->crop_top + this->crop_bottom); + cropped_height = this->delivered_height - (this->crop_top + this->crop_bottom); aspect = this->video_pixel_aspect / this->gui_pixel_aspect; x_factor = (double) this->gui_width / (double) (cropped_width * aspect); y_factor = (double) (this->gui_height * aspect) / (double) cropped_height; - + if (this->scaling_disabled) { this->output_width = cropped_width; @@ -124,8 +128,8 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { } else { if ( this->support_zoom ) { - - /* zoom behaviour: + + /* zoom behaviour: * - window size never changes due zooming * - output image shall be increased whenever there are * black borders to use. @@ -134,7 +138,7 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { if (((double)this->gui_width - (double)cropped_width * y_factor) < ((double)this->gui_height - (double)cropped_height * x_factor)) { this->output_width = this->gui_width; this->displayed_width = (double)cropped_width / this->zoom_factor_x + 0.5; - + this->output_height = (double)cropped_height * x_factor + 0.5; if( this->output_height * this->zoom_factor_y <= this->gui_height ) { this->displayed_height = cropped_height; @@ -147,7 +151,7 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { } else { this->output_height = this->gui_height; this->displayed_height = (double)cropped_height / this->zoom_factor_y + 0.5; - + this->output_width = (double)cropped_width * y_factor + 0.5; if( this->output_width * this->zoom_factor_x <= this->gui_width ) { this->displayed_width = cropped_width; @@ -158,7 +162,7 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { this->output_width = this->gui_width; } } - + } else { if (((double)this->gui_width - (double)cropped_width * y_factor) < ((double)this->gui_height - (double)cropped_height * x_factor)) { this->output_width = (double) this->gui_width; @@ -170,27 +174,27 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { this->displayed_width = cropped_width; this->displayed_height = cropped_height; } - } - + } + /* make sure displayed values are sane, that is, we are not trying to display * something outside the delivered image. may happen when zoom < 100%. */ if( this->displayed_width > this->delivered_width ) { - this->output_width = (double) this->output_width * + this->output_width = (double) this->output_width * this->delivered_width / this->displayed_width + 0.5; this->displayed_width = this->delivered_width; } if( this->displayed_height > this->delivered_height ) { - this->output_height = (double) this->output_height * + this->output_height = (double) this->output_height * this->delivered_height / this->displayed_height + 0.5; this->displayed_height = this->delivered_height; } - + this->output_xoffset = (this->gui_width - this->output_width) * this->output_horizontal_position + this->gui_x; this->output_yoffset = (this->gui_height - this->output_height) * this->output_vertical_position + this->gui_y; - + this->displayed_xoffset = ((cropped_width - this->displayed_width) / 2) + this->crop_left; this->displayed_yoffset = ((cropped_height - this->displayed_height) / 2) + this->crop_top; @@ -215,8 +219,8 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { /* no top/bottom borders */ this->border[0].w = this->border[0].h = 0; this->border[1].w = this->border[1].h = 0; - } - + } + if (this->output_width < this->gui_width) { /* left */ this->border[2].x = 0; @@ -248,10 +252,10 @@ int _x_vo_scale_redraw_needed (vo_scale_t *this) { _x_assert(this->frame_output_cb); if ( ! this->frame_output_cb ) return 0; - + this->frame_output_cb (this->user_data, - this->delivered_width - (this->crop_left + this->crop_right), - this->delivered_height - (this->crop_top + this->crop_bottom), + this->delivered_width - (this->crop_left + this->crop_right), + this->delivered_height - (this->crop_top + this->crop_bottom), this->video_pixel_aspect, &gui_x, &gui_y, &gui_width, &gui_height, &gui_pixel_aspect, &gui_win_x, &gui_win_y ); @@ -273,7 +277,7 @@ int _x_vo_scale_redraw_needed (vo_scale_t *this) { } else ret = this->force_redraw; - + this->force_redraw = 0; return ret; } @@ -302,7 +306,7 @@ void _x_vo_scale_translate_gui2video(vo_scale_t *this, * translate output area coordianates into the delivered area * coordiantes. */ - + x = x * this->displayed_width / this->output_width + this->displayed_xoffset; y = y * this->displayed_height / this->output_height + this->displayed_yoffset; } @@ -339,21 +343,21 @@ char *_x_vo_scale_aspect_ratio_name(int a) { */ static void vo_scale_horizontal_pos_changed(void *data, xine_cfg_entry_t *entry) { vo_scale_t *this = (vo_scale_t *)data; - + this->output_horizontal_position = entry->num_value / 100.0; this->force_redraw = 1; } static void vo_scale_vertical_pos_changed(void *data, xine_cfg_entry_t *entry) { vo_scale_t *this = (vo_scale_t *)data; - + this->output_vertical_position = entry->num_value / 100.0; this->force_redraw = 1; } static void vo_scale_disable_scaling_changed(void *data, xine_cfg_entry_t *entry) { vo_scale_t *this = (vo_scale_t *)data; - + if (this->scaling_disabled < 2) { this->scaling_disabled = entry->num_value; this->force_redraw = 1; @@ -361,13 +365,13 @@ static void vo_scale_disable_scaling_changed(void *data, xine_cfg_entry_t *entry } -/* +/* * initialize rescaling struct */ - + void _x_vo_scale_init(vo_scale_t *this, int support_zoom, int scaling_disabled, config_values_t *config ) { - + memset( this, 0, sizeof(vo_scale_t) ); this->support_zoom = support_zoom; this->force_redraw = 1; @@ -376,13 +380,13 @@ void _x_vo_scale_init(vo_scale_t *this, int support_zoom, int scaling_disabled, this->gui_pixel_aspect = 1.0; this->user_ratio = XINE_VO_ASPECT_AUTO; this->delivered_ratio = 0.0; - + this->crop_left = 0; this->crop_right = 0; this->crop_top = 0; this->crop_bottom = 0; - - this->output_horizontal_position = + + this->output_horizontal_position = config->register_range(config, "video.output.horizontal_position", 50, 0, 100, _("horizontal image position in the output window"), _("If the video window's horizontal size is bigger than the actual image " diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h index 829405162..fe2594eeb 100644 --- a/src/xine-engine/vo_scale.h +++ b/src/xine-engine/vo_scale.h @@ -7,7 +7,7 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -29,10 +29,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #ifdef XINE_COMPILE # include "configfile.h" #else @@ -48,22 +44,22 @@ struct vo_scale_s { /* true if driver supports frame zooming */ int support_zoom; - + /* forces direct mapping between frame pixels and screen pixels */ int scaling_disabled; - + /* size / aspect ratio calculations */ - /* + /* * "delivered" size: * frame dimension / aspect as delivered by the decoder * used (among other things) to detect frame size changes * units: frame pixels */ - int delivered_width; - int delivered_height; + int delivered_width; + int delivered_height; double delivered_ratio; - + /* * required cropping: * units: frame pixels @@ -73,7 +69,7 @@ struct vo_scale_s { int crop_top; int crop_bottom; - /* + /* * displayed part of delivered images, * taking zoom into account * units: frame pixels @@ -97,7 +93,7 @@ struct vo_scale_s { int gui_x, gui_y; int gui_width, gui_height; int gui_win_x, gui_win_y; - + /* * video + display pixel aspect * One pixel of height 1 has this width @@ -117,11 +113,11 @@ struct vo_scale_s { int output_height; int output_xoffset; int output_yoffset; - + /* */ int force_redraw; - + /* gui callbacks */ @@ -129,13 +125,13 @@ struct vo_scale_s { void (*frame_output_cb) (void *user_data, int video_width, int video_height, double video_pixel_aspect, - int *dest_x, int *dest_y, + int *dest_x, int *dest_y, int *dest_width, int *dest_height, double *dest_pixel_aspect, int *win_x, int *win_y); - + void (*dest_size_cb) (void *user_data, - int video_width, int video_height, + int video_width, int video_height, double video_pixel_aspect, int *dest_width, int *dest_height, double *dest_pixel_aspect); @@ -149,10 +145,10 @@ struct vo_scale_s { */ double output_horizontal_position; double output_vertical_position; - + }; -typedef struct vo_scale_s vo_scale_t; +typedef struct vo_scale_s vo_scale_t; /* @@ -179,7 +175,7 @@ int _x_vo_scale_redraw_needed (vo_scale_t *self) XINE_PROTECTED; /* * */ - + void _x_vo_scale_translate_gui2video(vo_scale_t *self, int x, int y, int *vid_x, int *vid_y) XINE_PROTECTED; @@ -190,11 +186,11 @@ void _x_vo_scale_translate_gui2video(vo_scale_t *self, char *_x_vo_scale_aspect_ratio_name(int a) XINE_PROTECTED; -/* +/* * initialize rescaling struct */ - -void _x_vo_scale_init(vo_scale_t *self, int support_zoom, + +void _x_vo_scale_init(vo_scale_t *self, int support_zoom, int scaling_disabled, config_values_t *config ) XINE_PROTECTED; #ifdef __cplusplus diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index eae13bec9..9f63d793c 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -36,6 +36,7 @@ #include <stdarg.h> #include <stdio.h> #include <ctype.h> +#include <unistd.h> #if defined (__linux__) || defined (__GLIBC__) #include <endian.h> #elif defined (__FreeBSD__) @@ -92,7 +93,7 @@ void _x_handle_stream_end (xine_stream_t *stream, int non_user) { * if they have called xine_stop explicitly, so only send * it if stream playback finished because of stream end reached */ - + xine_event_t event; event.data_length = 0; @@ -132,7 +133,7 @@ static int acquire_allowed_to_block(xine_ticket_t *this) { unsigned new_size; for(entry = 0; entry < this->holder_thread_count; ++entry) { - if(this->holder_threads[entry].holder == own_id) { + if(pthread_equal(this->holder_threads[entry].holder, own_id)) { /* This thread may already hold this ticket */ this->holder_threads[entry].count++; return (this->holder_threads[entry].count == 1); @@ -150,7 +151,7 @@ static int acquire_allowed_to_block(xine_ticket_t *this) { /* List too small. Realloc to larger size */ new_size = this->holder_thread_count * 2; lprintf("Reallocing from %d to %d entries\n", this->holder_thread_count, new_size); - + this->holder_threads = realloc(this->holder_threads, sizeof(*this->holder_threads) * new_size); memset(this->holder_threads + this->holder_thread_count, 0, this->holder_thread_count); @@ -159,15 +160,15 @@ static int acquire_allowed_to_block(xine_ticket_t *this) { this->holder_threads[this->holder_thread_count].holder = own_id; this->holder_thread_count = new_size; - return 1; + return 1; } - + static int ticket_acquire_internal(xine_ticket_t *this, int irrevocable, int nonblocking) { int must_wait = 0; pthread_mutex_lock(&this->lock); int allowed_to_block = acquire_allowed_to_block(this); - + if (this->ticket_revoked && !this->irrevocable_tickets) must_wait = !nonblocking; else if (this->atomic_revoke && !pthread_equal(this->atomic_revoker_thread, pthread_self())) @@ -181,12 +182,12 @@ static int ticket_acquire_internal(xine_ticket_t *this, int irrevocable, int non pthread_cond_wait(&this->issued, &this->lock); } - + this->tickets_granted++; if (irrevocable) this->irrevocable_tickets++; - - pthread_mutex_unlock(&this->lock); + + pthread_mutex_unlock(&this->lock); return 1; } @@ -201,9 +202,9 @@ static void ticket_acquire(xine_ticket_t *this, int irrevocable) { static int release_allowed_to_block(xine_ticket_t *this) { pthread_t own_id = pthread_self(); unsigned entry; - + for(entry = 0; entry < this->holder_thread_count; ++entry) { - if(this->holder_threads[entry].holder == own_id) { + if(pthread_equal(this->holder_threads[entry].holder, own_id)) { this->holder_threads[entry].count--; return this->holder_threads[entry].count == 0; } @@ -217,18 +218,18 @@ static void ticket_release_internal(xine_ticket_t *this, int irrevocable, int no pthread_mutex_lock(&this->lock); int allowed_to_block = release_allowed_to_block(this); - + this->tickets_granted--; if (irrevocable) this->irrevocable_tickets--; - + if (this->ticket_revoked && !this->tickets_granted) pthread_cond_broadcast(&this->revoked); if (allowed_to_block) { if (this->ticket_revoked && !this->irrevocable_tickets && !nonblocking) pthread_cond_wait(&this->issued, &this->lock); } - + pthread_mutex_unlock(&this->lock); } @@ -243,17 +244,17 @@ static void ticket_release(xine_ticket_t *this, int irrevocable) { static void ticket_renew(xine_ticket_t *this, int irrevocable) { pthread_mutex_lock(&this->lock); - + this->tickets_granted--; - + _x_assert(this->ticket_revoked); if (!this->tickets_granted) pthread_cond_broadcast(&this->revoked); if (!this->irrevocable_tickets || !irrevocable) pthread_cond_wait(&this->issued, &this->lock); - + this->tickets_granted++; - + pthread_mutex_unlock(&this->lock); } @@ -262,12 +263,12 @@ static void ticket_issue(xine_ticket_t *this, int atomic) { if (!atomic) pthread_mutex_lock(&this->revoke_lock); pthread_mutex_lock(&this->lock); - + this->pending_revocations--; if (!this->pending_revocations) pthread_cond_broadcast(&this->issued); this->atomic_revoke = 0; - + pthread_mutex_unlock(&this->lock); pthread_mutex_unlock(&this->revoke_lock); } @@ -276,7 +277,7 @@ static void ticket_revoke(xine_ticket_t *this, int atomic) { pthread_mutex_lock(&this->revoke_lock); pthread_mutex_lock(&this->lock); - + this->pending_revocations++; this->ticket_revoked = 1; if (this->tickets_granted) @@ -287,7 +288,7 @@ static void ticket_revoke(xine_ticket_t *this, int atomic) { this->atomic_revoke = 1; this->atomic_revoker_thread = pthread_self(); } - + pthread_mutex_unlock(&this->lock); if (!atomic) pthread_mutex_unlock(&this->revoke_lock); @@ -299,15 +300,15 @@ static void ticket_dispose(xine_ticket_t *this) { pthread_mutex_destroy(&this->revoke_lock); pthread_cond_destroy(&this->issued); pthread_cond_destroy(&this->revoked); - + free(this); } -static xine_ticket_t *ticket_init(void) { +static xine_ticket_t *XINE_MALLOC ticket_init(void) { xine_ticket_t *port_ticket; - - port_ticket = (xine_ticket_t *) xine_xmalloc(sizeof(xine_ticket_t)); - + + port_ticket = calloc(1, sizeof(xine_ticket_t)); + port_ticket->acquire_nonblocking = ticket_acquire_nonblocking; port_ticket->acquire = ticket_acquire; port_ticket->release_nonblocking = ticket_release_nonblocking; @@ -318,37 +319,44 @@ static xine_ticket_t *ticket_init(void) { port_ticket->dispose = ticket_dispose; port_ticket->holder_thread_count = XINE_MAX_TICKET_HOLDER_THREADS; port_ticket->holder_threads = calloc(XINE_MAX_TICKET_HOLDER_THREADS,sizeof(*port_ticket->holder_threads)); - + pthread_mutex_init(&port_ticket->lock, NULL); pthread_mutex_init(&port_ticket->revoke_lock, NULL); pthread_cond_init(&port_ticket->issued, NULL); pthread_cond_init(&port_ticket->revoked, NULL); - + return port_ticket; } static void set_speed_internal (xine_stream_t *stream, int speed) { xine_t *xine = stream->xine; + int old_speed = xine->clock->speed; - if (xine->clock->speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) /* get all decoder and post threads in a state where they agree to be blocked */ xine->port_ticket->revoke(xine->port_ticket, 0); - - if (xine->clock->speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) + + if (old_speed == XINE_SPEED_PAUSE && speed != XINE_SPEED_PAUSE) /* all decoder and post threads may continue now */ xine->port_ticket->issue(xine->port_ticket, 0); - - stream->xine->clock->set_fine_speed (stream->xine->clock, speed); + + if (old_speed != XINE_SPEED_PAUSE && speed == XINE_SPEED_PAUSE) + /* set master clock so audio_out loop can pause in a safe place */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); /* see coment on audio_out loop about audio_paused */ if( stream->audio_out ) { xine->port_ticket->acquire(xine->port_ticket, 1); - + /* inform audio_out that speed has changed - he knows what to do */ stream->audio_out->set_property (stream->audio_out, AO_PROP_CLOCK_SPEED, speed); - + xine->port_ticket->release(xine->port_ticket, 1); } + + if (old_speed == XINE_SPEED_PAUSE || speed != XINE_SPEED_PAUSE) + /* master clock is set after resuming the audio device (audio_out loop may continue) */ + stream->xine->clock->set_fine_speed (stream->xine->clock, speed); } @@ -398,18 +406,18 @@ void xine_stop (xine_stream_t *stream) { stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); stop_internal (stream); - + if (stream->slave && (stream->slave_affection & XINE_MASTER_SLAVE_STOP)) xine_stop(stream->slave); if (stream->video_out) - stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); + stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 0); - + stream->xine->port_ticket->release(stream->xine->port_ticket, 1); stream->ignore_speed_change = 0; - + pthread_cleanup_pop (0); pthread_mutex_unlock (&stream->frontend_lock); } @@ -418,6 +426,7 @@ void xine_stop (xine_stream_t *stream) { static void close_internal (xine_stream_t *stream) { int i ; + int gapless_switch = stream->gapless_switch; if( stream->slave ) { xine_close( stream->slave ); @@ -428,32 +437,32 @@ static void close_internal (xine_stream_t *stream) { } } - if( !stream->gapless_switch ) { + if( !gapless_switch ) { /* make sure that other threads cannot change the speed, especially pauseing the stream */ pthread_mutex_lock(&stream->speed_change_lock); stream->ignore_speed_change = 1; pthread_mutex_unlock(&stream->speed_change_lock); stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1); - + if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 1); if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); } - + stop_internal( stream ); - - if( !stream->gapless_switch ) { + + if( !gapless_switch ) { if (stream->video_out) - stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); + stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); if (stream->audio_out) stream->audio_out->set_property(stream->audio_out, AO_PROP_DISCARD_BUFFERS, 0); - + stream->xine->port_ticket->release(stream->xine->port_ticket, 1); stream->ignore_speed_change = 0; } - + if (stream->demux_plugin) { _x_free_demux_plugin(stream, stream->demux_plugin); stream->demux_plugin = NULL; @@ -515,14 +524,14 @@ static int stream_rewire_audio(xine_post_out_t *output, void *data) return 0; stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1); - + if (stream->audio_out->status(stream->audio_out, stream, &bits, &rate, &mode)) { /* register our stream at the new output port */ (new_port->open) (new_port, stream, bits, rate, mode); stream->audio_out->close(stream->audio_out, stream); } stream->audio_out = new_port; - + stream->xine->port_ticket->issue(stream->xine->port_ticket, 1); return 1; @@ -534,25 +543,25 @@ static int stream_rewire_video(xine_post_out_t *output, void *data) xine_video_port_t *new_port = (xine_video_port_t *)data; int64_t img_duration; int width, height; - + if (!data) return 0; stream->xine->port_ticket->revoke(stream->xine->port_ticket, 1); - + if (stream->video_out->status(stream->video_out, stream, &width, &height, &img_duration)) { /* register our stream at the new output port */ (new_port->open) (new_port, stream); stream->video_out->close(stream->video_out, stream); } stream->video_out = new_port; - + stream->xine->port_ticket->issue(stream->xine->port_ticket, 1); return 1; } -void xine_dispose_internal (xine_stream_t *stream); +static void xine_dispose_internal (xine_stream_t *stream); xine_stream_t *xine_stream_new (xine_t *this, xine_audio_port_t *ao, xine_video_port_t *vo) { @@ -569,7 +578,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_lock (&this->streams_lock); - stream = (xine_stream_t *) xine_xmalloc (sizeof (xine_stream_t)) ; + stream = (xine_stream_t *) calloc (1, sizeof (xine_stream_t)) ; stream->current_extra_info = malloc( sizeof( extra_info_t ) ); stream->audio_decoder_extra_info = malloc( sizeof( extra_info_t ) ); stream->video_decoder_extra_info = malloc( sizeof( extra_info_t ) ); @@ -595,30 +604,31 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->early_finish_event = 0; stream->delay_finish_event = 0; stream->gapless_switch = 0; + stream->keep_ao_driver_open = 0; stream->video_out = vo; if (vo) stream->video_driver = vo->driver; else stream->video_driver = NULL; - + stream->video_channel = 0; stream->video_decoder_plugin = NULL; stream->video_decoder_streamtype = -1; - stream->header_count_audio = 0; - stream->header_count_video = 0; - stream->finished_count_audio = 0; + stream->header_count_audio = 0; + stream->header_count_video = 0; + stream->finished_count_audio = 0; stream->finished_count_video = 0; stream->err = 0; stream->broadcaster = NULL; - + /* * initial master/slave */ stream->master = stream; stream->slave = NULL; stream->slave_is_subtitle = 0; - + /* * init mutexes and conditions */ @@ -628,6 +638,7 @@ xine_stream_t *xine_stream_new (xine_t *this, pthread_mutex_init (&stream->meta_mutex, NULL); pthread_mutex_init (&stream->demux_lock, NULL); pthread_mutex_init (&stream->demux_mutex, NULL); + pthread_cond_init (&stream->demux_resume, NULL); pthread_mutex_init (&stream->event_queues_lock, NULL); pthread_mutex_init (&stream->counter_lock, NULL); pthread_cond_init (&stream->counter_changed, NULL); @@ -652,7 +663,7 @@ xine_stream_t *xine_stream_new (xine_t *this, _x_meta_info_reset(stream, i); _x_meta_info_public_reset(stream, i); } - + /* * event queues */ @@ -723,22 +734,22 @@ xine_stream_t *xine_stream_new (xine_t *this, stream->video_source.type = XINE_POST_DATA_VIDEO; stream->video_source.data = stream; stream->video_source.rewire = stream_rewire_video; - + stream->audio_source.name = "audio source"; stream->audio_source.type = XINE_POST_DATA_AUDIO; stream->audio_source.data = stream; stream->audio_source.rewire = stream_rewire_audio; - + return stream; } void _x_mrl_unescape(char *mrl) { - int i, len = strlen(mrl); + size_t i, len = strlen(mrl); for (i = 0; i < len; i++) { if ((mrl[i]=='%') && (i<(len-2))) { unsigned int c; - + if (sscanf(&mrl[i + 1], "%02x", &c) == 1) { mrl[i]= (char)c; memmove(mrl + i + 1, mrl + i + 3, len - i - 3); @@ -780,11 +791,25 @@ void _x_flush_events_queues (xine_stream_t *stream) { pthread_mutex_unlock (&stream->event_queues_lock); } -/*static*/ int open_internal (xine_stream_t *stream, const char *mrl) { +static inline int _x_path_looks_like_mrl (const char *path) +{ + if ((*path & 0xDF) < 'A' || (*path & 0xDF) > 'Z') + return 0; + + for (++path; *path; ++path) + if ((*path != '-' && *path < '0') || (*path > '9' && *path < 'A') || + (*path > 'Z' && *path < 'a') || *path > 'z') + break; + + return path[0] == ':' && path[1] == '/'; +} + +static int open_internal (xine_stream_t *stream, const char *mrl) { const char *stream_setup = NULL; + const char *mrl_proto = NULL; int no_cache = 0; - + if (!mrl) { xprintf (stream->xine, XINE_VERBOSITY_LOG, _("xine: error while parsing mrl\n")); stream->err = XINE_ERROR_MALFORMED_MRL; @@ -806,33 +831,50 @@ void _x_flush_events_queues (xine_stream_t *stream) { /* * look for a stream_setup in MRL and try finding an input plugin */ + stream_setup = strchr (mrl, '#'); if (isalpha (*mrl)) { - stream_setup = mrl + 1; - while (isalnum (*stream_setup) || *stream_setup == '+' || *stream_setup == '-' || *stream_setup == '.') - ++stream_setup; - if (stream_setup[0] == ':' && stream_setup[1] == '/') - stream_setup = strchr (mrl, '#'); - else - stream_setup = NULL; + mrl_proto = mrl + 1; + while (isalnum (*mrl_proto) || *mrl_proto == '+' || *mrl_proto == '-' || *mrl_proto == '.') + ++mrl_proto; + if (!mrl_proto[0] || mrl_proto[0] != ':' || mrl_proto[1] != '/') + mrl_proto = NULL; + } + + /* for raw filenames we must try every '#' checking if it is part of the filename */ + if( !mrl_proto && stream_setup) { + struct stat stat_buf; + int res; + + while( stream_setup ) { + char *raw_filename = strndup (mrl, stream_setup - mrl); + + res = stat(raw_filename, &stat_buf); + free(raw_filename); + if( !res ) + break; + stream_setup = strchr(stream_setup + 1, '#'); + } } - + { char *input_source = strndup (mrl, stream_setup ? stream_setup - mrl : strlen (mrl)); /* * find an input plugin */ + stream->input_plugin = _x_find_input_plugin (stream, input_source); + free(input_source); - if ((stream->input_plugin = _x_find_input_plugin (stream, input_source))) { + if ( stream->input_plugin ) { int res; xine_log (stream->xine, XINE_LOG_MSG, _("xine: found input plugin : %s\n"), stream->input_plugin->input_class->get_description(stream->input_plugin->input_class)); if (stream->input_plugin->input_class->eject_media) stream->eject_class = stream->input_plugin->input_class; - _x_meta_info_set_utf8(stream, XINE_META_INFO_INPUT_PLUGIN, + _x_meta_info_set_utf8(stream, XINE_META_INFO_INPUT_PLUGIN, (stream->input_plugin->input_class->get_identifier (stream->input_plugin->input_class))); res = (stream->input_plugin->open) (stream->input_plugin); @@ -840,7 +882,6 @@ void _x_flush_events_queues (xine_stream_t *stream) { case 1: /* Open successfull */ break; case -1: /* Open unsuccessfull, but correct plugin */ - free(input_source); stream->err = XINE_ERROR_INPUT_FAILED; _x_flush_events_queues (stream); return 0; @@ -851,10 +892,8 @@ void _x_flush_events_queues (xine_stream_t *stream) { stream->err = XINE_ERROR_INPUT_FAILED; } } - - free(input_source); } - + if (!stream->input_plugin) { xine_log (stream->xine, XINE_LOG_MSG, _("xine: cannot find input plugin for MRL [%s]\n"),mrl); stream->err = XINE_ERROR_NO_INPUT_PLUGIN; @@ -917,11 +956,12 @@ void _x_flush_events_queues (xine_stream_t *stream) { memcpy(filename, tmp, strlen(tmp)); filename[strlen(tmp)] = '\0'; } + _x_mrl_unescape(filename); xine_log(stream->xine, XINE_LOG_MSG, _("xine: join rip input plugin\n")); input_saver = _x_rip_plugin_get_instance (stream, filename); free(filename); - + if( input_saver ) { stream->input_plugin = input_saver; } else { @@ -1091,13 +1131,15 @@ void _x_flush_events_queues (xine_stream_t *stream) { memcpy(subtitle_mrl, tmp, strlen(tmp)); subtitle_mrl[strlen(tmp)] = '\0'; } - _x_mrl_unescape(subtitle_mrl); + /* unescape for xine_open() if the MRL looks like a raw pathname */ + if (!_x_path_looks_like_mrl(subtitle_mrl)) + _x_mrl_unescape(subtitle_mrl); stream->slave = xine_stream_new (stream->xine, NULL, stream->video_out ); stream->slave_affection = XINE_MASTER_SLAVE_PLAY | XINE_MASTER_SLAVE_STOP; if( xine_open( stream->slave, subtitle_mrl ) ) { xprintf (stream->xine, XINE_VERBOSITY_LOG, _("subtitle mrl opened '%s'\n"), subtitle_mrl); stream->slave->master = stream; - stream->slave_is_subtitle = 1; + stream->slave_is_subtitle = 1; } else { xprintf(stream->xine, XINE_VERBOSITY_LOG, _("xine: error opening subtitle mrl\n")); xine_dispose( stream->slave ); @@ -1152,6 +1194,27 @@ void _x_flush_events_queues (xine_stream_t *stream) { /* enable buffered input plugin (request optimizer) */ stream->input_plugin = _x_cache_plugin_get_instance(stream, 0); + /* Let the plugin request a specific demuxer (if the user hasn't). + * This overrides find-by-content & find-by-extension. + */ + if (!stream->demux_plugin) + { + char *default_demux = NULL; + stream->input_plugin->get_optional_data (stream->input_plugin, &default_demux, INPUT_OPTIONAL_DATA_DEMUXER); + if (default_demux) + { + stream->demux_plugin = _x_find_demux_plugin_by_name (stream, default_demux, stream->input_plugin); + if (stream->demux_plugin) + { + lprintf ("demux and input plugin found\n"); + _x_meta_info_set_utf8 (stream, XINE_META_INFO_SYSTEMLAYER, + stream->demux_plugin->demux_class->get_identifier (stream->demux_plugin->demux_class)); + } + else + xine_log (stream->xine, XINE_LOG_MSG, _("xine: couldn't load plugin-specified demux %s for >%s<\n"), default_demux, mrl); + } + } + if (!stream->demux_plugin) { /* @@ -1275,9 +1338,9 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) /* set normal speed */ if (_x_get_speed(stream) != XINE_SPEED_NORMAL) set_speed_internal (stream, XINE_FINE_SPEED_NORMAL); - + stream->xine->port_ticket->acquire(stream->xine->port_ticket, 1); - + /* only flush/discard output ports on master streams */ if( stream->master == stream && !stream->gapless_switch) { /* discard audio/video buffers to get engine going and take the lock faster */ @@ -1286,25 +1349,26 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 1); } - + pthread_mutex_lock( &stream->demux_lock ); /* demux_lock taken. now demuxer is suspended */ stream->demux_action_pending = 0; + pthread_cond_signal(&stream->demux_resume); - /* set normal speed again (now that demuxer/input pair is suspended) + /* set normal speed again (now that demuxer/input pair is suspended) * some input plugin may have changed speed by itself, we must ensure * the engine is not paused. */ if (_x_get_speed(stream) != XINE_SPEED_NORMAL) set_speed_internal (stream, XINE_FINE_SPEED_NORMAL); - + /* * start/seek demux */ /* seek to new position (no data is sent to decoders yet) */ demux_status = stream->demux_plugin->seek (stream->demux_plugin, - start_pos, start_time, + start_pos, start_time, stream->demux_thread_running); /* only flush/discard output ports on master streams */ @@ -1314,9 +1378,9 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) if (stream->video_out) stream->video_out->set_property(stream->video_out, VO_PROP_DISCARD_FRAMES, 0); } - + stream->xine->port_ticket->release(stream->xine->port_ticket, 1); - + /* before resuming the demuxer, set first_frame_flag */ pthread_mutex_lock (&stream->first_frame_lock); stream->first_frame_flag = 2; @@ -1328,7 +1392,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) pthread_mutex_unlock( &stream->current_extra_info_lock ); demux_thread_running = stream->demux_thread_running; - + /* now resume demuxer thread if it is running already */ pthread_mutex_unlock( &stream->demux_lock ); @@ -1351,7 +1415,7 @@ static int play_internal (xine_stream_t *stream, int start_pos, int start_time) * see video_out.c */ wait_first_frame (stream); - + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "play_internal ...done\n"); return 1; @@ -1365,26 +1429,26 @@ int xine_play (xine_stream_t *stream, int start_pos, int start_time) { pthread_cleanup_push (mutex_cleanup, (void *) &stream->frontend_lock); stream->delay_finish_event = 0; - + ret = play_internal (stream, start_pos, start_time); if( stream->slave && (stream->slave_affection & XINE_MASTER_SLAVE_PLAY) ) xine_play (stream->slave, start_pos, start_time); - + stream->gapless_switch = 0; pthread_cleanup_pop (0); pthread_mutex_unlock (&stream->frontend_lock); - + return ret; } int xine_eject (xine_stream_t *stream) { - + int status; - if (!stream->eject_class) + if (!stream->eject_class) return 0; - + pthread_mutex_lock (&stream->frontend_lock); pthread_cleanup_push (mutex_cleanup, (void *) &stream->frontend_lock); @@ -1399,11 +1463,11 @@ int xine_eject (xine_stream_t *stream) { pthread_cleanup_pop (0); pthread_mutex_unlock (&stream->frontend_lock); - + return status; } -void xine_dispose_internal (xine_stream_t *stream) { +static void xine_dispose_internal (xine_stream_t *stream) { xine_list_iterator_t *ite; @@ -1416,6 +1480,7 @@ void xine_dispose_internal (xine_stream_t *stream) { pthread_mutex_destroy (&stream->current_extra_info_lock); pthread_cond_destroy (&stream->counter_changed); pthread_mutex_destroy (&stream->demux_mutex); + pthread_cond_destroy (&stream->demux_resume); pthread_mutex_destroy (&stream->demux_lock); pthread_mutex_destroy (&stream->first_frame_lock); pthread_cond_destroy (&stream->first_frame_reached); @@ -1430,7 +1495,7 @@ void xine_dispose_internal (xine_stream_t *stream) { pthread_mutex_unlock(&stream->xine->streams_lock); _x_refcounter_dispose(stream->refcounter); - + free (stream->current_extra_info); free (stream->video_decoder_extra_info); free (stream->audio_decoder_extra_info); @@ -1448,7 +1513,7 @@ void xine_dispose (xine_stream_t *stream) { xine_close(stream); if( stream->master != stream ) { - stream->master->slave = NULL; + stream->master->slave = NULL; } if( stream->slave && stream->slave->master == stream ) { stream->slave->master = NULL; @@ -1456,7 +1521,7 @@ void xine_dispose (xine_stream_t *stream) { if(stream->broadcaster) _x_close_broadcaster(stream->broadcaster); - + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "shutdown audio\n"); _x_audio_decoder_shutdown (stream); @@ -1488,13 +1553,13 @@ void xine_exit (xine_t *this) { if(this->clock) this->clock->exit (this->clock); - + if(this->config) this->config->dispose(this->config); if(this->port_ticket) this->port_ticket->dispose(this->port_ticket); - + #if defined(WIN32) WSACleanup(); #endif @@ -1510,7 +1575,7 @@ xine_t *xine_new (void) { int i_err; #endif - this = xine_xmalloc (sizeof (xine_t)); + this = calloc(1, sizeof (xine_t)); if (!this) _x_abort(); @@ -1552,7 +1617,7 @@ xine_t *xine_new (void) { #endif /* WIN32 */ this->verbosity = XINE_VERBOSITY_NONE; - + return this; } @@ -1599,18 +1664,17 @@ static void config_save_cb (void *this_gen, xine_cfg_entry_t *entry) { xine_t *this = (xine_t *)this_gen; char *homedir_trail_slash; - homedir_trail_slash = (char *)malloc(strlen(xine_get_homedir()) + 2); - sprintf(homedir_trail_slash, "%s/", xine_get_homedir()); + asprintf(&homedir_trail_slash, "%s/", xine_get_homedir()); if (entry->str_value[0] && (entry->str_value[0] != '/' || strstr(entry->str_value, "/.") || strcmp(entry->str_value, xine_get_homedir()) == 0 || strcmp(entry->str_value, homedir_trail_slash) == 0)) { xine_stream_t *stream; xine_list_iterator_t ite; - + xine_log(this, XINE_LOG_MSG, _("xine: The specified save_dir \"%s\" might be a security risk.\n"), entry->str_value); - + pthread_mutex_lock(&this->streams_lock); if ( (ite = xine_list_front(this->streams)) ) { stream = xine_list_get_value(this->streams, ite); @@ -1618,7 +1682,7 @@ static void config_save_cb (void *this_gen, xine_cfg_entry_t *entry) { } pthread_mutex_unlock(&this->streams_lock); } - + free(homedir_trail_slash); this->save_path = entry->str_value; } @@ -1627,6 +1691,12 @@ void xine_init (xine_t *this) { static const char *demux_strategies[] = {"default", "reverse", "content", "extension", NULL}; + /* + * locks + */ + pthread_mutex_init (&this->streams_lock, NULL); + pthread_mutex_init (&this->log_lock, NULL); + /* initialize color conversion tables and functions */ init_yuv_conversion(); @@ -1666,7 +1736,7 @@ void xine_init (xine_t *this) { * save directory */ this->save_path = this->config->register_filename ( - this->config, + this->config, "media.capture.save_dir", "", XINE_CONFIG_STRING_IS_DIRECTORY_NAME, _("directory for saving streams"), _("When using the stream save feature, files will be written only into this directory.\n" @@ -1674,7 +1744,7 @@ void xine_init (xine_t *this) { "can be used to fill files in it with arbitrary content. So you should be careful that " "the directory you specify is robust against any content in any file."), XINE_CONFIG_SECURITY, config_save_cb, this); - + /* * implicit configuration changes */ @@ -1708,19 +1778,13 @@ void xine_init (xine_t *this) { this->streams = xine_list_new(); /* - * locks - */ - pthread_mutex_init (&this->streams_lock, NULL); - pthread_mutex_init (&this->log_lock, NULL); - - /* * start metronom clock */ this->clock = _x_metronom_clock_init(this); this->clock->start_clock (this->clock, 0); - + /* * tickets */ @@ -1733,7 +1797,7 @@ void _x_select_spu_channel (xine_stream_t *stream, int channel) { stream->spu_channel_user = (channel >= -2 ? channel : -2); stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); - + switch (stream->spu_channel_user) { case -2: stream->spu_channel = -1; @@ -1753,7 +1817,7 @@ void _x_select_spu_channel (xine_stream_t *stream, int channel) { lprintf("set to %d\n",stream->spu_channel); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); - + pthread_mutex_unlock (&stream->frontend_lock); } @@ -1813,10 +1877,10 @@ void _x_set_fine_speed (xine_stream_t *stream, int speed) { { if (speed <= XINE_SPEED_PAUSE) speed = XINE_SPEED_PAUSE; - + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "set_speed %d\n", speed); set_speed_internal (stream, speed); - + if (stream->slave && (stream->slave_affection & XINE_MASTER_SLAVE_SPEED)) set_speed_internal (stream->slave, speed); } @@ -1828,7 +1892,7 @@ int _x_get_fine_speed (xine_stream_t *stream) { } void _x_set_speed (xine_stream_t *stream, int speed) { - + if (speed > XINE_SPEED_FAST_4) speed = XINE_SPEED_FAST_4; @@ -1837,13 +1901,13 @@ void _x_set_speed (xine_stream_t *stream, int speed) { int _x_get_speed (xine_stream_t *stream) { int speed = _x_get_fine_speed (stream); - + /* - * ensure compatibility with old API, only valid XINE_SPEED_xxx + * ensure compatibility with old API, only valid XINE_SPEED_xxx * constants are allowed. XINE_SPEED_NORMAL may only be returned * if speed is exactly XINE_FINE_SPEED_NORMAL. */ - + if( speed <= XINE_SPEED_PAUSE ) return XINE_SPEED_PAUSE; if( speed <= XINE_SPEED_SLOW_4 * XINE_FINE_SPEED_NORMAL / XINE_SPEED_NORMAL ) @@ -1899,50 +1963,98 @@ int xine_get_pos_length (xine_stream_t *stream, int *pos_stream, return 1; } -int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, - int *ratio_code, int *format, - uint8_t *img) { +static int _x_get_current_frame_data (xine_stream_t *stream, + xine_current_frame_data_t *data, + int flags, int img_size_unknown) { vo_frame_t *frame; + size_t required_size; stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); - - if (!frame) + + if (!frame) { + data->img_size = 0; return 0; + } - *width = frame->width; - *height = frame->height; + data->width = frame->width; + data->height = frame->height; + data->crop_left = frame->crop_left; + data->crop_right = frame->crop_right; + data->crop_top = frame->crop_top; + data->crop_bottom = frame->crop_bottom; - *ratio_code = 10000.0 * frame->ratio; + data->ratio_code = 10000.0 * frame->ratio; /* make ratio_code backward compatible */ #define RATIO_LIKE(a, b) ((b) - 1 <= (a) && (a) <= 1 + (b)) - if (RATIO_LIKE(*ratio_code, 10000)) - *ratio_code = XINE_VO_ASPECT_SQUARE; - else if (RATIO_LIKE(*ratio_code, 13333)) - *ratio_code = XINE_VO_ASPECT_4_3; - else if (RATIO_LIKE(*ratio_code, 17778)) - *ratio_code = XINE_VO_ASPECT_ANAMORPHIC; - else if (RATIO_LIKE(*ratio_code, 21100)) - *ratio_code = XINE_VO_ASPECT_DVB; - - *format = frame->format; - - if (img){ + if (RATIO_LIKE(data->ratio_code, 10000)) + data->ratio_code = XINE_VO_ASPECT_SQUARE; + else if (RATIO_LIKE(data->ratio_code, 13333)) + data->ratio_code = XINE_VO_ASPECT_4_3; + else if (RATIO_LIKE(data->ratio_code, 17778)) + data->ratio_code = XINE_VO_ASPECT_ANAMORPHIC; + else if (RATIO_LIKE(data->ratio_code, 21100)) + data->ratio_code = XINE_VO_ASPECT_DVB; + + data->format = frame->format; + data->interlaced = frame->progressive_frame ? 0 : (2 - frame->top_field_first); + + switch (frame->format) { + + case XINE_IMGFMT_YV12: + required_size = frame->width * frame->height + + ((frame->width + 1) / 2) * ((frame->height + 1) / 2) + + ((frame->width + 1) / 2) * ((frame->height + 1) / 2); + break; + + case XINE_IMGFMT_YUY2: + required_size = frame->width * frame->height + + ((frame->width + 1) / 2) * frame->height + + ((frame->width + 1) / 2) * frame->height; + break; + + default: + if (data->img || (flags & XINE_FRAME_DATA_ALLOCATE_IMG)) { + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); + _x_abort (); + } + + required_size = 0; + } + + if (flags & XINE_FRAME_DATA_ALLOCATE_IMG) { + /* return allocated buffer size */ + data->img_size = required_size; + /* allocate img or fail */ + if (!(data->img = calloc(1, required_size))) + return 0; + } else { + /* fail if supplied buffer is to small */ + if (data->img && !img_size_unknown && data->img_size < required_size) { + data->img_size = required_size; + return 0; + } + /* return used buffer size */ + data->img_size = required_size; + } + + if (data->img) { switch (frame->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( /* Y */ frame->base[0], frame->pitches[0], - img, frame->width, + data->img, frame->width, /* U */ frame->base[1], frame->pitches[1], - img+frame->width*frame->height, frame->width/2, + data->img+frame->width*frame->height, frame->width/2, /* V */ frame->base[2], frame->pitches[2], - img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, + data->img+frame->width*frame->height+frame->width*frame->height/4, frame->width/2, /* width x height */ frame->width, frame->height); break; @@ -1952,13 +2064,13 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, /* src */ frame->base[0], frame->pitches[0], /* dst */ - img, frame->width*2, + data->img, frame->width*2, /* width x height */ frame->width, frame->height); break; default: - xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); _x_abort (); } @@ -1966,6 +2078,69 @@ int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, return 1; } +int xine_get_current_frame_data (xine_stream_t *stream, + xine_current_frame_data_t *data, + int flags) { + + return _x_get_current_frame_data(stream, data, flags, 0); +} + +int xine_get_current_frame_alloc (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t **img, int *img_size) { + + int result; + xine_current_frame_data_t data; + + memset(&data, 0, sizeof (data)); + + result = _x_get_current_frame_data(stream, &data, img ? XINE_FRAME_DATA_ALLOCATE_IMG : 0, 0); + if (width) *width = data.width; + if (height) *height = data.height; + if (ratio_code) *ratio_code = data.ratio_code; + if (format) *format = data.format; + if (img_size) *img_size = data.img_size; + if (img) *img = data.img; + return result; +} + +int xine_get_current_frame_s (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img, int *img_size) { + int result; + xine_current_frame_data_t data; + + memset(&data, 0, sizeof (data)); + data.img = img; + if (img_size) + data.img_size = *img_size; + + result = _x_get_current_frame_data(stream, &data, 0, 0); + if (width) *width = data.width; + if (height) *height = data.height; + if (ratio_code) *ratio_code = data.ratio_code; + if (format) *format = data.format; + if (img_size) *img_size = data.img_size; + return result; +} + +int xine_get_current_frame (xine_stream_t *stream, int *width, int *height, + int *ratio_code, int *format, + uint8_t *img) { + int result; + xine_current_frame_data_t data; + + memset(&data, 0, sizeof (data)); + data.img = img; + + result = _x_get_current_frame_data(stream, &data, 0, 1); + if (width) *width = data.width; + if (height) *height = data.height; + if (ratio_code) *ratio_code = data.ratio_code; + if (format) *format = data.format; + return result; +} + int xine_get_video_frame (xine_stream_t *stream, int timestamp, /* msec */ int *width, int *height, @@ -2072,7 +2247,7 @@ static inline void check_log_alloc (xine_t *this, int buf) void xine_log (xine_t *this, int buf, const char *format, ...) { va_list argp; char buffer[SCRATCH_LINE_LEN_MAX]; - + check_log_alloc (this, buf); va_start (argp, format); @@ -2084,15 +2259,21 @@ void xine_log (xine_t *this, int buf, const char *format, ...) { vsnprintf(buffer, SCRATCH_LINE_LEN_MAX, format, argp); printf("%s", buffer); va_end (argp); - } + } + + if (this->log_cb) + this->log_cb (this->log_cb_user_data, buf); } -void xine_vlog(xine_t *this, int buf, const char *format, +void xine_vlog(xine_t *this, int buf, const char *format, va_list args) { check_log_alloc (this, buf); this->log_buffers[buf]->scratch_printf(this->log_buffers[buf], format, args); + + if (this->log_cb) + this->log_cb (this->log_cb_user_data, buf); } char *const *xine_get_log (xine_t *this, int buf) { @@ -2107,12 +2288,10 @@ char *const *xine_get_log (xine_t *this, int buf) { } void xine_register_log_cb (xine_t *this, xine_log_cb_t cb, void *user_data) { - - printf ("xine: xine_register_log_cb: not implemented yet.\n"); - _x_abort(); + this->log_cb = cb; + this->log_cb_user_data = user_data; } - int xine_get_error (xine_stream_t *stream) { return stream->err; } @@ -2139,13 +2318,13 @@ int _x_query_buffer_usage(xine_stream_t *stream, int *num_video_buffers, int *nu if (num_video_buffers) *num_video_buffers = (stream->video_fifo ? stream->video_fifo->size(stream->video_fifo) : 0); - + if (num_audio_buffers) *num_audio_buffers = (stream->audio_fifo ? stream->audio_fifo->size(stream->audio_fifo) : 0); - + if ((num_video_frames && stream->video_out) || (num_audio_frames && stream->audio_out)) { - + ticket_acquired = stream->xine->port_ticket->acquire_nonblocking(stream->xine->port_ticket, 1); } diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 50d8796e8..e39c19817 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -46,7 +46,7 @@ #include "demuxers/demux.h" #include "post.h" -/* +/* * version information / checking */ @@ -65,12 +65,12 @@ void xine_get_version (int *major, int *minor, int *sub) { } int xine_check_version(int major, int minor, int sub) { - - if((XINE_MAJOR > major) || - ((XINE_MAJOR == major) && (XINE_MINOR > minor)) || + + if((XINE_MAJOR > major) || + ((XINE_MAJOR == major) && (XINE_MINOR > minor)) || ((XINE_MAJOR == major) && (XINE_MINOR == minor) && (XINE_SUB >= sub))) return 1; - + return 0; } @@ -86,7 +86,7 @@ const char* xine_config_register_string (xine_t *self, int exp_level, xine_config_cb_t changed_cb, void *cb_data) { - + return self->config->register_string (self->config, key, def_value, @@ -107,7 +107,7 @@ const char* xine_config_register_filename (xine_t *self, int exp_level, xine_config_cb_t changed_cb, void *cb_data) { - + return self->config->register_filename (self->config, key, def_value, req_type, description, help, exp_level, @@ -128,7 +128,7 @@ int xine_config_register_range (xine_t *self, description, help, exp_level, changed_cb, cb_data); } - + int xine_config_register_enum (xine_t *self, const char *key, @@ -144,7 +144,7 @@ int xine_config_register_enum (xine_t *self, description, help, exp_level, changed_cb, cb_data); } - + int xine_config_register_num (xine_t *self, const char *key, @@ -155,7 +155,7 @@ int xine_config_register_num (xine_t *self, xine_config_cb_t changed_cb, void *cb_data) { return self->config->register_num (self->config, - key, def_value, + key, def_value, description, help, exp_level, changed_cb, cb_data); } @@ -170,11 +170,11 @@ int xine_config_register_bool (xine_t *self, xine_config_cb_t changed_cb, void *cb_data) { return self->config->register_bool (self->config, - key, def_value, + key, def_value, description, help, exp_level, changed_cb, cb_data); } - + /* * helper function: @@ -210,7 +210,7 @@ static int config_get_current_entry (xine_t *this, xine_cfg_entry_t *entry) { } /* - * get first config item + * get first config item */ int xine_config_get_first_entry (xine_t *this, xine_cfg_entry_t *entry) { int result; @@ -227,12 +227,12 @@ int xine_config_get_first_entry (xine_t *this, xine_cfg_entry_t *entry) { return result; } - + /* * get next config item (iterate through the items) * this will return NULL when called after returning the last item - */ + */ int xine_config_get_next_entry (xine_t *this, xine_cfg_entry_t *entry) { int result; config_values_t *config = this->config; @@ -243,7 +243,7 @@ int xine_config_get_next_entry (xine_t *this, xine_cfg_entry_t *entry) { pthread_mutex_unlock(&config->config_lock); return (xine_config_get_first_entry(this, entry)); } - + /* do not hand out unclaimed entries */ do { config->cur = config->cur->next; @@ -252,11 +252,11 @@ int xine_config_get_next_entry (xine_t *this, xine_cfg_entry_t *entry) { pthread_mutex_unlock(&config->config_lock); return result; -} - +} + /* - * search for a config entry by key + * search for a config entry by key */ int xine_config_lookup_entry (xine_t *this, const char *key, @@ -274,7 +274,7 @@ int xine_config_lookup_entry (xine_t *this, const char *key, return result; } - + /* * update a config entry (which was returned from lookup_entry() ) @@ -294,12 +294,12 @@ void xine_config_update_entry (xine_t *this, const xine_cfg_entry_t *entry) { break; default: - xprintf (this, XINE_VERBOSITY_DEBUG, + xprintf (this, XINE_VERBOSITY_DEBUG, "xine_interface: error, unknown config entry type %d\n", entry->type); _x_abort(); } } - + void xine_config_reset (xine_t *this) { @@ -326,7 +326,7 @@ void xine_config_reset (xine_t *this) { int xine_gui_send_vo_data (xine_stream_t *stream, int type, void *data) { - return stream->video_driver->gui_data_exchange (stream->video_driver, + return stream->video_driver->gui_data_exchange (stream->video_driver, type, data); } #endif @@ -334,7 +334,7 @@ int xine_gui_send_vo_data (xine_stream_t *stream, int xine_port_send_gui_data (xine_video_port_t *vo, int type, void *data) { - return vo->driver->gui_data_exchange (vo->driver, + return vo->driver->gui_data_exchange (vo->driver, type, data); } @@ -369,7 +369,7 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { _x_set_speed (stream, value); pthread_mutex_unlock (&stream->frontend_lock); break; - + case XINE_PARAM_FINE_SPEED: pthread_mutex_lock (&stream->frontend_lock); _x_set_fine_speed (stream, value); @@ -379,7 +379,7 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_AV_OFFSET: stream->metronom->set_option (stream->metronom, METRONOM_AV_OFFSET, value); break; - + case XINE_PARAM_SPU_OFFSET: stream->metronom->set_option (stream->metronom, METRONOM_SPU_OFFSET, value); break; @@ -417,14 +417,14 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { stream->audio_out->set_property (stream->audio_out, AO_PROP_MUTE_VOL, value); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; - + case XINE_PARAM_AUDIO_COMPR_LEVEL: stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) stream->audio_out->set_property (stream->audio_out, AO_PROP_COMPRESSOR, value); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; - + case XINE_PARAM_AUDIO_AMP_LEVEL: stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) { @@ -464,8 +464,8 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_EQ_16000HZ: stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); if (stream->audio_out) - stream->audio_out->set_property (stream->audio_out, - param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ, + stream->audio_out->set_property (stream->audio_out, + param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ, value); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; @@ -495,15 +495,15 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { case XINE_PARAM_IGNORE_VIDEO: _x_stream_info_set(stream, XINE_STREAM_INFO_IGNORE_VIDEO, value); break; - + case XINE_PARAM_IGNORE_AUDIO: _x_stream_info_set(stream, XINE_STREAM_INFO_IGNORE_AUDIO, value); break; - + case XINE_PARAM_IGNORE_SPU: _x_stream_info_set(stream, XINE_STREAM_INFO_IGNORE_SPU, value); break; - + case XINE_PARAM_METRONOM_PREBUFFER: stream->metronom->set_option(stream->metronom, METRONOM_PREBUFFER, value); break; @@ -516,23 +516,26 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { stream->broadcaster = NULL; } break; - + case XINE_PARAM_EARLY_FINISHED_EVENT: stream->early_finish_event = !!value; break; - + case XINE_PARAM_DELAY_FINISHED_EVENT: stream->delay_finish_event = value; break; - + case XINE_PARAM_GAPLESS_SWITCH: stream->gapless_switch = !!value; + if( stream->gapless_switch && !stream->early_finish_event ) { + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "frontend possibly buggy: gapless_switch without early_finish_event\n"); + } break; - + default: xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine_interface: unknown or deprecated stream param %d set\n", param); - } + } } int xine_get_param (xine_stream_t *stream, int param) { @@ -542,7 +545,7 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_SPEED: ret = _x_get_speed(stream); break; - + case XINE_PARAM_FINE_SPEED: ret = _x_get_fine_speed(stream); break; @@ -550,7 +553,7 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_AV_OFFSET: ret = stream->metronom->get_option (stream->metronom, METRONOM_AV_OFFSET); break; - + case XINE_PARAM_SPU_OFFSET: ret = stream->metronom->get_option (stream->metronom, METRONOM_SPU_OFFSET); break; @@ -573,7 +576,7 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = -1; else ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MIXER_VOL); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_MUTE: @@ -582,7 +585,7 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = -1; else ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_MUTE_VOL); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_COMPR_LEVEL: @@ -591,7 +594,7 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = -1; else ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_COMPRESSOR); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_AMP_LEVEL: @@ -600,7 +603,7 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = -1; else ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_AUDIO_AMP_MUTE: @@ -609,7 +612,7 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = -1; else ret = stream->audio_out->get_property (stream->audio_out, AO_PROP_AMP_MUTE); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_EQ_30HZ: @@ -626,9 +629,9 @@ int xine_get_param (xine_stream_t *stream, int param) { if (!stream->audio_out) ret = -1; else - ret= stream->audio_out->get_property (stream->audio_out, + ret= stream->audio_out->get_property (stream->audio_out, param - XINE_PARAM_EQ_30HZ + AO_PROP_EQ_30HZ); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; case XINE_PARAM_VERBOSITY: @@ -652,17 +655,17 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_VO_CROP_BOTTOM: stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); ret = stream->video_out->get_property(stream->video_out, param); - stream->xine->port_ticket->release(stream->xine->port_ticket, 0); + stream->xine->port_ticket->release(stream->xine->port_ticket, 0); break; - + case XINE_PARAM_IGNORE_VIDEO: ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_VIDEO); break; - + case XINE_PARAM_IGNORE_AUDIO: ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_AUDIO); break; - + case XINE_PARAM_IGNORE_SPU: ret = _x_stream_info_get_public(stream, XINE_STREAM_INFO_IGNORE_SPU); break; @@ -670,22 +673,22 @@ int xine_get_param (xine_stream_t *stream, int param) { case XINE_PARAM_METRONOM_PREBUFFER: ret = stream->metronom->get_option(stream->metronom, METRONOM_PREBUFFER); break; - + case XINE_PARAM_BROADCASTER_PORT: if( stream->broadcaster ) ret = _x_get_broadcaster_port(stream->broadcaster); else ret = 0; break; - + case XINE_PARAM_EARLY_FINISHED_EVENT: ret = stream->early_finish_event; break; - + case XINE_PARAM_DELAY_FINISHED_EVENT: ret = stream->delay_finish_event; break; - + case XINE_PARAM_GAPLESS_SWITCH: ret = stream->gapless_switch; break; @@ -739,6 +742,8 @@ uint32_t xine_get_stream_info (xine_stream_t *stream, int info) { case XINE_STREAM_INFO_IGNORE_AUDIO: case XINE_STREAM_INFO_IGNORE_SPU: case XINE_STREAM_INFO_VIDEO_HAS_STILL: + case XINE_STREAM_INFO_SKIPPED_FRAMES: + case XINE_STREAM_INFO_DISCARDED_FRAMES: case XINE_STREAM_INFO_VIDEO_AFD: case XINE_STREAM_INFO_DVD_TITLE_NUMBER: case XINE_STREAM_INFO_DVD_TITLE_COUNT: @@ -753,7 +758,7 @@ uint32_t xine_get_stream_info (xine_stream_t *stream, int info) { case XINE_STREAM_INFO_MAX_SPU_CHANNEL: return stream->spu_track_map_entries; - + default: xprintf (stream->xine, XINE_VERBOSITY_DEBUG, "xine_interface: unknown or deprecated stream info %d requested\n", info); @@ -774,11 +779,11 @@ xine_osd_t *xine_osd_new(xine_stream_t *stream, int x, int y, int width, int hei uint32_t xine_osd_get_capabilities(xine_osd_t *this) { return this->osd.renderer->get_capabilities(&this->osd); -} +} void xine_osd_draw_point(xine_osd_t *this, int x, int y, int color) { this->osd.renderer->point(&this->osd, x, y, color); -} +} void xine_osd_draw_line(xine_osd_t *this, int x1, int y1, int x2, int y2, int color) { this->osd.renderer->line(&this->osd, x1, y1, x2, y2, color); @@ -866,7 +871,7 @@ const char *const *xine_post_list_outputs(xine_post_t *this_gen) { xine_post_in_t *xine_post_input(xine_post_t *this_gen, const char *name) { post_plugin_t *this = (post_plugin_t *)this_gen; xine_list_iterator_t ite; - + ite = xine_list_front(this->input); while (ite) { xine_post_in_t *input = xine_list_get_value(this->input, ite); @@ -880,7 +885,7 @@ xine_post_in_t *xine_post_input(xine_post_t *this_gen, const char *name) { xine_post_out_t *xine_post_output(xine_post_t *this_gen, const char *name) { post_plugin_t *this = (post_plugin_t *)this_gen; xine_list_iterator_t ite; - + ite = xine_list_front(this->output); while (ite) { xine_post_out_t *output = xine_list_get_value(this->output, ite); @@ -931,7 +936,7 @@ int xine_post_wire_audio_port(xine_post_out_t *source, xine_audio_port_t *ao) { } xine_post_out_t * xine_get_video_source(xine_stream_t *stream) { - return &stream->video_source; + return &stream->video_source; } xine_post_out_t * xine_get_audio_source(xine_stream_t *stream) { @@ -945,7 +950,7 @@ int _x_message(xine_stream_t *stream, int type, ...) { xine_ui_message_data_t *data; xine_event_t event; const char *explanation; - int size; + size_t size; int n; va_list ap; char *s, *params; @@ -988,14 +993,14 @@ int _x_message(xine_stream_t *stream, int type, ...) { va_end(ap); args[n] = NULL; - + size += sizeof(xine_ui_message_data_t) + 1; - data = xine_xmalloc( size ); + data = calloc(1, size ); strcpy(data->compatibility.str, "Upgrade your frontend to see the error messages"); data->type = type; data->num_parameters = n; - + if( explanation ) { strcpy(data->messages, explanation); data->explanation = data->messages - (char *)data; @@ -1006,10 +1011,10 @@ int _x_message(xine_stream_t *stream, int type, ...) { } data->parameters = params - (char *)data; - + n = 0; *params = '\0'; - + while(args[n]) { strcpy(params, args[n]); params += strlen(args[n]) + 1; diff --git a/src/xine-engine/xine_internal.h b/src/xine-engine/xine_internal.h index 9b69f16f1..7566c83e0 100644 --- a/src/xine-engine/xine_internal.h +++ b/src/xine-engine/xine_internal.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -96,11 +96,11 @@ typedef struct xine_ticket_s xine_ticket_t; */ struct xine_s { - + config_values_t *config; plugin_catalog_t *plugin_catalog; - + int demux_strategy; char *save_path; @@ -111,12 +111,15 @@ struct xine_s { xine_list_t *streams; pthread_mutex_t streams_lock; - + metronom_clock_t *clock; #ifdef XINE_ENGINE_INTERNAL xine_ticket_t *port_ticket; pthread_mutex_t log_lock; + + xine_log_cb_t log_cb; + void *log_cb_user_data; #endif }; @@ -131,34 +134,34 @@ struct xine_ticket_s { * the ticket before any operation that might block * * you must never write to this member directly - */ + */ int ticket_revoked; - + /* apply for a ticket; between acquire and relese of an irrevocable * ticket (be sure to pair them properly!), it is guaranteed that you * will never be blocked by ticket revocation */ void (*acquire)(xine_ticket_t *self, int irrevocable); - + /* give a ticket back */ void (*release)(xine_ticket_t *self, int irrevocable); - + /* renew a ticket, when it has been revoked, see ticket_revoked above; * irrevocable must be set to one, if your thread might have acquired * irrevocable tickets you don't know of; set it to zero only when * you know that this is impossible */ void (*renew)(xine_ticket_t *self, int irrevocable); - + #ifdef XINE_ENGINE_INTERNAL /* allow handing out new tickets */ void (*issue)(xine_ticket_t *self, int atomic); - + /* revoke all tickets and deny new ones; * a pair of atomic revoke and issue cannot be interrupted by another * revocation or by other threads acquiring tickets */ void (*revoke)(xine_ticket_t *self, int atomic); - + /* behaves like acquire() but doesn't block the calling thread; when - * the thread would have been blocked, 0 is returned otherwise 1 + * the thread would have been blocked, 0 is returned otherwise 1 * this function acquires a ticket even if ticket revocation is active */ int (*acquire_nonblocking)(xine_ticket_t *self, int irrevocable); @@ -167,7 +170,7 @@ struct xine_ticket_s { void (*release_nonblocking)(xine_ticket_t *self, int irrevocable); void (*dispose)(xine_ticket_t *self); - + pthread_mutex_t lock; pthread_mutex_t revoke_lock; pthread_cond_t issued; @@ -206,28 +209,28 @@ struct xine_event_queue_s { */ struct xine_stream_s { - + /* reference to xine context */ xine_t *xine; - /* metronom instance used by current stream */ + /* metronom instance used by current stream */ metronom_t *metronom; - + /* demuxers use input_plugin to read data */ input_plugin_t *input_plugin; - + /* current content detection method, see METHOD_BY_xxx */ int content_detection_method; /* used by video decoders */ xine_video_port_t *video_out; - + /* demuxers send data to video decoders using this fifo */ fifo_buffer_t *video_fifo; - + /* used by audio decoders */ xine_audio_port_t *audio_out; - + /* demuxers send data to audio decoders using this fifo */ fifo_buffer_t *audio_fifo; @@ -240,10 +243,10 @@ struct xine_stream_s { /* input_dvd uses this one. is it possible to add helper functions instead? */ spu_decoder_t *spu_decoder_plugin; - + /* dxr3 use this one, should be possible to fix to use the port instead */ vo_driver_t *video_driver; - + /* these definitely should be made private! */ int audio_channel_auto; int spu_decoder_streamtype; @@ -251,10 +254,10 @@ struct xine_stream_s { int spu_channel_auto; int spu_channel_letterbox; int spu_channel; - + #ifdef XINE_ENGINE_INTERNAL /* these are private variables, plugins must not access them */ - + int status; /* lock controlling speed change access */ @@ -271,7 +274,7 @@ struct xine_stream_s { int video_decoder_streamtype; extra_info_t *video_decoder_extra_info; int video_channel; - + pthread_t audio_thread; int audio_thread_created; audio_decoder_t *audio_decoder_plugin; @@ -318,21 +321,22 @@ struct xine_stream_s { /* wait for headers sent / stream decoding finished */ pthread_mutex_t counter_lock; pthread_cond_t counter_changed; - int header_count_audio; - int header_count_video; - int finished_count_audio; - int finished_count_video; + int header_count_audio; + int header_count_video; + int finished_count_audio; + int finished_count_video; /* event mechanism */ xine_list_t *event_queues; pthread_mutex_t event_queues_lock; - + /* demux thread stuff */ pthread_t demux_thread; int demux_thread_created; int demux_thread_running; pthread_mutex_t demux_lock; int demux_action_pending; + pthread_cond_t demux_resume; pthread_mutex_t demux_mutex; /* used in _x_demux_... functions to synchronize order of pairwise A/V buffer operations */ extra_info_t *current_extra_info; @@ -341,14 +345,14 @@ struct xine_stream_s { xine_post_out_t video_source; xine_post_out_t audio_source; - + int slave_is_subtitle; /* ... and will be automaticaly disposed */ int slave_affection; /* what operations need to be propagated down to the slave? */ - + int err; - + broadcaster_t *broadcaster; - + refcounter_t *refcounter; int emergency_brake; /* something went really wrong and this stream must be @@ -357,6 +361,7 @@ struct xine_stream_s { int early_finish_event; /* do not wait fifos get empty before sending event */ int gapless_switch; /* next stream switch will be gapless */ int delay_finish_event; /* delay event in 1/10 sec units. 0=>no delay, -1=>forever */ + int keep_ao_driver_open; #endif }; @@ -388,8 +393,8 @@ input_plugin_t *_x_find_input_plugin (xine_stream_t *stream, const char *mrl) XI demux_plugin_t *_x_find_demux_plugin (xine_stream_t *stream, input_plugin_t *input) XINE_PROTECTED; demux_plugin_t *_x_find_demux_plugin_by_name (xine_stream_t *stream, const char *name, input_plugin_t *input) XINE_PROTECTED; demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const char *last_demux_name, input_plugin_t *input) XINE_PROTECTED; -input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) XINE_PROTECTED; -input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) XINE_PROTECTED; +input_plugin_t *_x_rip_plugin_get_instance (xine_stream_t *stream, const char *filename) XINE_MALLOC XINE_PROTECTED; +input_plugin_t *_x_cache_plugin_get_instance (xine_stream_t *stream, int readahead_size) XINE_MALLOC XINE_PROTECTED; void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) XINE_PROTECTED; void _x_free_demux_plugin (xine_stream_t *stream, demux_plugin_t *demux) XINE_PROTECTED; @@ -407,11 +412,11 @@ void _x_extra_info_reset( extra_info_t *extra_info ) XINE_PROTECTED; void _x_extra_info_merge( extra_info_t *dst, extra_info_t *src ) XINE_PROTECTED; void _x_get_current_info (xine_stream_t *stream, extra_info_t *extra_info, int size) XINE_PROTECTED; - - + + /* demuxer helper functions from demux.c */ -/* +/* * Flush audio and video buffers. It is called from demuxers on * seek/stop, and may be useful when user input changes a stream and * xine-lib has cached buffers that have yet to be played. @@ -441,9 +446,9 @@ void _x_demux_send_data(fifo_buffer_t *fifo, uint8_t *data, int size, int input_normpos, int input_time, int total_time, uint32_t frame_number) XINE_PROTECTED; -int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, - int size, int64_t pts, uint32_t type, - uint32_t decoder_flags, off_t input_normpos, +int _x_demux_read_send_data(fifo_buffer_t *fifo, input_plugin_t *input, + int size, int64_t pts, uint32_t type, + uint32_t decoder_flags, off_t input_normpos, int input_time, int total_time, uint32_t frame_number) XINE_PROTECTED; @@ -456,7 +461,7 @@ void _x_demux_send_mrl_reference (xine_stream_t *stream, int alternative, */ void _x_mrl_unescape(char *mrl) XINE_PROTECTED; -/* +/* * plugin_loader functions * */ diff --git a/src/xine-engine/xine_plugin.h b/src/xine-engine/xine_plugin.h index 74e7523e9..3aa236ceb 100644 --- a/src/xine-engine/xine_plugin.h +++ b/src/xine-engine/xine_plugin.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -33,7 +33,7 @@ #define PLUGIN_VIDEO_OUT 7 #define PLUGIN_POST 8 -#define PLUGIN_TYPE_MAX PLUGIN_POST +#define PLUGIN_TYPE_MAX PLUGIN_POST /* this flag may be or'ed with type in order to force preloading the plugin. * very useful to register config items on xine initialization. diff --git a/src/xine-engine/xineintl.h b/src/xine-engine/xineintl.h index 113a033fa..bb9c006ef 100644 --- a/src/xine-engine/xineintl.h +++ b/src/xine-engine/xineintl.h @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-utils/Makefile.am b/src/xine-utils/Makefile.am index 95de06b9e..501f489fe 100644 --- a/src/xine-utils/Makefile.am +++ b/src/xine-utils/Makefile.am @@ -12,7 +12,7 @@ endif endif AM_CFLAGS = $(X_CFLAGS) $(VISIBILITY_FLAG) -AM_CPPFLAGS=-DXINE_LIBRARY_COMPILE +AM_CPPFLAGS= -DXINE_LIBRARY_COMPILE libxineutils_la_SOURCES = $(pppc_files) \ cpu_accel.c \ @@ -37,6 +37,7 @@ xineinclude_HEADERS = \ compat.h \ xine_buffer.h \ xineutils.h \ + xine_mmx.h \ xmllexer.h \ xmlparser.h \ list.h \ @@ -46,5 +47,5 @@ xineinclude_HEADERS = \ ring_buffer.h -noinst_HEADERS = ppcasm_string.h xine_check.h +noinst_HEADERS = ppcasm_string.h mangle.h diff --git a/src/xine-utils/array.c b/src/xine-utils/array.c index 6c226c7ef..5cb3100ad 100644 --- a/src/xine-utils/array.c +++ b/src/xine-utils/array.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -56,7 +56,7 @@ xine_array_t *xine_array_new(size_t initial_size) { if (initial_size < MIN_CHUNK_SIZE) initial_size = MIN_CHUNK_SIZE; - new_array->chunk = (void**)malloc(sizeof(void*) * initial_size); + new_array->chunk = (void**)calloc(initial_size, sizeof(void*)); if (!new_array->chunk) { free(new_array); return NULL; diff --git a/src/xine-utils/array.h b/src/xine-utils/array.h index ae2093823..cd0780e04 100644 --- a/src/xine-utils/array.h +++ b/src/xine-utils/array.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -27,7 +27,7 @@ typedef struct xine_array_s xine_array_t; /* Constructor */ -xine_array_t *xine_array_new(size_t initial_size) XINE_PROTECTED; +xine_array_t *xine_array_new(size_t initial_size) XINE_MALLOC XINE_PROTECTED; /* Destructor */ void xine_array_delete(xine_array_t *array) XINE_PROTECTED; diff --git a/src/xine-utils/attributes.h b/src/xine-utils/attributes.h index 563832e5c..2326dab18 100644 --- a/src/xine-utils/attributes.h +++ b/src/xine-utils/attributes.h @@ -1,7 +1,7 @@ /* * attributes.h * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> - * Copyright (C) 2001-2007 xine developers + * Copyright (C) 2001-2008 xine developers * * This file was originally part of mpeg2dec, a free MPEG-2 video stream * decoder. @@ -32,20 +32,29 @@ #define ATTR_ALIGN(align) #endif -/* disable GNU __attribute__ extension, when not compiling with GNU C */ -#if defined(__GNUC__) || defined (__ICC) -#ifndef ATTRIBUTE_PACKED -#define ATTRIBUTE_PACKED 1 -#endif -#else -#undef ATTRIBUTE_PACKED -#ifndef __attribute__ -#define __attribute__(x) /**/ -#endif /* __attribute __*/ -#endif - #ifdef XINE_COMPILE # include "configure.h" +#else +# if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95 ) +# define SUPPORT_ATTRIBUTE_PACKED 1 +# endif + +# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3 ) +# define SUPPORT_ATTRIBUTE_DEPRECATED 1 +# define SUPPORT_ATTRIBUTE_FORMAT 1 +# define SUPPORT_ATTRIBUTE_FORMAT_ARG 1 +# define SUPPORT_ATTRIBUTE_MALLOC 1 +# define SUPPORT_ATTRIBUTE_UNUSED 1 +# define SUPPORT_ATTRIBUTE_CONST 1 +# endif + +# if __GNUC__ >= 4 +# define SUPPORT_ATTRIBUTE_VISIBILITY_DEFAULT 1 +# if __ELF__ +# define SUPPORT_ATTRIBUTE_VISIBILITY_PROTECTED 1 +# endif +# define SUPPORT_ATTRIBUTE_SENTINEL 1 +# endif #endif /* Export protected only for libxine functions */ @@ -63,6 +72,12 @@ # define XINE_SENTINEL #endif +#if defined(SUPPORT_ATTRIBUTE_DEPRECATED) && !defined(XINE_COMPILE) +# define XINE_DEPRECATED __attribute__((__deprecated__)) +#else +# define XINE_DEPRECATED +#endif + #ifndef __attr_unused # ifdef SUPPORT_ATTRIBUTE_UNUSED # define __attr_unused __attribute__((__unused__)) @@ -74,8 +89,10 @@ /* Format attributes */ #ifdef SUPPORT_ATTRIBUTE_FORMAT # define XINE_FORMAT_PRINTF(fmt,var) __attribute__((__format__(__printf__, fmt, var))) +# define XINE_FORMAT_SCANF(fmt,var) __attribute__((__format__(__scanf__, fmt, var))) #else # define XINE_FORMAT_PRINTF(fmt,var) +# define XINE_FORMAT_SCANF(fmt,var) #endif #ifdef SUPPORT_ATTRIBUTE_FORMAT_ARG # define XINE_FORMAT_PRINTF_ARG(fmt) __attribute__((__format_arg__(fmt))) @@ -83,4 +100,22 @@ # define XINE_FORMAT_PRINTF_ARG(fmt) #endif +#ifdef SUPPORT_ATTRIBUTE_MALLOC +# define XINE_MALLOC __attribute__((__malloc__)) +#else +# define XINE_MALLOC +#endif + +#ifdef SUPPORT_ATTRIBUTE_PACKED +# define XINE_PACKED __attribute__((__packed__)) +#else +# define XINE_PACKED +#endif + +#ifdef SUPPORT_ATTRIBUTE_CONST +# define XINE_CONST __attribute__((__const__)) +#else +# define XINE_CONST +#endif + #endif /* ATTRIBUTE_H_ */ diff --git a/src/xine-utils/color.c b/src/xine-utils/color.c index 0b9cf0188..bea4cd952 100644 --- a/src/xine-utils/color.c +++ b/src/xine-utils/color.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * Color Conversion Utility Functions - * + * * Overview: xine's video output modules only accept YUV images from * video decoder modules. A video decoder can either send a planar (YV12) * image or a packed (YUY2) image to a video output module. However, many @@ -140,16 +140,16 @@ void (*yuv411_to_yv12) const unsigned char *v_src, int v_src_pitch, unsigned char *v_dest, int v_dest_pitch, int width, int height); void (*yv12_to_yuy2) - (const unsigned char *y_src, int y_src_pitch, - const unsigned char *u_src, int u_src_pitch, - const unsigned char *v_src, int v_src_pitch, + (const unsigned char *y_src, int y_src_pitch, + const unsigned char *u_src, int u_src_pitch, + const unsigned char *v_src, int v_src_pitch, unsigned char *yuy2_map, int yuy2_pitch, int width, int height, int progressive); void (*yuy2_to_yv12) (const unsigned char *yuy2_map, int yuy2_pitch, - unsigned char *y_dst, int y_dst_pitch, - unsigned char *u_dst, int u_dst_pitch, - unsigned char *v_dst, int v_dst_pitch, + unsigned char *y_dst, int y_dst_pitch, + unsigned char *u_dst, int u_dst_pitch, + unsigned char *v_dst, int v_dst_pitch, int width, int height); /* @@ -159,18 +159,14 @@ void (*yuy2_to_yv12) * and height passed to it. The width must be divisible by 2. */ void init_yuv_planes(yuv_planes_t *yuv_planes, int width, int height) { - - int plane_size; - memset (yuv_planes, 0, sizeof (yuv_planes)); yuv_planes->row_width = width; yuv_planes->row_count = height; - plane_size = yuv_planes->row_width * yuv_planes->row_count; - yuv_planes->y = xine_xmalloc(plane_size); - yuv_planes->u = xine_xmalloc(plane_size); - yuv_planes->v = xine_xmalloc(plane_size); + yuv_planes->y = calloc(width, height); + yuv_planes->u = calloc(width, height); + yuv_planes->v = calloc(width, height); } /* @@ -187,7 +183,7 @@ void free_yuv_planes(yuv_planes_t *yuv_planes) { free(yuv_planes->v); } -/* +/* * yuv444_to_yuy2_c * * This is the simple, portable C version of the yuv444_to_yuy2() function. @@ -204,7 +200,7 @@ void free_yuv_planes(yuv_planes_t *yuv_planes) { * * YUY2 map: Y0 U0 Y1 V1 Y2 U2 Y3 V3 */ -static void yuv444_to_yuy2_c(const yuv_planes_t *yuv_planes, unsigned char *yuy2_map, +static void yuv444_to_yuy2_c(const yuv_planes_t *yuv_planes, unsigned char *yuy2_map, int pitch) { unsigned int row_ptr, pixel_ptr; @@ -239,12 +235,12 @@ static void yuv444_to_yuy2_c(const yuv_planes_t *yuv_planes, unsigned char *yuy2 } } -/* +/* * yuv444_to_yuy2_mmx * * This is the proper, filtering version of the yuv444_to_yuy2() function * optimized with basic Intel MMX instructions. - * + * * yuv_planes contains the 3 non-subsampled planes that represent Y, U, * and V samples for every pixel in the image. The goal is to convert the * 3 planes to a single packed YUY2 byte stream. Dealing with the Y @@ -349,7 +345,7 @@ static void yuv444_to_yuy2_mmx(const yuv_planes_t *yuv_planes, unsigned char *yu block_loops--; } - /* set up some MMX registers: + /* set up some MMX registers: * mm0 = 0, mm7 = color filter */ pxor_r2r(mm0, mm0); movq_m2r(*filter, mm7); @@ -529,8 +525,8 @@ static void vscale_chroma_line (unsigned char *dst, int pitch, } } -static void upsample_c_plane_c(const unsigned char *src, int src_width, - int src_height, unsigned char *dest, +static void upsample_c_plane_c(const unsigned char *src, int src_width, + int src_height, unsigned char *dest, unsigned int src_pitch, unsigned int dest_pitch) { unsigned char *cr1; @@ -589,11 +585,11 @@ static void yuv9_to_yv12_c } /* U plane */ - upsample_c_plane_c(u_src, width / 4, height / 4, u_dest, + upsample_c_plane_c(u_src, width / 4, height / 4, u_dest, u_src_pitch, u_dest_pitch); /* V plane */ - upsample_c_plane_c(v_src, width / 4, height / 4, v_dest, + upsample_c_plane_c(v_src, width / 4, height / 4, v_dest, v_src_pitch, v_dest_pitch); } @@ -632,7 +628,7 @@ static void yuv411_to_yv12_c c_src_pixel++) { /* downsample by averaging the samples from 2 rows */ - c_sample = + c_sample = (u_src[c_src_pixel] + u_src[c_src_pixel + u_src_pitch] + 1) / 2; /* upsample by outputting the sample twice on the YV12 row */ u_dest[c_dest_pixel++] = c_sample; @@ -651,7 +647,7 @@ static void yuv411_to_yv12_c c_src_pixel++) { /* downsample by averaging the samples from 2 rows */ - c_sample = + c_sample = (v_src[c_src_pixel] + v_src[c_src_pixel + v_src_pitch] + 1 ) / 2; /* upsample by outputting the sample twice on the YV12 row */ v_dest[c_dest_pixel++] = c_sample; @@ -674,9 +670,9 @@ static void yuv411_to_yv12_c * changed to support interlaced frames and use simple mean interpolation [MF] *****************************************************************************/ static void yv12_to_yuy2_c - (const unsigned char *y_src, int y_src_pitch, - const unsigned char *u_src, int u_src_pitch, - const unsigned char *v_src, int v_src_pitch, + (const unsigned char *y_src, int y_src_pitch, + const unsigned char *u_src, int u_src_pitch, + const unsigned char *v_src, int v_src_pitch, unsigned char *yuy2_map, int yuy2_pitch, int width, int height, int progressive) { @@ -701,15 +697,15 @@ static void yv12_to_yuy2_c { p_line1 = p_line2; p_line2 += yuy2_pitch; - + p_y1 = p_y2; p_y2 += y_src_pitch; - + for( i_x = width / 2 ; i_x-- ; ) { C_YUV420_YUYV( ); } - + p_y2 += i_source_margin; p_u += i_source_u_margin; p_v += i_source_v_margin; @@ -731,15 +727,15 @@ static void yv12_to_yuy2_c { p_line1 = p_line2; p_line2 += 2 * yuy2_pitch; - + p_y1 = p_y2; p_y2 += 2 * y_src_pitch; - + for( i_x = width / 2 ; i_x-- ; ) { C_YUV420_YUYV( ); } - + p_y2 += i_source_margin + y_src_pitch; p_u += i_source_u_margin + u_src_pitch; p_v += i_source_v_margin + v_src_pitch; @@ -752,27 +748,27 @@ static void yv12_to_yuy2_c } p_line2 += i_dest_margin + yuy2_pitch; } - + p_line2 = yuy2_map + yuy2_pitch; p_y2 = y_src + y_src_pitch; p_u = u_src + u_src_pitch; p_v = v_src + v_src_pitch; p_u2 = u_src + 3*u_src_pitch; p_v2 = v_src + 3*v_src_pitch; - + for( i_y = height / 4 ; i_y-- ; ) { p_line1 = p_line2; p_line2 += 2 * yuy2_pitch; - + p_y1 = p_y2; p_y2 += 2 * y_src_pitch; - + for( i_x = width / 2 ; i_x-- ; ) { C_YUV420_YUYV( ); } - + p_y2 += i_source_margin + y_src_pitch; p_u += i_source_u_margin + u_src_pitch; p_v += i_source_v_margin + v_src_pitch; @@ -829,9 +825,9 @@ do { #endif static void yv12_to_yuy2_mmxext - (const unsigned char *y_src, int y_src_pitch, - const unsigned char *u_src, int u_src_pitch, - const unsigned char *v_src, int v_src_pitch, + (const unsigned char *y_src, int y_src_pitch, + const unsigned char *u_src, int u_src_pitch, + const unsigned char *v_src, int v_src_pitch, unsigned char *yuy2_map, int yuy2_pitch, int width, int height, int progressive ) { #if defined(ARCH_X86) || defined(ARCH_X86_64) @@ -855,10 +851,10 @@ static void yv12_to_yuy2_mmxext { p_line1 = p_line2; p_line2 += yuy2_pitch; - + p_y1 = p_y2; p_y2 += y_src_pitch; - + for( i_x = width / 8 ; i_x-- ; ) { MMXEXT_YUV420_YUYV( ); @@ -867,7 +863,7 @@ static void yv12_to_yuy2_mmxext { C_YUV420_YUYV( ); } - + p_y2 += i_source_margin; p_u += i_source_u_margin; p_v += i_source_v_margin; @@ -889,10 +885,10 @@ static void yv12_to_yuy2_mmxext { p_line1 = p_line2; p_line2 += 2 * yuy2_pitch; - + p_y1 = p_y2; p_y2 += 2 * y_src_pitch; - + for( i_x = width / 8 ; i_x-- ; ) { MMXEXT_YUV420_YUYV( ); @@ -901,7 +897,7 @@ static void yv12_to_yuy2_mmxext { C_YUV420_YUYV( ); } - + p_y2 += i_source_margin + y_src_pitch; p_u += i_source_u_margin + u_src_pitch; p_v += i_source_v_margin + v_src_pitch; @@ -914,22 +910,22 @@ static void yv12_to_yuy2_mmxext } p_line2 += i_dest_margin + yuy2_pitch; } - + p_line2 = yuy2_map + yuy2_pitch; p_y2 = y_src + y_src_pitch; p_u = u_src + u_src_pitch; p_v = v_src + v_src_pitch; p_u2 = u_src + 3*u_src_pitch; p_v2 = v_src + 3*v_src_pitch; - + for( i_y = height / 4 ; i_y-- ; ) { p_line1 = p_line2; p_line2 += 2 * yuy2_pitch; - + p_y1 = p_y2; p_y2 += 2 * y_src_pitch; - + for( i_x = width / 8 ; i_x-- ; ) { MMXEXT_YUV420_YUYV( ); @@ -938,7 +934,7 @@ static void yv12_to_yuy2_mmxext { C_YUV420_YUYV( ); } - + p_y2 += i_source_margin + y_src_pitch; p_u += i_source_u_margin + u_src_pitch; p_v += i_source_v_margin + v_src_pitch; @@ -968,9 +964,9 @@ static void yv12_to_yuy2_mmxext static void yuy2_to_yv12_c (const unsigned char *yuy2_map, int yuy2_pitch, - unsigned char *y_dst, int y_dst_pitch, - unsigned char *u_dst, int u_dst_pitch, - unsigned char *v_dst, int v_dst_pitch, + unsigned char *y_dst, int y_dst_pitch, + unsigned char *u_dst, int u_dst_pitch, + unsigned char *v_dst, int v_dst_pitch, int width, int height) { const uint8_t *p_line1, *p_line2 = yuy2_map; @@ -990,10 +986,10 @@ static void yuy2_to_yv12_c { p_line1 = p_line2; p_line2 += yuy2_pitch; - + p_y1 = p_y2; p_y2 += y_dst_pitch; - + for( i_x = width / 8 ; i_x-- ; ) { C_YUYV_YUV420( ); @@ -1001,7 +997,7 @@ static void yuy2_to_yv12_c C_YUYV_YUV420( ); C_YUYV_YUV420( ); } - + p_y2 += i_dest_margin; p_u += i_dest_u_margin; p_v += i_dest_v_margin; @@ -1061,9 +1057,9 @@ do { static void yuy2_to_yv12_mmxext (const unsigned char *yuy2_map, int yuy2_pitch, - unsigned char *y_dst, int y_dst_pitch, - unsigned char *u_dst, int u_dst_pitch, - unsigned char *v_dst, int v_dst_pitch, + unsigned char *y_dst, int y_dst_pitch, + unsigned char *u_dst, int u_dst_pitch, + unsigned char *v_dst, int v_dst_pitch, int width, int height) { #if defined(ARCH_X86) || defined(ARCH_X86_64) const uint8_t *p_line1, *p_line2 = yuy2_map; @@ -1087,15 +1083,15 @@ static void yuy2_to_yv12_mmxext { p_line1 = p_line2; p_line2 += yuy2_pitch; - + p_y1 = p_y2; p_y2 += y_dst_pitch; - + for( i_x = width / 8 ; i_x-- ; ) { MMXEXT_YUYV_YUV420( ); } - + p_y2 += i_dest_margin; p_u += i_dest_u_margin; p_v += i_dest_v_margin; diff --git a/src/xine-utils/compat.h b/src/xine-utils/compat.h index d4b95aeb3..0392b45fd 100644 --- a/src/xine-utils/compat.h +++ b/src/xine-utils/compat.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2001 the xine project - * + * * This file is part of xine, a unix video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-utils/copy.c b/src/xine-utils/copy.c index ed42b3a88..277cb64af 100644 --- a/src/xine-utils/copy.c +++ b/src/xine-utils/copy.c @@ -17,10 +17,10 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * $Id: + * $Id: * */ - + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -32,9 +32,9 @@ void yv12_to_yv12 const unsigned char *u_src, int u_src_pitch, unsigned char *u_dst, int u_dst_pitch, const unsigned char *v_src, int v_src_pitch, unsigned char *v_dst, int v_dst_pitch, int width, int height) { - + int y, half_width = width / 2; - + /* Y Plane */ if(y_src_pitch == y_dst_pitch) xine_fast_memcpy(y_dst, y_src, y_src_pitch*height); @@ -45,7 +45,7 @@ void yv12_to_yv12 y_dst += y_dst_pitch; } } - + /* U/V Planes */ if((u_src_pitch == u_dst_pitch) && (v_src_pitch == v_dst_pitch)) { xine_fast_memcpy(u_dst, u_src, u_src_pitch*height/2); @@ -54,12 +54,12 @@ void yv12_to_yv12 for(y = 0; y < (height / 2); y++) { xine_fast_memcpy(u_dst, u_src, half_width); xine_fast_memcpy(v_dst, v_src, half_width); - + u_src += u_src_pitch; v_src += v_src_pitch; - + u_dst += u_dst_pitch; - v_dst += v_dst_pitch; + v_dst += v_dst_pitch; } } } @@ -68,9 +68,9 @@ void yuy2_to_yuy2 (const unsigned char *src, int src_pitch, unsigned char *dst, int dst_pitch, int width, int height) { - + int y, double_width = width * 2; - + if(src_pitch == dst_pitch) xine_fast_memcpy(dst, src, src_pitch*height); else { diff --git a/src/xine-utils/cpu_accel.c b/src/xine-utils/cpu_accel.c index c241dd7ef..1e12986fb 100644 --- a/src/xine-utils/cpu_accel.c +++ b/src/xine-utils/cpu_accel.c @@ -40,6 +40,10 @@ #include "xineutils.h" +#if defined(PIC) && ! defined(__PIC__) +#define __PIC__ +#endif + #if defined(ARCH_X86) || defined(ARCH_X86_64) static jmp_buf sigill_return; @@ -281,10 +285,10 @@ static uint32_t arch_accel (void) } canjump = 1; - + /* pdist %f0, %f0, %f0 */ __asm__ __volatile__(".word\t0x81b007c0"); - + canjump = 0; flags |= MM_ACCEL_SPARC_VIS; @@ -292,15 +296,15 @@ static uint32_t arch_accel (void) signal(SIGILL, SIG_DFL); return flags; } - + canjump = 1; - + /* edge8n %g0, %g0, %g0 */ __asm__ __volatile__(".word\t0x81b00020"); - + canjump = 0; flags |= MM_ACCEL_SPARC_VIS2; - + signal(SIGILL, SIG_DFL); return flags; } diff --git a/src/xine-utils/list.c b/src/xine-utils/list.c index 65bdaec26..48ef0bff6 100644 --- a/src/xine-utils/list.c +++ b/src/xine-utils/list.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -67,9 +67,9 @@ struct xine_list_s { /* Allocates a new chunk of n elements * One malloc call is used to allocate the struct and the elements. */ -static xine_list_chunk_t *xine_list_alloc_chunk(size_t size) { +static xine_list_chunk_t *XINE_MALLOC xine_list_alloc_chunk(size_t size) { xine_list_chunk_t *new_chunk; - size_t chunk_mem_size;; + size_t chunk_mem_size; chunk_mem_size = sizeof(xine_list_chunk_t); chunk_mem_size += sizeof(xine_list_elem_t) * size; diff --git a/src/xine-utils/list.h b/src/xine-utils/list.h index e00e30d6c..4910f9982 100644 --- a/src/xine-utils/list.h +++ b/src/xine-utils/list.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -48,7 +48,7 @@ typedef struct xine_list_s xine_list_t; typedef void* xine_list_iterator_t; /* Constructor */ -xine_list_t *xine_list_new(void) XINE_PROTECTED; +xine_list_t *xine_list_new(void) XINE_MALLOC XINE_PROTECTED; /* Destructor */ void xine_list_delete(xine_list_t *list) XINE_PROTECTED; diff --git a/src/xine-utils/mangle.h b/src/xine-utils/mangle.h new file mode 100644 index 000000000..4ca7db7a5 --- /dev/null +++ b/src/xine-utils/mangle.h @@ -0,0 +1,54 @@ +/* + * copyright (c) 2006 Michael Niedermayer <michaelni@gmx.at> + * copyright (c) 2008 the xine-project + * + * This file is part of FFmpeg. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + */ + +/** + * @file + * + * @brief MANGLE definition from FFmpeg project, until the code is ported + * not to require this (considered an hack by the FFmpeg project. + */ + +#ifndef _XINE_MANGLE_H +#define _XINE_MANGLE_H + +#if defined(PIC) && ! defined(__PIC__) +#define __PIC__ +#endif + +// Use rip-relative addressing if compiling PIC code on x86-64. +#if defined(__MINGW32__) || defined(__CYGWIN__) || defined(__DJGPP__) || \ + defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__)) +# if defined(__x86_64__) && defined(__PIC__) +# define MANGLE(a) "_" #a"(%%rip)" +# else +# define MANGLE(a) "_" #a +# endif +#else +# if defined(__x86_64__) && defined(__PIC__) +# define MANGLE(a) #a"(%%rip)" +# elif defined(__APPLE__) +# define MANGLE(a) "_" #a +# else +# define MANGLE(a) #a +# endif +#endif + +#endif diff --git a/src/xine-utils/memcpy.c b/src/xine-utils/memcpy.c index 1b3e38fd1..a19e700c5 100644 --- a/src/xine-utils/memcpy.c +++ b/src/xine-utils/memcpy.c @@ -471,7 +471,7 @@ void xine_probe_fast_memcpy(xine_t *xine) #endif NULL }; - + config_flags = xine_mm_accel(); best = xine->config->register_enum (xine->config, "engine.performance.memcpy_method", 0, diff --git a/src/xine-utils/monitor.c b/src/xine-utils/monitor.c index fb323055c..3fe83b3f7 100644 --- a/src/xine-utils/monitor.c +++ b/src/xine-utils/monitor.c @@ -1,18 +1,18 @@ -/* - * Copyright (C) 2000-2003 the xine project - * +/* + * Copyright (C) 2000-2008 the xine project + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -32,44 +32,42 @@ #ifndef NDEBUG -static long long int profiler_times[MAX_ID] ; -static long long int profiler_start[MAX_ID] ; -static long profiler_calls[MAX_ID] ; -static const char *profiler_label[MAX_ID] ; +typedef struct { + uint64_t p_times; + uint64_t p_start; + long p_calls; + const char *p_label; +} xine_profiler_t; + +static xine_profiler_t profiler[MAX_ID]; void xine_profiler_init () { - int i; - for (i=0; i<MAX_ID; i++) { - profiler_times[i] = 0; - profiler_start[i] = 0; - profiler_calls[i] = 0; - profiler_label[i] = NULL; - } + memset(profiler, 0, sizeof(profiler)); } int xine_profiler_allocate_slot (const char *label) { int id; - for (id = 0; id < MAX_ID && profiler_label[id] != NULL; id++) + for (id = 0; id < MAX_ID && profiler[id].p_label != NULL; id++) ; if (id >= MAX_ID) return -1; - profiler_label[id] = label; + profiler[id].p_label = label; return id; } #if defined(ARCH_X86_32) -static __inline__ unsigned long long int rdtsc(void) +static __inline__ uint64_t rdtsc(void) { unsigned long long int x; __asm__ volatile ("rdtsc\n\t" : "=A" (x)); return x; } #elif defined(ARCH_X86_64) -static __inline__ unsigned long long int rdtsc(void) +static __inline__ uint64_t rdtsc(void) { unsigned long long int a, d; __asm__ volatile ("rdtsc\n\t" : "=a" (a), "=d" (d)); @@ -81,7 +79,7 @@ void xine_profiler_start_count (int id) { if ( id >= MAX_ID || id < 0 ) return; #if defined(ARCH_X86) || defined(ARCH_X86_64) - profiler_start[id] = rdtsc(); + profiler[id].p_start = rdtsc(); #endif } @@ -89,18 +87,19 @@ void xine_profiler_stop_count (int id) { if ( id >= MAX_ID || id < 0 ) return; #if defined(ARCH_X86) || defined(ARCH_X86_64) - profiler_times[id] += rdtsc() - profiler_start[id]; + profiler[id].p_times += rdtsc() - profiler[id].p_start; #endif - profiler_calls[id]++; + profiler[id].p_calls++; } void xine_profiler_print_results (void) { int i; #if defined(ARCH_X86) || defined(ARCH_X86_64) - static long long int cpu_speed; /* cpu cyles/usec */ + static uint64_t cpu_speed; /* cpu cyles/usec */ + if (!cpu_speed) { - long long int tsc_start, tsc_end; + uint64_t tsc_start, tsc_end; struct timeval tv_start, tv_end; tsc_start = rdtsc(); @@ -122,13 +121,13 @@ void xine_profiler_print_results (void) { "----------------------------------------------------------------------------\n", "ID", "name", "cpu cycles", "calls", "cycles/call", "usec/call"); for (i=0; i<MAX_ID; i++) { - if (profiler_label[i]) { + if (profiler[i].p_label) { printf ("%2d: %-24.24s %12lld %9ld", - i, profiler_label[i], profiler_times[i], profiler_calls[i]); - if (profiler_calls[i]) { - printf(" %12lld", profiler_times[i] / profiler_calls[i]); + i, profiler[i].p_label, profiler[i].p_times, profiler[i].p_calls); + if (profiler[i].p_calls) { + printf(" %12lld", profiler[i].p_times / profiler[i].p_calls); #if defined(ARCH_X86) || defined(ARCH_X86_64) - printf(" %9lld", profiler_times[i] / (cpu_speed * profiler_calls[i])); + printf(" %9lld", profiler[i].p_times / (cpu_speed * profiler[i].p_calls)); #endif } printf ("\n"); diff --git a/src/xine-utils/pool.c b/src/xine-utils/pool.c index a1fddadd9..8b7f6d9f3 100644 --- a/src/xine-utils/pool.c +++ b/src/xine-utils/pool.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -39,7 +39,7 @@ struct xine_pool_chunk_s { struct xine_pool_s { size_t object_size; - + /* callbacks */ void (*create_object)(void *object); void (*prepare_object)(void *object); @@ -55,7 +55,7 @@ struct xine_pool_s { /* Allocates a new chunk of n elements * One malloc call is used to allocate the struct and the elements. */ -static xine_pool_chunk_t *xine_pool_alloc_chunk(size_t object_size, size_t object_count) { +static xine_pool_chunk_t *XINE_MALLOC xine_pool_alloc_chunk(size_t object_size, size_t object_count) { xine_pool_chunk_t *new_chunk; size_t chunk_mem_size;; diff --git a/src/xine-utils/pool.h b/src/xine-utils/pool.h index 918da82a2..37f60220c 100644 --- a/src/xine-utils/pool.h +++ b/src/xine-utils/pool.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -36,7 +36,7 @@ xine_pool_t *xine_pool_new(size_t object_size, void (create_object)(void *object), void (prepare_object)(void *object), void (return_object)(void *object), - void (delete_object)(void *object)) XINE_PROTECTED; + void (delete_object)(void *object)) XINE_MALLOC XINE_PROTECTED; /* Deletes a pool */ void xine_pool_delete(xine_pool_t *pool) XINE_PROTECTED; diff --git a/src/xine-utils/ring_buffer.c b/src/xine-utils/ring_buffer.c index 031fda4fc..da3e2450c 100644 --- a/src/xine-utils/ring_buffer.c +++ b/src/xine-utils/ring_buffer.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-utils/ring_buffer.h b/src/xine-utils/ring_buffer.h index efcffd3b7..7678aa903 100644 --- a/src/xine-utils/ring_buffer.h +++ b/src/xine-utils/ring_buffer.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -22,7 +22,7 @@ typedef struct xine_ring_buffer_s xine_ring_buffer_t; /* Creates a new ring buffer */ -xine_ring_buffer_t *xine_ring_buffer_new(size_t size) XINE_PROTECTED; +xine_ring_buffer_t *xine_ring_buffer_new(size_t size) XINE_MALLOC XINE_PROTECTED; /* Deletes a ring buffer */ void xine_ring_buffer_delete(xine_ring_buffer_t *ring_buffer) XINE_PROTECTED; diff --git a/src/xine-utils/sorted_array.c b/src/xine-utils/sorted_array.c index 363325f0b..4bb618d4c 100644 --- a/src/xine-utils/sorted_array.c +++ b/src/xine-utils/sorted_array.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-utils/sorted_array.h b/src/xine-utils/sorted_array.h index a1894eca3..0d229199a 100644 --- a/src/xine-utils/sorted_array.h +++ b/src/xine-utils/sorted_array.h @@ -1,25 +1,25 @@ -/* +/* * Copyright (C) 2000-2006 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * Sorted array which grows automatically when you add elements. * A binary search is used to find the position of a new element. - * + * * Example: * Let's create de comparison method for integers: * @@ -63,7 +63,7 @@ typedef struct xine_sarray_s xine_sarray_t; typedef int (*xine_sarray_comparator_t)(void*, void*); /* Constructor */ -xine_sarray_t *xine_sarray_new(size_t initial_size, xine_sarray_comparator_t comparator) XINE_PROTECTED; +xine_sarray_t *xine_sarray_new(size_t initial_size, xine_sarray_comparator_t comparator) XINE_MALLOC XINE_PROTECTED; /* Destructor */ void xine_sarray_delete(xine_sarray_t *sarray) XINE_PROTECTED; diff --git a/src/xine-utils/utils.c b/src/xine-utils/utils.c index c5f18a699..2f62c95a8 100644 --- a/src/xine-utils/utils.c +++ b/src/xine-utils/utils.c @@ -1,18 +1,18 @@ /* * Copyright (C) 2000-2005 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -236,7 +236,25 @@ static const lang_locale_t lang_locales[] = { { NULL, NULL, NULL, NULL } }; - +/** + * @brief Allocate and clean memory size_t 'size', then return the + * pointer to the allocated memory. + * @param size Size of the memory area to allocate. + * + * @return A pointer to the allocated memory area, or NULL in case of + * error. + * + * The behaviour of this function differs from standard malloc() as + * xine_xmalloc(0) will not return a NULL pointer, but rather a + * pointer to a memory area of size 1 byte. + * + * The NULL value is only ever returned in case of an error in + * malloc(), and is reported to stderr stream. + * + * @deprecated This function has been deprecated, as the behaviour of + * allocating a 1 byte memory area on zero size is almost + * never desired, and the function is thus mostly misused. + */ void *xine_xmalloc(size_t size) { void *ptr; @@ -256,12 +274,12 @@ void *xine_xmalloc(size_t size) { void *xine_xmalloc_aligned(size_t alignment, size_t size, void **base) { char *ptr; - - *base = ptr = xine_xmalloc (size+alignment); - + + *base = ptr = calloc(1, size+alignment); + while ((size_t) ptr % alignment) ptr++; - + return ptr; } @@ -324,22 +342,18 @@ const char *xine_get_homedir(void) { char *s; int len; - if (!homedir[0]) { - len = xine_strcpy_command(GetCommandLine(), homedir, sizeof(homedir)); - s = strdup(homedir); - GetFullPathName(s, sizeof(homedir), homedir, NULL); - free(s); - if ((s = strrchr(homedir, '\\'))) *s = '\0'; - } + len = xine_strcpy_command(GetCommandLine(), homedir, sizeof(homedir)); + s = strdup(homedir); + GetFullPathName(s, sizeof(homedir), homedir, NULL); + free(s); + if ((s = strrchr(homedir, '\\'))) + *s = '\0'; return homedir; #else struct passwd pwd, *pw = NULL; static char homedir[BUFSIZ] = {0,}; - if(homedir[0]) - return homedir; - #ifdef HAVE_GETPWUID_R if(getpwuid_r(getuid(), &pwd, homedir, sizeof(homedir), &pw) != 0 || pw == NULL) { #else @@ -375,6 +389,17 @@ static void xine_get_rootdir(char *rootdir, size_t maxlen) { if ((s = strrchr(rootdir, XINE_DIRECTORY_SEPARATOR_CHAR))) *s = '\0'; } +const char *xine_get_pluginroot(void) { + static char pluginroot[1024] = {0, }; + + if (!pluginroot[0]) { + xine_get_rootdir(pluginroot, sizeof(pluginroot) - strlen(XINE_REL_PLUGINROOT) - 1); + strcat(pluginroot, XINE_DIRECTORY_SEPARATOR_STRING XINE_REL_PLUGINROOT); + } + + return pluginroot; +} + const char *xine_get_plugindir(void) { static char plugindir[1024] = {0, }; @@ -431,23 +456,22 @@ char *xine_chomp(char *str) { * a thread-safe usecond sleep */ void xine_usec_sleep(unsigned usec) { -#if 0 -#if HAVE_NANOSLEEP +#ifdef WIN32 + /* select does not work on win32 */ + Sleep(usec / 1000); +#else +# if 0 +# if HAVE_NANOSLEEP /* nanosleep is prefered on solaris, because it's mt-safe */ struct timespec ts, remaining; - ts.tv_sec = usec / 1000000; ts.tv_nsec = (usec % 1000000) * 1000; while (nanosleep (&ts, &remaining) == -1 && errno == EINTR) ts = remaining; -#else -# if WIN32 - Sleep(usec / 1000); -# else +# else usleep(usec); -# endif -#endif -#else +# endif +# else if (usec < 10000) { usec = 10000; } @@ -455,6 +479,7 @@ void xine_usec_sleep(unsigned usec) { tm.tv_sec = usec / 1000000; tm.tv_usec = usec % 1000000; select(0, 0, 0, 0, &tm); +# endif #endif } @@ -497,7 +522,7 @@ void xine_hexdump (const char *buf, int length) { static const lang_locale_t *_get_first_lang_locale(const char *lcal) { const lang_locale_t *llocale; - int lang_len; + size_t lang_len; char *mod; if(lcal && *lcal) { @@ -507,13 +532,13 @@ static const lang_locale_t *_get_first_lang_locale(const char *lcal) { lang_len = mod++ - lcal; else lang_len = strlen(lcal); - + while(llocale->language) { if(!strncmp(lcal, llocale->language, lang_len)) { if ((!mod && !llocale->modifier) || (mod && llocale->modifier && !strcmp(mod, llocale->modifier))) return llocale; } - + llocale++; } } @@ -523,7 +548,7 @@ static const lang_locale_t *_get_first_lang_locale(const char *lcal) { static char *_get_lang(void) { char *lang; - + if(!(lang = getenv("LC_ALL"))) if(!(lang = getenv("LC_MESSAGES"))) lang = getenv("LANG"); @@ -537,9 +562,9 @@ static char *_get_lang(void) { */ char *xine_get_system_encoding(void) { char *codeset = NULL; - + #ifdef HAVE_NL_LANGINFO - setlocale(LC_ALL, ""); + setlocale(LC_CTYPE, ""); codeset = nl_langinfo(CODESET); #endif /* @@ -621,15 +646,15 @@ int xine_monotonic_clock(struct timeval *tv, struct timezone *tz) #if _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) && defined(HAVE_POSIX_TIMERS) static int initialized = 0; static int use_clock_monotonic = 0; - + struct timespec tp; - - if( !initialized ) { + + if( !initialized ) { struct timespec res; int ret; - + ret = clock_getres(CLOCK_MONOTONIC, &res); - + if( ret != 0 ) { lprintf("get resolution of monotonic clock failed\n"); } else { @@ -648,8 +673,8 @@ int xine_monotonic_clock(struct timeval *tv, struct timezone *tz) } } initialized = 1; - } - + } + if(use_clock_monotonic && !clock_gettime(CLOCK_MONOTONIC, &tp)) { tv->tv_sec = tp.tv_sec; tv->tv_usec = tp.tv_nsec / 1000; @@ -659,8 +684,16 @@ int xine_monotonic_clock(struct timeval *tv, struct timezone *tz) } #else - + return gettimeofday(tv, tz); #endif } + +char *xine_strcat_realloc (char **dest, char *append) +{ + char *newstr = realloc (*dest, (*dest ? strlen (*dest) : 0) + strlen (append) + 1); + if (newstr) + strcat (*dest = newstr, append); + return newstr; +} diff --git a/src/xine-utils/xine_buffer.c b/src/xine-utils/xine_buffer.c index 190ab5197..b1cfcf76b 100644 --- a/src/xine-utils/xine_buffer.c +++ b/src/xine-utils/xine_buffer.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -47,6 +47,10 @@ * (eg during reallocation). The user must respect that. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdlib.h> #include <stdio.h> #include <string.h> @@ -70,9 +74,9 @@ typedef struct { uint32_t size; uint32_t chunk_size; - + uint8_t magic; - + } xine_buffer_header_t; #define XINE_BUFFER_HEADER_SIZE 9 @@ -116,8 +120,8 @@ typedef struct { * reallocation on slow growing buffers. */ void *xine_buffer_init(int chunk_size) { - - uint8_t *data=xine_xmalloc(chunk_size+XINE_BUFFER_HEADER_SIZE); + + uint8_t *data=calloc(1, chunk_size+XINE_BUFFER_HEADER_SIZE); xine_buffer_header_t *header=(xine_buffer_header_t*)data; header->size=chunk_size; @@ -153,7 +157,7 @@ void *_xine_buffer_free(void *buf) { void *xine_buffer_dup(const void *buf) { uint8_t *new; - + #ifdef CHECKS if (!buf) { lprintf("warning: got NULL pointer\n"); @@ -162,9 +166,9 @@ void *xine_buffer_dup(const void *buf) { CHECK_MAGIC(buf); #endif -new=xine_xmalloc(GET_HEADER(buf)->size+XINE_BUFFER_HEADER_SIZE); + new = malloc(GET_HEADER(buf)->size+XINE_BUFFER_HEADER_SIZE); - xine_fast_memcpy(new, ((uint8_t*)buf)-XINE_BUFFER_HEADER_SIZE, + xine_fast_memcpy(new, ((uint8_t*)buf)-XINE_BUFFER_HEADER_SIZE, GET_HEADER(buf)->size+XINE_BUFFER_HEADER_SIZE); return new+XINE_BUFFER_HEADER_SIZE; @@ -176,7 +180,7 @@ new=xine_xmalloc(GET_HEADER(buf)->size+XINE_BUFFER_HEADER_SIZE); #define xine_buffer_copyin(buf,i,data,len) \ buf=_xine_buffer_copyin(buf,i,data,len) void *_xine_buffer_copyin(void *buf, int index, const void *data, int len) { - + #ifdef CHECKS if (!buf || !data) { lprintf("warning: got NULL pointer\n"); @@ -233,7 +237,7 @@ void *_xine_buffer_set(void *buf, int index, uint8_t b, int len) { #endif GROW_TO(buf, index+len); - + memset(((uint8_t*)buf)+index, b, len); return buf; @@ -322,6 +326,6 @@ void *_xine_buffer_ensure_size(void *buf, int size) { #endif GROW_TO(buf, size); - + return buf; } diff --git a/src/xine-utils/xine_buffer.h b/src/xine-utils/xine_buffer.h index 84511bd1b..f88a21aef 100644 --- a/src/xine-utils/xine_buffer.h +++ b/src/xine-utils/xine_buffer.h @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2004 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA diff --git a/src/xine-utils/xine_check.c b/src/xine-utils/xine_check.c index f00a23832..ad94b0382 100644 --- a/src/xine-utils/xine_check.c +++ b/src/xine-utils/xine_check.c @@ -44,7 +44,6 @@ #include <fcntl.h> #include <unistd.h> -#include "xine_check.h" #include "xineutils.h" #if defined(__linux__) @@ -102,38 +101,7 @@ set_hc_result(xine_health_check_t* hc, int state, const char *format, ...) #if defined(__linux__) -xine_health_check_t* xine_health_check (xine_health_check_t* hc, int check_num) { - - switch(check_num) { - case CHECK_KERNEL: - hc = _x_health_check_kernel (hc); - break; - case CHECK_MTRR: - hc = _x_health_check_mtrr (hc); - break; - case CHECK_CDROM: - hc = _x_health_check_cdrom (hc); - break; - case CHECK_DVDROM: - hc = _x_health_check_dvdrom (hc); - break; - case CHECK_DMA: - hc = _x_health_check_dma (hc); - break; - case CHECK_X: - hc = _x_health_check_x (hc); - break; - case CHECK_XV: - hc = _x_health_check_xv (hc); - break; - default: - hc->status = XINE_HEALTH_CHECK_NO_SUCH_CHECK; - } - - return hc; -} - -xine_health_check_t* _x_health_check_kernel (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_kernel (xine_health_check_t* hc) { struct utsname kernel; hc->title = "Check for kernel version"; @@ -146,14 +114,14 @@ xine_health_check_t* _x_health_check_kernel (xine_health_check_t* hc) { hc->status = XINE_HEALTH_CHECK_OK; } else { - set_hc_result (hc, XINE_HEALTH_CHECK_FAIL, + set_hc_result (hc, XINE_HEALTH_CHECK_FAIL, "FAILED - Could not get kernel information."); } return hc; } #if defined(ARCH_X86) || defined(ARCH_X86_64) -xine_health_check_t* _x_health_check_mtrr (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_mtrr (xine_health_check_t* hc) { FILE *fd; hc->title = "Check for MTRR support"; @@ -161,7 +129,7 @@ xine_health_check_t* _x_health_check_mtrr (xine_health_check_t* hc) { fd = fopen("/proc/mtrr", "r"); if (!fd) { - set_hc_result (hc, XINE_HEALTH_CHECK_FAIL, + set_hc_result (hc, XINE_HEALTH_CHECK_FAIL, "FAILED: mtrr is not enabled."); } else { hc->status = XINE_HEALTH_CHECK_OK; @@ -170,18 +138,18 @@ xine_health_check_t* _x_health_check_mtrr (xine_health_check_t* hc) { return hc; } #else -xine_health_check_t* _x_health_check_mtrr (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_mtrr (xine_health_check_t* hc) { hc->title = "Check for MTRR support"; hc->explanation = "Don't worry about this one"; - set_hc_result (hc, XINE_HEALTH_CHECK_OK, + set_hc_result (hc, XINE_HEALTH_CHECK_OK, "mtrr does not apply on this hw platform."); return hc; } #endif -xine_health_check_t* _x_health_check_cdrom (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_cdrom (xine_health_check_t* hc) { struct stat cdrom_st; int fd; @@ -194,12 +162,12 @@ xine_health_check_t* _x_health_check_cdrom (xine_health_check_t* hc) { set_hc_result (hc, XINE_HEALTH_CHECK_FAIL, "FAILED - could not access cdrom: %s\n", hc->cdrom_dev); return hc; } - + if ((cdrom_st.st_mode & S_IFMT) != S_IFBLK) { set_hc_result (hc, XINE_HEALTH_CHECK_FAIL, "FAILED - %s is not a block device.\n", hc->cdrom_dev); return hc; } - + if ( (fd = open(hc->cdrom_dev, O_RDWR)) < 0) { switch (errno) { case EACCES: @@ -212,12 +180,12 @@ xine_health_check_t* _x_health_check_cdrom (xine_health_check_t* hc) { } } else close(fd); - + hc->status = XINE_HEALTH_CHECK_OK; return hc; } -xine_health_check_t* _x_health_check_dvdrom(xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_dvdrom(xine_health_check_t* hc) { struct stat dvdrom_st; int fd; @@ -253,7 +221,7 @@ xine_health_check_t* _x_health_check_dvdrom(xine_health_check_t* hc) { return hc; } -xine_health_check_t* _x_health_check_dma (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_dma (xine_health_check_t* hc) { int is_scsi_dev = 0; int fd = 0; @@ -307,11 +275,11 @@ xine_health_check_t* _x_health_check_dma (xine_health_check_t* hc) { } -xine_health_check_t* _x_health_check_x (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_x (xine_health_check_t* hc) { char* env_display = getenv("DISPLAY"); hc->title = "Check for X11 environment"; - hc->explanation = "Make sure you're running X11, if this is an ssh connection,\n" + hc->explanation = "Make sure you're running X11, if this is an ssh connection,\n" "make sure you have X11 forwarding enabled (ssh -X ...)"; if (strlen (env_display) == 0) { @@ -323,7 +291,7 @@ xine_health_check_t* _x_health_check_x (xine_health_check_t* hc) { return hc; } -xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { +static xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { #ifdef HAVE_X11 #ifdef HAVE_XV @@ -373,7 +341,7 @@ xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { dlclose(x11_handle); return hc; } - + dlerror(); /* clear error code */ xv_handle = dlopen(LIBXV_SO, RTLD_LAZY); if(!xv_handle) { @@ -394,7 +362,7 @@ xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { dlclose(xv_handle); return hc; } - + /* Get reference to XvQueryAdaptors */ xvqueryadaptors = dlsym(xv_handle,"XvQueryAdaptors"); if((err = dlerror()) != NULL) { @@ -404,7 +372,7 @@ xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { dlclose(xv_handle); return hc; } - + /* Get reference to XvListImageFormats */ xvlistimageformats = dlsym(xv_handle,"XvListImageFormats"); if((err = dlerror()) != NULL) { @@ -414,7 +382,7 @@ xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { dlclose(xv_handle); return hc; } - + if(!(dpy = (*xopendisplay)(disname))) { if (!disname) { @@ -477,7 +445,7 @@ xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { dlclose(x11_handle); dlclose(xv_handle); - + return hc; #else hc->title = "Check for MIT Xv extension"; @@ -497,12 +465,43 @@ xine_health_check_t* _x_health_check_xv (xine_health_check_t* hc) { #endif /* ! HAVE_X11 */ } +xine_health_check_t* xine_health_check (xine_health_check_t* hc, int check_num) { + + switch(check_num) { + case CHECK_KERNEL: + hc = _x_health_check_kernel (hc); + break; + case CHECK_MTRR: + hc = _x_health_check_mtrr (hc); + break; + case CHECK_CDROM: + hc = _x_health_check_cdrom (hc); + break; + case CHECK_DVDROM: + hc = _x_health_check_dvdrom (hc); + break; + case CHECK_DMA: + hc = _x_health_check_dma (hc); + break; + case CHECK_X: + hc = _x_health_check_x (hc); + break; + case CHECK_XV: + hc = _x_health_check_xv (hc); + break; + default: + hc->status = XINE_HEALTH_CHECK_NO_SUCH_CHECK; + } + + return hc; +} + #else /* !__linux__ */ xine_health_check_t* xine_health_check (xine_health_check_t* hc, int check_num) { hc->title = "xine health check not supported on this platform"; hc->explanation = "contact the xine-devel mailing list if you'd like to\n" "contribute code for your platform."; - set_hc_result(hc, XINE_HEALTH_CHECK_NO_SUCH_CHECK, + set_hc_result(hc, XINE_HEALTH_CHECK_NO_SUCH_CHECK, "xine health check not supported on the OS.\n"); return hc; } diff --git a/src/xine-utils/xine_check.h b/src/xine-utils/xine_check.h deleted file mode 100644 index 4b21bf74e..000000000 --- a/src/xine-utils/xine_check.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef XINE_CHECK_H -#define XINE_CHECK_H -#include <stdio.h> - -#ifdef XINE_COMPILE -# include "xine.h" -#else -# include <xine.h> -#endif - -/* - * Start checking xine setup here - * - * cdrom_dev = Name of the device link for the cdrom drive (e.g. /dev/cdrom) - * dvd_dev = Name of the device link for the dvd drive (e.g. /dev/dvd) - */ - -/* Get Kernel information */ -xine_health_check_t* _x_health_check_kernel(xine_health_check_t*); - -/* health_check MTRR */ -xine_health_check_t* _x_health_check_mtrr(xine_health_check_t*); - -/* health_check CDROM */ -xine_health_check_t* _x_health_check_cdrom(xine_health_check_t*); - -/* health_check DVDROM */ -xine_health_check_t* _x_health_check_dvdrom(xine_health_check_t*); - -/* health_check DMA settings of DVD drive*/ -xine_health_check_t* _x_health_check_dma(xine_health_check_t*); - -/* health_check X */ -xine_health_check_t* _x_health_check_x(xine_health_check_t*); - -/* health_check Xv extension */ -xine_health_check_t* _x_health_check_xv(xine_health_check_t*); - -#endif diff --git a/src/xine-utils/xine_mmx.h b/src/xine-utils/xine_mmx.h new file mode 100644 index 000000000..26e712409 --- /dev/null +++ b/src/xine-utils/xine_mmx.h @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2000-2006 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + */ +#ifndef XINE_MMX_H +#define XINE_MMX_H + +#if defined(ARCH_X86) || defined(ARCH_X86_64) + +typedef union { + int64_t q; /* Quadword (64-bit) value */ + uint64_t uq; /* Unsigned Quadword */ + int d[2]; /* 2 Doubleword (32-bit) values */ + unsigned int ud[2]; /* 2 Unsigned Doubleword */ + short w[4]; /* 4 Word (16-bit) values */ + unsigned short uw[4]; /* 4 Unsigned Word */ + char b[8]; /* 8 Byte (8-bit) values */ + unsigned char ub[8]; /* 8 Unsigned Byte */ + float s[2]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ + + + +#define mmx_i2r(op,imm,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "i" (imm) ) + +#define mmx_m2r(op,mem,reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "m" (mem)) + +#define mmx_r2m(op,reg,mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=m" (mem) \ + : /* nothing */ ) + +#define mmx_r2r(op,regs,regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + + +#define emms() __asm__ __volatile__ ("emms") + +#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) +#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) +#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) + +#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) +#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) +#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) + +#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) +#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) +#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) +#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) + +#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) +#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) + +#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) +#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) +#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) +#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) +#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) +#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) + +#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) +#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) +#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) +#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) + +#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) +#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) +#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) +#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) + +#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) +#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) + +#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) +#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) + +#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) +#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) +#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) +#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) +#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) +#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) + +#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) +#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) +#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) +#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) +#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) +#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) + +#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) +#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) + +#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) +#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) + +#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) +#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) + +#define por_m2r(var,reg) mmx_m2r (por, var, reg) +#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) + +#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) +#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) +#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) +#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) +#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) +#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) +#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) +#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) +#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) + +#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) +#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) +#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) +#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) +#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) +#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) + +#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) +#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) +#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) +#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) +#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) +#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) +#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) +#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) +#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) + +#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) +#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) +#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) +#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) +#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) +#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) + +#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) +#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) +#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) +#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) + +#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) +#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) +#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) +#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) + +#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) +#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) +#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) +#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) +#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) +#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) + +#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) +#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) +#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) +#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) +#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) +#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) + +#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) +#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) + + +/* 3DNOW extensions */ + +#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) +#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) + + +/* AMD MMX extensions - also available in intel SSE */ + + +#define mmx_m2ri(op,mem,reg,imm) \ + __asm__ __volatile__ (#op " %1, %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem), "X" (imm)) +#define mmx_r2ri(op,regs,regd,imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +#define mmx_fetch(mem,hint) \ + __asm__ __volatile__ ("prefetch" #hint " %0" \ + : /* nothing */ \ + : "X" (mem)) + + +#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) + +#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) + +#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) +#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) +#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) +#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) + +#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) + +#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) + +#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) +#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) + +#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) +#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) + +#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) +#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) + +#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) +#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) + +#define pmovmskb(mmreg,reg) \ + __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) + +#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) +#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) + +#define prefetcht0(mem) mmx_fetch (mem, t0) +#define prefetcht1(mem) mmx_fetch (mem, t1) +#define prefetcht2(mem) mmx_fetch (mem, t2) +#define prefetchnta(mem) mmx_fetch (mem, nta) + +#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) +#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) + +#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) +#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) + +#define sfence() __asm__ __volatile__ ("sfence\n\t") + +typedef union { + float sf[4]; /* Single-precision (32-bit) value */ +} ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */ + + +#define sse_i2r(op, imm, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2r(op, mem, reg) \ + __asm__ __volatile__ (#op " %0, %%" #reg \ + : /* nothing */ \ + : "X" (mem)) + +#define sse_r2m(op, reg, mem) \ + __asm__ __volatile__ (#op " %%" #reg ", %0" \ + : "=X" (mem) \ + : /* nothing */ ) + +#define sse_r2r(op, regs, regd) \ + __asm__ __volatile__ (#op " %" #regs ", %" #regd) + +#define sse_r2ri(op, regs, regd, imm) \ + __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ + : /* nothing */ \ + : "X" (imm) ) + +#define sse_m2ri(op, mem, reg, subop) \ + __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ + : /* nothing */ \ + : "X" (mem)) + + +#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) +#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) +#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) + +#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) + +#define movups_m2r(var, reg) sse_m2r(movups, var, reg) +#define movups_r2m(reg, var) sse_r2m(movups, reg, var) +#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) + +#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) + +#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) + +#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) +#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) + +#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) +#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) + +#define movss_m2r(var, reg) sse_m2r(movss, var, reg) +#define movss_r2m(reg, var) sse_r2m(movss, reg, var) +#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) + +#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) +#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) + +#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) +#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) + +#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) +#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) + +#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) +#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) + +#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) +#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) + +#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + +#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) +#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) + +#define movmskps(xmmreg, reg) \ + __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) + +#define addps_m2r(var, reg) sse_m2r(addps, var, reg) +#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) + +#define addss_m2r(var, reg) sse_m2r(addss, var, reg) +#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) + +#define subps_m2r(var, reg) sse_m2r(subps, var, reg) +#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) + +#define subss_m2r(var, reg) sse_m2r(subss, var, reg) +#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) + +#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) +#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) + +#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) +#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) + +#define divps_m2r(var, reg) sse_m2r(divps, var, reg) +#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) + +#define divss_m2r(var, reg) sse_m2r(divss, var, reg) +#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) + +#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) +#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) + +#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) +#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) + +#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) +#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) + +#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) +#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) + +#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) +#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) + +#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) +#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) + +#define andps_m2r(var, reg) sse_m2r(andps, var, reg) +#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) + +#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) +#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) + +#define orps_m2r(var, reg) sse_m2r(orps, var, reg) +#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) + +#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) +#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) + +#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) +#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) + +#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) +#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) + +#define minps_m2r(var, reg) sse_m2r(minps, var, reg) +#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) + +#define minss_m2r(var, reg) sse_m2r(minss, var, reg) +#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) + +#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) +#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) + +#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) +#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) + +#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) +#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) + +#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) +#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) + +#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) +#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) + +#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) +#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) + +#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) +#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) + +#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) +#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) + +#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) +#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) + +#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) +#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) + +#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) +#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) + +#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) +#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) + +#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) +#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) + +#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) +#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) + +#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) +#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) + +#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) +#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) + +#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) +#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) + +#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) +#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) + +#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) +#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) + +#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) +#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) + +#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) +#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) + +#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) +#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) + +#define fxrstor(mem) \ + __asm__ __volatile__ ("fxrstor %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define fxsave(mem) \ + __asm__ __volatile__ ("fxsave %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define stmxcsr(mem) \ + __asm__ __volatile__ ("stmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) + +#define ldmxcsr(mem) \ + __asm__ __volatile__ ("ldmxcsr %0" \ + : /* nothing */ \ + : "X" (mem)) +#endif /*ARCH_X86 */ + +#endif /*XINE_MMX_H*/ diff --git a/src/xine-utils/xine_mutex.c b/src/xine-utils/xine_mutex.c index c94f32be0..e53de574b 100644 --- a/src/xine-utils/xine_mutex.c +++ b/src/xine-utils/xine_mutex.c @@ -1,18 +1,18 @@ -/* +/* * Copyright (C) 2000-2003 the xine project - * + * * This file is part of xine, a free video player. - * + * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * xine is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA @@ -40,7 +40,7 @@ int xine_mutex_init (xine_mutex_t *mutex, const pthread_mutexattr_t *mutexattr, return pthread_mutex_init (&mutex->mutex, mutexattr); } - + int xine_mutex_lock (xine_mutex_t *mutex, const char *who) { #ifndef DBG_MUTEX @@ -50,13 +50,13 @@ int xine_mutex_lock (xine_mutex_t *mutex, const char *who) { #else if (pthread_mutex_trylock (&mutex->mutex)) { - printf ("xine_mutex: BLOCK when %s tried to lock mutex %s because it is locked by %s. continue trying...)\n", + printf ("xine_mutex: BLOCK when %s tried to lock mutex %s because it is locked by %s. continue trying...)\n", who, mutex->id, mutex->locked_by); pthread_mutex_lock (&mutex->mutex); } - printf ("xine_mutex: %s has now locked mutex %s\n", + printf ("xine_mutex: %s has now locked mutex %s\n", who, mutex->id); mutex->locked_by = who; diff --git a/src/xine-utils/xineutils.h b/src/xine-utils/xineutils.h index 120cb3578..0fd0bbf0e 100644 --- a/src/xine-utils/xineutils.h +++ b/src/xine-utils/xineutils.h @@ -24,10 +24,6 @@ extern "C" { #endif -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include <stdlib.h> #include <string.h> #include <stdarg.h> @@ -43,6 +39,7 @@ extern "C" { # include "list.h" # include "array.h" # include "sorted_array.h" +# include "xine_mmx.h" #else # ifdef WIN32 # include <winsock.h> @@ -58,12 +55,13 @@ extern "C" { # include <xine/list.h> # include <xine/array.h> # include <xine/sorted_array.h> +# include <xine/xine_mmx.h> #endif #include <stdio.h> #include <string.h> -/* +/* * Mark exported data symbols for link engine library clients with older * Win32 compilers */ @@ -125,474 +123,8 @@ extern "C" { #define MM_SSE MM_ACCEL_X86_SSE #define MM_SSE2 MM_ACCEL_X86_SSE2 -uint32_t xine_mm_accel (void) XINE_PROTECTED; - -#if defined(ARCH_X86) || defined(ARCH_X86_64) - -typedef union { - int64_t q; /* Quadword (64-bit) value */ - uint64_t uq; /* Unsigned Quadword */ - int d[2]; /* 2 Doubleword (32-bit) values */ - unsigned int ud[2]; /* 2 Unsigned Doubleword */ - short w[4]; /* 4 Word (16-bit) values */ - unsigned short uw[4]; /* 4 Unsigned Word */ - char b[8]; /* 8 Byte (8-bit) values */ - unsigned char ub[8]; /* 8 Unsigned Byte */ - float s[2]; /* Single-precision (32-bit) value */ -} ATTR_ALIGN(8) mmx_t; /* On an 8-byte (64-bit) boundary */ - - - -#define mmx_i2r(op,imm,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "i" (imm) ) - -#define mmx_m2r(op,mem,reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "m" (mem)) - -#define mmx_r2m(op,reg,mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=m" (mem) \ - : /* nothing */ ) - -#define mmx_r2r(op,regs,regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - - -#define emms() __asm__ __volatile__ ("emms") - -#define movd_m2r(var,reg) mmx_m2r (movd, var, reg) -#define movd_r2m(reg,var) mmx_r2m (movd, reg, var) -#define movd_r2r(regs,regd) mmx_r2r (movd, regs, regd) - -#define movq_m2r(var,reg) mmx_m2r (movq, var, reg) -#define movq_r2m(reg,var) mmx_r2m (movq, reg, var) -#define movq_r2r(regs,regd) mmx_r2r (movq, regs, regd) - -#define packssdw_m2r(var,reg) mmx_m2r (packssdw, var, reg) -#define packssdw_r2r(regs,regd) mmx_r2r (packssdw, regs, regd) -#define packsswb_m2r(var,reg) mmx_m2r (packsswb, var, reg) -#define packsswb_r2r(regs,regd) mmx_r2r (packsswb, regs, regd) - -#define packuswb_m2r(var,reg) mmx_m2r (packuswb, var, reg) -#define packuswb_r2r(regs,regd) mmx_r2r (packuswb, regs, regd) - -#define paddb_m2r(var,reg) mmx_m2r (paddb, var, reg) -#define paddb_r2r(regs,regd) mmx_r2r (paddb, regs, regd) -#define paddd_m2r(var,reg) mmx_m2r (paddd, var, reg) -#define paddd_r2r(regs,regd) mmx_r2r (paddd, regs, regd) -#define paddw_m2r(var,reg) mmx_m2r (paddw, var, reg) -#define paddw_r2r(regs,regd) mmx_r2r (paddw, regs, regd) - -#define paddsb_m2r(var,reg) mmx_m2r (paddsb, var, reg) -#define paddsb_r2r(regs,regd) mmx_r2r (paddsb, regs, regd) -#define paddsw_m2r(var,reg) mmx_m2r (paddsw, var, reg) -#define paddsw_r2r(regs,regd) mmx_r2r (paddsw, regs, regd) - -#define paddusb_m2r(var,reg) mmx_m2r (paddusb, var, reg) -#define paddusb_r2r(regs,regd) mmx_r2r (paddusb, regs, regd) -#define paddusw_m2r(var,reg) mmx_m2r (paddusw, var, reg) -#define paddusw_r2r(regs,regd) mmx_r2r (paddusw, regs, regd) - -#define pand_m2r(var,reg) mmx_m2r (pand, var, reg) -#define pand_r2r(regs,regd) mmx_r2r (pand, regs, regd) - -#define pandn_m2r(var,reg) mmx_m2r (pandn, var, reg) -#define pandn_r2r(regs,regd) mmx_r2r (pandn, regs, regd) - -#define pcmpeqb_m2r(var,reg) mmx_m2r (pcmpeqb, var, reg) -#define pcmpeqb_r2r(regs,regd) mmx_r2r (pcmpeqb, regs, regd) -#define pcmpeqd_m2r(var,reg) mmx_m2r (pcmpeqd, var, reg) -#define pcmpeqd_r2r(regs,regd) mmx_r2r (pcmpeqd, regs, regd) -#define pcmpeqw_m2r(var,reg) mmx_m2r (pcmpeqw, var, reg) -#define pcmpeqw_r2r(regs,regd) mmx_r2r (pcmpeqw, regs, regd) - -#define pcmpgtb_m2r(var,reg) mmx_m2r (pcmpgtb, var, reg) -#define pcmpgtb_r2r(regs,regd) mmx_r2r (pcmpgtb, regs, regd) -#define pcmpgtd_m2r(var,reg) mmx_m2r (pcmpgtd, var, reg) -#define pcmpgtd_r2r(regs,regd) mmx_r2r (pcmpgtd, regs, regd) -#define pcmpgtw_m2r(var,reg) mmx_m2r (pcmpgtw, var, reg) -#define pcmpgtw_r2r(regs,regd) mmx_r2r (pcmpgtw, regs, regd) - -#define pmaddwd_m2r(var,reg) mmx_m2r (pmaddwd, var, reg) -#define pmaddwd_r2r(regs,regd) mmx_r2r (pmaddwd, regs, regd) - -#define pmulhw_m2r(var,reg) mmx_m2r (pmulhw, var, reg) -#define pmulhw_r2r(regs,regd) mmx_r2r (pmulhw, regs, regd) - -#define pmullw_m2r(var,reg) mmx_m2r (pmullw, var, reg) -#define pmullw_r2r(regs,regd) mmx_r2r (pmullw, regs, regd) - -#define por_m2r(var,reg) mmx_m2r (por, var, reg) -#define por_r2r(regs,regd) mmx_r2r (por, regs, regd) - -#define pslld_i2r(imm,reg) mmx_i2r (pslld, imm, reg) -#define pslld_m2r(var,reg) mmx_m2r (pslld, var, reg) -#define pslld_r2r(regs,regd) mmx_r2r (pslld, regs, regd) -#define psllq_i2r(imm,reg) mmx_i2r (psllq, imm, reg) -#define psllq_m2r(var,reg) mmx_m2r (psllq, var, reg) -#define psllq_r2r(regs,regd) mmx_r2r (psllq, regs, regd) -#define psllw_i2r(imm,reg) mmx_i2r (psllw, imm, reg) -#define psllw_m2r(var,reg) mmx_m2r (psllw, var, reg) -#define psllw_r2r(regs,regd) mmx_r2r (psllw, regs, regd) - -#define psrad_i2r(imm,reg) mmx_i2r (psrad, imm, reg) -#define psrad_m2r(var,reg) mmx_m2r (psrad, var, reg) -#define psrad_r2r(regs,regd) mmx_r2r (psrad, regs, regd) -#define psraw_i2r(imm,reg) mmx_i2r (psraw, imm, reg) -#define psraw_m2r(var,reg) mmx_m2r (psraw, var, reg) -#define psraw_r2r(regs,regd) mmx_r2r (psraw, regs, regd) - -#define psrld_i2r(imm,reg) mmx_i2r (psrld, imm, reg) -#define psrld_m2r(var,reg) mmx_m2r (psrld, var, reg) -#define psrld_r2r(regs,regd) mmx_r2r (psrld, regs, regd) -#define psrlq_i2r(imm,reg) mmx_i2r (psrlq, imm, reg) -#define psrlq_m2r(var,reg) mmx_m2r (psrlq, var, reg) -#define psrlq_r2r(regs,regd) mmx_r2r (psrlq, regs, regd) -#define psrlw_i2r(imm,reg) mmx_i2r (psrlw, imm, reg) -#define psrlw_m2r(var,reg) mmx_m2r (psrlw, var, reg) -#define psrlw_r2r(regs,regd) mmx_r2r (psrlw, regs, regd) - -#define psubb_m2r(var,reg) mmx_m2r (psubb, var, reg) -#define psubb_r2r(regs,regd) mmx_r2r (psubb, regs, regd) -#define psubd_m2r(var,reg) mmx_m2r (psubd, var, reg) -#define psubd_r2r(regs,regd) mmx_r2r (psubd, regs, regd) -#define psubw_m2r(var,reg) mmx_m2r (psubw, var, reg) -#define psubw_r2r(regs,regd) mmx_r2r (psubw, regs, regd) - -#define psubsb_m2r(var,reg) mmx_m2r (psubsb, var, reg) -#define psubsb_r2r(regs,regd) mmx_r2r (psubsb, regs, regd) -#define psubsw_m2r(var,reg) mmx_m2r (psubsw, var, reg) -#define psubsw_r2r(regs,regd) mmx_r2r (psubsw, regs, regd) - -#define psubusb_m2r(var,reg) mmx_m2r (psubusb, var, reg) -#define psubusb_r2r(regs,regd) mmx_r2r (psubusb, regs, regd) -#define psubusw_m2r(var,reg) mmx_m2r (psubusw, var, reg) -#define psubusw_r2r(regs,regd) mmx_r2r (psubusw, regs, regd) - -#define punpckhbw_m2r(var,reg) mmx_m2r (punpckhbw, var, reg) -#define punpckhbw_r2r(regs,regd) mmx_r2r (punpckhbw, regs, regd) -#define punpckhdq_m2r(var,reg) mmx_m2r (punpckhdq, var, reg) -#define punpckhdq_r2r(regs,regd) mmx_r2r (punpckhdq, regs, regd) -#define punpckhwd_m2r(var,reg) mmx_m2r (punpckhwd, var, reg) -#define punpckhwd_r2r(regs,regd) mmx_r2r (punpckhwd, regs, regd) - -#define punpcklbw_m2r(var,reg) mmx_m2r (punpcklbw, var, reg) -#define punpcklbw_r2r(regs,regd) mmx_r2r (punpcklbw, regs, regd) -#define punpckldq_m2r(var,reg) mmx_m2r (punpckldq, var, reg) -#define punpckldq_r2r(regs,regd) mmx_r2r (punpckldq, regs, regd) -#define punpcklwd_m2r(var,reg) mmx_m2r (punpcklwd, var, reg) -#define punpcklwd_r2r(regs,regd) mmx_r2r (punpcklwd, regs, regd) - -#define pxor_m2r(var,reg) mmx_m2r (pxor, var, reg) -#define pxor_r2r(regs,regd) mmx_r2r (pxor, regs, regd) - - -/* 3DNOW extensions */ - -#define pavgusb_m2r(var,reg) mmx_m2r (pavgusb, var, reg) -#define pavgusb_r2r(regs,regd) mmx_r2r (pavgusb, regs, regd) - - -/* AMD MMX extensions - also available in intel SSE */ - - -#define mmx_m2ri(op,mem,reg,imm) \ - __asm__ __volatile__ (#op " %1, %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem), "X" (imm)) -#define mmx_r2ri(op,regs,regd,imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "X" (imm) ) - -#define mmx_fetch(mem,hint) \ - __asm__ __volatile__ ("prefetch" #hint " %0" \ - : /* nothing */ \ - : "X" (mem)) - - -#define maskmovq(regs,maskreg) mmx_r2ri (maskmovq, regs, maskreg) - -#define movntq_r2m(mmreg,var) mmx_r2m (movntq, mmreg, var) - -#define pavgb_m2r(var,reg) mmx_m2r (pavgb, var, reg) -#define pavgb_r2r(regs,regd) mmx_r2r (pavgb, regs, regd) -#define pavgw_m2r(var,reg) mmx_m2r (pavgw, var, reg) -#define pavgw_r2r(regs,regd) mmx_r2r (pavgw, regs, regd) - -#define pextrw_r2r(mmreg,reg,imm) mmx_r2ri (pextrw, mmreg, reg, imm) - -#define pinsrw_r2r(reg,mmreg,imm) mmx_r2ri (pinsrw, reg, mmreg, imm) - -#define pmaxsw_m2r(var,reg) mmx_m2r (pmaxsw, var, reg) -#define pmaxsw_r2r(regs,regd) mmx_r2r (pmaxsw, regs, regd) - -#define pmaxub_m2r(var,reg) mmx_m2r (pmaxub, var, reg) -#define pmaxub_r2r(regs,regd) mmx_r2r (pmaxub, regs, regd) - -#define pminsw_m2r(var,reg) mmx_m2r (pminsw, var, reg) -#define pminsw_r2r(regs,regd) mmx_r2r (pminsw, regs, regd) - -#define pminub_m2r(var,reg) mmx_m2r (pminub, var, reg) -#define pminub_r2r(regs,regd) mmx_r2r (pminub, regs, regd) - -#define pmovmskb(mmreg,reg) \ - __asm__ __volatile__ ("movmskps %" #mmreg ", %" #reg) - -#define pmulhuw_m2r(var,reg) mmx_m2r (pmulhuw, var, reg) -#define pmulhuw_r2r(regs,regd) mmx_r2r (pmulhuw, regs, regd) - -#define prefetcht0(mem) mmx_fetch (mem, t0) -#define prefetcht1(mem) mmx_fetch (mem, t1) -#define prefetcht2(mem) mmx_fetch (mem, t2) -#define prefetchnta(mem) mmx_fetch (mem, nta) - -#define psadbw_m2r(var,reg) mmx_m2r (psadbw, var, reg) -#define psadbw_r2r(regs,regd) mmx_r2r (psadbw, regs, regd) - -#define pshufw_m2r(var,reg,imm) mmx_m2ri(pshufw, var, reg, imm) -#define pshufw_r2r(regs,regd,imm) mmx_r2ri(pshufw, regs, regd, imm) - -#define sfence() __asm__ __volatile__ ("sfence\n\t") - -typedef union { - float sf[4]; /* Single-precision (32-bit) value */ -} ATTR_ALIGN(16) sse_t; /* On a 16 byte (128-bit) boundary */ - - -#define sse_i2r(op, imm, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2r(op, mem, reg) \ - __asm__ __volatile__ (#op " %0, %%" #reg \ - : /* nothing */ \ - : "X" (mem)) - -#define sse_r2m(op, reg, mem) \ - __asm__ __volatile__ (#op " %%" #reg ", %0" \ - : "=X" (mem) \ - : /* nothing */ ) - -#define sse_r2r(op, regs, regd) \ - __asm__ __volatile__ (#op " %" #regs ", %" #regd) - -#define sse_r2ri(op, regs, regd, imm) \ - __asm__ __volatile__ (#op " %0, %%" #regs ", %%" #regd \ - : /* nothing */ \ - : "X" (imm) ) - -#define sse_m2ri(op, mem, reg, subop) \ - __asm__ __volatile__ (#op " %0, %%" #reg ", " #subop \ - : /* nothing */ \ - : "X" (mem)) - - -#define movaps_m2r(var, reg) sse_m2r(movaps, var, reg) -#define movaps_r2m(reg, var) sse_r2m(movaps, reg, var) -#define movaps_r2r(regs, regd) sse_r2r(movaps, regs, regd) - -#define movntps_r2m(xmmreg, var) sse_r2m(movntps, xmmreg, var) - -#define movups_m2r(var, reg) sse_m2r(movups, var, reg) -#define movups_r2m(reg, var) sse_r2m(movups, reg, var) -#define movups_r2r(regs, regd) sse_r2r(movups, regs, regd) - -#define movhlps_r2r(regs, regd) sse_r2r(movhlps, regs, regd) - -#define movlhps_r2r(regs, regd) sse_r2r(movlhps, regs, regd) - -#define movhps_m2r(var, reg) sse_m2r(movhps, var, reg) -#define movhps_r2m(reg, var) sse_r2m(movhps, reg, var) - -#define movlps_m2r(var, reg) sse_m2r(movlps, var, reg) -#define movlps_r2m(reg, var) sse_r2m(movlps, reg, var) - -#define movss_m2r(var, reg) sse_m2r(movss, var, reg) -#define movss_r2m(reg, var) sse_r2m(movss, reg, var) -#define movss_r2r(regs, regd) sse_r2r(movss, regs, regd) - -#define shufps_m2r(var, reg, index) sse_m2ri(shufps, var, reg, index) -#define shufps_r2r(regs, regd, index) sse_r2ri(shufps, regs, regd, index) - -#define cvtpi2ps_m2r(var, xmmreg) sse_m2r(cvtpi2ps, var, xmmreg) -#define cvtpi2ps_r2r(mmreg, xmmreg) sse_r2r(cvtpi2ps, mmreg, xmmreg) - -#define cvtps2pi_m2r(var, mmreg) sse_m2r(cvtps2pi, var, mmreg) -#define cvtps2pi_r2r(xmmreg, mmreg) sse_r2r(cvtps2pi, mmreg, xmmreg) - -#define cvttps2pi_m2r(var, mmreg) sse_m2r(cvttps2pi, var, mmreg) -#define cvttps2pi_r2r(xmmreg, mmreg) sse_r2r(cvttps2pi, mmreg, xmmreg) +uint32_t xine_mm_accel (void) XINE_CONST XINE_PROTECTED; -#define cvtsi2ss_m2r(var, xmmreg) sse_m2r(cvtsi2ss, var, xmmreg) -#define cvtsi2ss_r2r(reg, xmmreg) sse_r2r(cvtsi2ss, reg, xmmreg) - -#define cvtss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvtss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - -#define cvttss2si_m2r(var, reg) sse_m2r(cvtss2si, var, reg) -#define cvttss2si_r2r(xmmreg, reg) sse_r2r(cvtss2si, xmmreg, reg) - -#define movmskps(xmmreg, reg) \ - __asm__ __volatile__ ("movmskps %" #xmmreg ", %" #reg) - -#define addps_m2r(var, reg) sse_m2r(addps, var, reg) -#define addps_r2r(regs, regd) sse_r2r(addps, regs, regd) - -#define addss_m2r(var, reg) sse_m2r(addss, var, reg) -#define addss_r2r(regs, regd) sse_r2r(addss, regs, regd) - -#define subps_m2r(var, reg) sse_m2r(subps, var, reg) -#define subps_r2r(regs, regd) sse_r2r(subps, regs, regd) - -#define subss_m2r(var, reg) sse_m2r(subss, var, reg) -#define subss_r2r(regs, regd) sse_r2r(subss, regs, regd) - -#define mulps_m2r(var, reg) sse_m2r(mulps, var, reg) -#define mulps_r2r(regs, regd) sse_r2r(mulps, regs, regd) - -#define mulss_m2r(var, reg) sse_m2r(mulss, var, reg) -#define mulss_r2r(regs, regd) sse_r2r(mulss, regs, regd) - -#define divps_m2r(var, reg) sse_m2r(divps, var, reg) -#define divps_r2r(regs, regd) sse_r2r(divps, regs, regd) - -#define divss_m2r(var, reg) sse_m2r(divss, var, reg) -#define divss_r2r(regs, regd) sse_r2r(divss, regs, regd) - -#define rcpps_m2r(var, reg) sse_m2r(rcpps, var, reg) -#define rcpps_r2r(regs, regd) sse_r2r(rcpps, regs, regd) - -#define rcpss_m2r(var, reg) sse_m2r(rcpss, var, reg) -#define rcpss_r2r(regs, regd) sse_r2r(rcpss, regs, regd) - -#define rsqrtps_m2r(var, reg) sse_m2r(rsqrtps, var, reg) -#define rsqrtps_r2r(regs, regd) sse_r2r(rsqrtps, regs, regd) - -#define rsqrtss_m2r(var, reg) sse_m2r(rsqrtss, var, reg) -#define rsqrtss_r2r(regs, regd) sse_r2r(rsqrtss, regs, regd) - -#define sqrtps_m2r(var, reg) sse_m2r(sqrtps, var, reg) -#define sqrtps_r2r(regs, regd) sse_r2r(sqrtps, regs, regd) - -#define sqrtss_m2r(var, reg) sse_m2r(sqrtss, var, reg) -#define sqrtss_r2r(regs, regd) sse_r2r(sqrtss, regs, regd) - -#define andps_m2r(var, reg) sse_m2r(andps, var, reg) -#define andps_r2r(regs, regd) sse_r2r(andps, regs, regd) - -#define andnps_m2r(var, reg) sse_m2r(andnps, var, reg) -#define andnps_r2r(regs, regd) sse_r2r(andnps, regs, regd) - -#define orps_m2r(var, reg) sse_m2r(orps, var, reg) -#define orps_r2r(regs, regd) sse_r2r(orps, regs, regd) - -#define xorps_m2r(var, reg) sse_m2r(xorps, var, reg) -#define xorps_r2r(regs, regd) sse_r2r(xorps, regs, regd) - -#define maxps_m2r(var, reg) sse_m2r(maxps, var, reg) -#define maxps_r2r(regs, regd) sse_r2r(maxps, regs, regd) - -#define maxss_m2r(var, reg) sse_m2r(maxss, var, reg) -#define maxss_r2r(regs, regd) sse_r2r(maxss, regs, regd) - -#define minps_m2r(var, reg) sse_m2r(minps, var, reg) -#define minps_r2r(regs, regd) sse_r2r(minps, regs, regd) - -#define minss_m2r(var, reg) sse_m2r(minss, var, reg) -#define minss_r2r(regs, regd) sse_r2r(minss, regs, regd) - -#define cmpps_m2r(var, reg, op) sse_m2ri(cmpps, var, reg, op) -#define cmpps_r2r(regs, regd, op) sse_r2ri(cmpps, regs, regd, op) - -#define cmpeqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 0) -#define cmpeqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 0) - -#define cmpltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 1) -#define cmpltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 1) - -#define cmpleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 2) -#define cmpleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 2) - -#define cmpunordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 3) -#define cmpunordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 3) - -#define cmpneqps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 4) -#define cmpneqps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 4) - -#define cmpnltps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 5) -#define cmpnltps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 5) - -#define cmpnleps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 6) -#define cmpnleps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 6) - -#define cmpordps_m2r(var, reg) sse_m2ri(cmpps, var, reg, 7) -#define cmpordps_r2r(regs, regd) sse_r2ri(cmpps, regs, regd, 7) - -#define cmpss_m2r(var, reg, op) sse_m2ri(cmpss, var, reg, op) -#define cmpss_r2r(regs, regd, op) sse_r2ri(cmpss, regs, regd, op) - -#define cmpeqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 0) -#define cmpeqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 0) - -#define cmpltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 1) -#define cmpltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 1) - -#define cmpless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 2) -#define cmpless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 2) - -#define cmpunordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 3) -#define cmpunordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 3) - -#define cmpneqss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 4) -#define cmpneqss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 4) - -#define cmpnltss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 5) -#define cmpnltss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 5) - -#define cmpnless_m2r(var, reg) sse_m2ri(cmpss, var, reg, 6) -#define cmpnless_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 6) - -#define cmpordss_m2r(var, reg) sse_m2ri(cmpss, var, reg, 7) -#define cmpordss_r2r(regs, regd) sse_r2ri(cmpss, regs, regd, 7) - -#define comiss_m2r(var, reg) sse_m2r(comiss, var, reg) -#define comiss_r2r(regs, regd) sse_r2r(comiss, regs, regd) - -#define ucomiss_m2r(var, reg) sse_m2r(ucomiss, var, reg) -#define ucomiss_r2r(regs, regd) sse_r2r(ucomiss, regs, regd) - -#define unpcklps_m2r(var, reg) sse_m2r(unpcklps, var, reg) -#define unpcklps_r2r(regs, regd) sse_r2r(unpcklps, regs, regd) - -#define unpckhps_m2r(var, reg) sse_m2r(unpckhps, var, reg) -#define unpckhps_r2r(regs, regd) sse_r2r(unpckhps, regs, regd) - -#define fxrstor(mem) \ - __asm__ __volatile__ ("fxrstor %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define fxsave(mem) \ - __asm__ __volatile__ ("fxsave %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define stmxcsr(mem) \ - __asm__ __volatile__ ("stmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) - -#define ldmxcsr(mem) \ - __asm__ __volatile__ ("ldmxcsr %0" \ - : /* nothing */ \ - : "X" (mem)) -#endif /*ARCH_X86 */ /* Optimized/fast memcpy */ @@ -621,11 +153,7 @@ void xine_profiler_print_results (void) XINE_PROTECTED; * Allocate and clean memory size_t 'size', then return the pointer * to the allocated memory. */ -#if !defined(__GNUC__) || __GNUC__ < 3 -void *xine_xmalloc(size_t size) XINE_PROTECTED; -#else -void *xine_xmalloc(size_t size) __attribute__ ((__malloc__)) XINE_PROTECTED; -#endif +void *xine_xmalloc(size_t size) XINE_MALLOC XINE_DEPRECATED XINE_PROTECTED; /* * Same as above, but memory is aligned to 'alignement'. @@ -643,6 +171,7 @@ const char *xine_get_homedir(void) XINE_PROTECTED; /* * Get other xine directories. */ +const char *xine_get_pluginroot(void) XINE_PROTECTED; const char *xine_get_plugindir(void) XINE_PROTECTED; const char *xine_get_fontdir(void) XINE_PROTECTED; const char *xine_get_localedir(void) XINE_PROTECTED; @@ -665,7 +194,7 @@ void xine_usec_sleep(unsigned usec) XINE_PROTECTED; */ -void xine_strdupa(char *dest, char *src) XINE_PROTECTED; +void xine_strdupa(char *dest, char *src) XINE_PROTECTED XINE_DEPRECATED; #define xine_strdupa(d, s) do { \ (d) = NULL; \ if((s) != NULL) { \ @@ -679,6 +208,13 @@ void xine_strdupa(char *dest, char *src) XINE_PROTECTED; #define xine_strsep(STRINGP, DELIM) strsep((STRINGP), (DELIM)) #define xine_setenv(NAME, VAL, XX) setenv((NAME), (VAL), (XX)) +/** + * append to a string, reallocating + * normally, updates & returns *dest + * on error, *dest is unchanged & NULL is returned. + */ +char *xine_strcat_realloc (char **dest, char *append) XINE_PROTECTED; + /* * Color Conversion Utility Functions * The following data structures and functions facilitate the conversion @@ -959,7 +495,7 @@ void xine_xprintf(xine_t *xine, int verbose, const char *fmt, ...); /** * get encoding of current locale */ -char *xine_get_system_encoding(void) XINE_PROTECTED; +char *xine_get_system_encoding(void) XINE_MALLOC XINE_PROTECTED; /* * guess default encoding for the subtitles diff --git a/src/xine-utils/xmllexer.c b/src/xine-utils/xmllexer.c index be3bdd248..fb504f430 100644 --- a/src/xine-utils/xmllexer.c +++ b/src/xine-utils/xmllexer.c @@ -25,11 +25,14 @@ #define LOG */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #ifdef XINE_COMPILE #include "xineutils.h" #else #define lprintf(...) -#define xine_xmalloc malloc #endif #include "xmllexer.h" #include <stdio.h> @@ -47,16 +50,11 @@ #define DATA 1 /* data lex mode */ /* private global variables */ -static const char * lexbuf; -static int lexbuf_size = 0; -static int lexbuf_pos = 0; -static int lex_mode = NORMAL; -static int in_comment = 0; -static char *lex_malloc = NULL; +struct lexer * static_lexer; enum utf { UTF32BE, UTF32LE, UTF16BE, UTF16LE }; -static void lex_convert (const char * buf, int size, enum utf utf) +static void lex_convert (struct lexer * lexer, const char * buf, int size, enum utf utf) { char *utf8 = malloc (size * (utf >= UTF16BE ? 3 : 6) + 1); char *bp = utf8; @@ -88,42 +86,60 @@ static void lex_convert (const char * buf, int size, enum utf utf) } } *bp = 0; - lexbuf_size = bp - utf8; - lexbuf = lex_malloc = realloc (utf8, lexbuf_size + 1); + lexer->lexbuf_size = bp - utf8; + lexer->lexbuf = lexer->lex_malloc = realloc (utf8, lexer->lexbuf_size + 1); } +/* for ABI compatibility */ void lexer_init(const char * buf, int size) { + if (static_lexer) { + lexer_finalize_r(static_lexer); + } + static_lexer = lexer_init_r(buf, size); +} + +struct lexer *lexer_init_r(const char * buf, int size) { static const char boms[] = { 0xFF, 0xFE, 0, 0, 0xFE, 0xFF }, bom_utf8[] = { 0xEF, 0xBB, 0xBF }; + struct lexer * lexer = calloc (1, sizeof (*lexer)); - free (lex_malloc); - lex_malloc = NULL; - - lexbuf = buf; - lexbuf_size = size; + lexer->lexbuf = buf; + lexer->lexbuf_size = size; if (size >= 4 && !memcmp (buf, boms + 2, 4)) - lex_convert (buf + 4, size - 4, UTF32BE); + lex_convert (lexer, buf + 4, size - 4, UTF32BE); else if (size >= 4 && !memcmp (buf, boms, 4)) - lex_convert (buf + 4, size - 4, UTF32LE); + lex_convert (lexer, buf + 4, size - 4, UTF32LE); else if (size >= 3 && !memcmp (buf, bom_utf8, 3)) { - lexbuf += 3; - lexbuf_size -= 3; + lexer->lexbuf += 3; + lexer->lexbuf_size -= 3; } else if (size >= 2 && !memcmp (buf, boms + 4, 2)) - lex_convert (buf + 2, size - 2, UTF16BE); + lex_convert (lexer, buf + 2, size - 2, UTF16BE); else if (size >= 2 && !memcmp (buf, boms, 2)) - lex_convert (buf + 2, size - 2, UTF16LE); + lex_convert (lexer, buf + 2, size - 2, UTF16LE); - lexbuf_pos = 0; - lex_mode = NORMAL; - in_comment = 0; + lexer->lexbuf_pos = 0; + lexer->lex_mode = NORMAL; + lexer->in_comment = 0; lprintf("buffer length %d\n", size); + return lexer; } +void lexer_finalize_r(struct lexer * lexer) +{ + free(lexer->lex_malloc); + free(lexer); +} + +/* for ABI compatibility */ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { + return lexer_get_token_d_r(static_lexer, _tok, _tok_size, fixed); +} + +int lexer_get_token_d_r(struct lexer * lexer, char ** _tok, int * _tok_size, int fixed) { char *tok = *_tok; int tok_size = *_tok_size; @@ -132,11 +148,11 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { char c; if (tok) { - while ((tok_pos < tok_size) && (lexbuf_pos < lexbuf_size)) { - c = lexbuf[lexbuf_pos]; - lprintf("c=%c, state=%d, in_comment=%d\n", c, state, in_comment); + while ((tok_pos < tok_size) && (lexer->lexbuf_pos < lexer->lexbuf_size)) { + c = lexer->lexbuf[lexer->lexbuf_pos]; + lprintf("c=%c, state=%d, in_comment=%d\n", c, state, lexer->in_comment); - if (lex_mode == NORMAL) { + if (lexer->lex_mode == NORMAL) { /* normal mode */ switch (state) { /* init state */ @@ -169,7 +185,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { break; case '/': - if (!in_comment) + if (!lexer->in_comment) state = 5; tok[tok_pos] = c; tok_pos++; @@ -207,14 +223,14 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { tok_pos++; break; } - lexbuf_pos++; + lexer->lexbuf_pos++; break; /* end of line */ case 1: if (c == '\n' || (c == '\r')) { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; } else { tok[tok_pos] = '\0'; @@ -226,7 +242,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 2: if (c == ' ' || (c == '\t')) { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; } else { tok[tok_pos] = '\0'; @@ -239,20 +255,20 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { switch (c) { case '/': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_M_START_2; break; case '!': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; state = 8; break; case '?': tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_TI_START; @@ -266,8 +282,8 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { /* T_M_STOP_1 */ case 4: tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_M_STOP_1; break; @@ -275,11 +291,11 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 5: if (c == '>') { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; - if (!in_comment) - lex_mode = DATA; + if (!lexer->in_comment) + lexer->lex_mode = DATA; return T_M_STOP_2; } else { tok[tok_pos] = '\0'; @@ -296,7 +312,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { /* T_STRING */ case 7: tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; if (c == '\"') { /* " */ tok[tok_pos] = '\0'; /* FIXME */ return T_STRING; @@ -308,22 +324,22 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 8: switch (c) { case '-': - lexbuf_pos++; - if (lexbuf[lexbuf_pos] == '-') + lexer->lexbuf_pos++; + if (lexer->lexbuf[lexer->lexbuf_pos] == '-') { - lexbuf_pos++; + lexer->lexbuf_pos++; tok[tok_pos++] = '-'; /* FIXME */ tok[tok_pos++] = '-'; tok[tok_pos] = '\0'; - in_comment = 1; + lexer->in_comment = 1; return T_C_START; } break; case 'D': - lexbuf_pos++; - if (strncmp(lexbuf + lexbuf_pos, "OCTYPE", 6) == 0) { + lexer->lexbuf_pos++; + if (strncmp(lexer->lexbuf + lexer->lexbuf_pos, "OCTYPE", 6) == 0) { strncpy(tok + tok_pos, "DOCTYPE", 7); /* FIXME */ - lexbuf_pos += 6; + lexer->lexbuf_pos += 6; return T_DOCTYPE_START; } else { return T_ERROR; @@ -339,7 +355,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case 9: if (c == '>') { tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; tok_pos++; /* FIXME */ tok[tok_pos] = '\0'; return T_TI_STOP; @@ -355,13 +371,13 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '-': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 11; break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 100; } break; @@ -372,21 +388,21 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '>': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; tok[tok_pos] = '\0'; /* FIX ME */ if (strlen(tok) != 3) { tok[tok_pos - 3] = '\0'; - lexbuf_pos -= 3; + lexer->lexbuf_pos -= 3; return T_IDENT; } else { - in_comment = 0; + lexer->in_comment = 0; return T_C_STOP; } break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 100; } break; @@ -394,7 +410,7 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { /* T_STRING (single quotes) */ case 12: tok[tok_pos] = c; - lexbuf_pos++; + lexer->lexbuf_pos++; if (c == '\'') { /* " */ tok[tok_pos] = '\0'; /* FIXME */ return T_STRING; @@ -411,6 +427,8 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '\"': /* " */ case ' ': case '\t': + case '\n': + case '\r': case '=': case '/': tok[tok_pos] = '\0'; @@ -419,19 +437,19 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { case '?': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 9; break; case '-': tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; state = 10; break; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } break; default: @@ -444,17 +462,17 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { { case '<': tok[tok_pos] = '\0'; - lex_mode = NORMAL; + lexer->lex_mode = NORMAL; return T_DATA; default: tok[tok_pos] = c; tok_pos++; - lexbuf_pos++; + lexer->lexbuf_pos++; } } } - lprintf ("loop done tok_pos = %d, tok_size=%d, lexbuf_pos=%d, lexbuf_size=%d\n", - tok_pos, tok_size, lexbuf_pos, lexbuf_size); + lprintf ("loop done tok_pos = %d, tok_size=%d, lexbuf_pos=%d, lexbuf_size=%d\n", + tok_pos, tok_size, lexer->lexbuf_pos, lexer->lexbuf_size); /* pb */ if (tok_pos >= tok_size) { @@ -465,12 +483,12 @@ int lexer_get_token_d(char ** _tok, int * _tok_size, int fixed) { lprintf("token buffer is too small\n"); lprintf("increasing buffer size to %d bytes\n", *_tok_size); if (*_tok) { - return lexer_get_token_d (_tok, _tok_size, 0); + return lexer_get_token_d_r (lexer, _tok, _tok_size, 0); } else { return T_ERROR; } } else { - if (lexbuf_pos >= lexbuf_size) { + if (lexer->lexbuf_pos >= lexer->lexbuf_size) { /* Terminate the current token */ tok[tok_pos] = '\0'; switch (state) { @@ -532,7 +550,7 @@ static struct { char *lexer_decode_entities (const char *tok) { - char *buf = xine_xmalloc (strlen (tok) + 1); + char *buf = calloc (strlen (tok) + 1, sizeof(char)); char *bp = buf; char c; diff --git a/src/xine-utils/xmllexer.h b/src/xine-utils/xmllexer.h index 425d0e70a..bcea7d6b4 100644 --- a/src/xine-utils/xmllexer.h +++ b/src/xine-utils/xmllexer.h @@ -23,6 +23,10 @@ #ifndef XML_LEXER_H #define XML_LEXER_H +#ifndef XINE_DEPRECATED +#define XINE_DEPRECATED +#endif + #ifndef XINE_PROTECTED #define XINE_PROTECTED #endif @@ -49,10 +53,25 @@ #define T_DOCTYPE_STOP 17 /* > */ +/* public structure */ +struct lexer +{ + const char * lexbuf; + int lexbuf_size; + int lexbuf_pos; + int lex_mode; + int in_comment; + char *lex_malloc; +}; + + /* public functions */ -void lexer_init(const char * buf, int size) XINE_PROTECTED; -int lexer_get_token_d(char ** tok, int * tok_size, int fixed) XINE_PROTECTED; -int lexer_get_token(char * tok, int tok_size) XINE_PROTECTED; +void lexer_init(const char * buf, int size) XINE_DEPRECATED XINE_PROTECTED; +struct lexer *lexer_init_r(const char * buf, int size) XINE_PROTECTED; +void lexer_finalize_r(struct lexer * lexer) XINE_PROTECTED; +int lexer_get_token_d_r(struct lexer * lexer, char ** tok, int * tok_size, int fixed) XINE_PROTECTED; +int lexer_get_token_d(char ** tok, int * tok_size, int fixed) XINE_DEPRECATED XINE_PROTECTED; +int lexer_get_token(char * tok, int tok_size) XINE_DEPRECATED XINE_PROTECTED; char *lexer_decode_entities (const char *tok) XINE_PROTECTED; #endif diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c index 14ce35c54..add985512 100644 --- a/src/xine-utils/xmlparser.c +++ b/src/xine-utils/xmlparser.c @@ -19,6 +19,10 @@ * Floor, Boston, MA 02110, USA */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <unistd.h> #include <stdio.h> #include <stdlib.h> @@ -36,7 +40,7 @@ #include "xineutils.h" #else #define lprintf(...) -#define xine_xmalloc malloc +#define XINE_MALLOC #endif #include "xmllexer.h" #include "xmlparser.h" @@ -47,7 +51,7 @@ #define MAX_RECURSION 10 /* private global variables */ -static int xml_parser_mode; +xml_parser_t * static_xml_parser; /* private functions */ @@ -79,7 +83,7 @@ static void free_xml_node(xml_node_t * node) { free(node); } -static xml_property_t * new_xml_property(void) { +static xml_property_t *XINE_MALLOC new_xml_property(void) { xml_property_t * new_property; new_property = (xml_property_t*) malloc(sizeof(xml_property_t)); @@ -95,10 +99,24 @@ static void free_xml_property(xml_property_t * property) { free(property); } +/* for ABI compatibility */ void xml_parser_init(const char * buf, int size, int mode) { + if (static_xml_parser) { + xml_parser_finalize_r(static_xml_parser); + } + static_xml_parser = xml_parser_init_r(buf, size, mode); +} - lexer_init(buf, size); - xml_parser_mode = mode; +xml_parser_t *xml_parser_init_r(const char * buf, int size, int mode) { + xml_parser_t *xml_parser = malloc(sizeof(*xml_parser)); + xml_parser->lexer = lexer_init_r(buf, size); + xml_parser->mode = mode; + return xml_parser; +} + +void xml_parser_finalize_r(xml_parser_t *xml_parser) { + lexer_finalize_r(xml_parser->lexer); + free(xml_parser); } static void xml_parser_free_props(xml_property_t *current_property) { @@ -153,9 +171,9 @@ void xml_parser_free_tree(xml_node_t *current_node) { #define STATE_NODE 1 #define STATE_COMMENT 7 -static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int rec); +static int xml_parser_get_node (xml_parser_t *xml_parser, xml_node_t *current_node, char *root_name, int rec); -static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, +static int _xml_parser_get_node (xml_parser_t *xml_parser, char ** token_buffer, int * token_buffer_size, char ** pname_buffer, int * pname_buffer_size, char ** nname_buffer, int * nname_buffer_size, xml_node_t *current_node, char *root_name, int rec) { @@ -175,7 +193,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, memset (tok, 0, *token_buffer_size); - while ((bypass_get_token) || (res = lexer_get_token_d(token_buffer, token_buffer_size, 0)) != T_ERROR) { + while ((bypass_get_token) || (res = lexer_get_token_d_r(xml_parser->lexer, token_buffer, token_buffer_size, 0)) != T_ERROR) { tok = *token_buffer; bypass_get_token = 0; lprintf("info: %d - %d : '%s'\n", state, res, tok); @@ -228,7 +246,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, current_property = NULL; /* save node name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } /* make sure the buffer for the node name is big enough */ @@ -263,7 +281,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, /* set node propertys */ subtree->props = properties; lprintf("info: rec %d new subtree %s\n", rec, node_name); - parse_res = xml_parser_get_node(subtree, node_name, rec + 1); + parse_res = xml_parser_get_node(xml_parser, subtree, node_name, rec + 1); if (parse_res != 0) { return parse_res; } @@ -294,13 +312,13 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, current_subtree = subtree; } else { current_subtree->next = subtree; - current_subtree = subtree; + current_subtree = subtree; } state = STATE_IDLE; break; case (T_IDENT): /* save property name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } /* make sure the buffer for the property name is big enough */ @@ -324,7 +342,7 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, switch (res) { case (T_IDENT): /* must be equal to root_name */ - if (xml_parser_mode == XML_PARSER_CASE_INSENSITIVE) { + if (xml_parser->mode == XML_PARSER_CASE_INSENSITIVE) { strtoupper(tok); } if (strcmp(tok, root_name) == 0) { @@ -470,17 +488,17 @@ static int _xml_parser_get_node (char ** token_buffer, int * token_buffer_size, } } -static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int rec) +static int xml_parser_get_node (xml_parser_t *xml_parser, xml_node_t *current_node, char *root_name, int rec) { int res = 0; int token_buffer_size = TOKEN_SIZE; int pname_buffer_size = TOKEN_SIZE; int nname_buffer_size = TOKEN_SIZE; - char *token_buffer = xine_xmalloc (token_buffer_size); - char *pname_buffer = xine_xmalloc (pname_buffer_size); - char *nname_buffer = xine_xmalloc (nname_buffer_size); + char *token_buffer = calloc(1, token_buffer_size); + char *pname_buffer = calloc(1, pname_buffer_size); + char *nname_buffer = calloc(1, nname_buffer_size); - res = _xml_parser_get_node(&token_buffer, &token_buffer_size, + res = _xml_parser_get_node(xml_parser, &token_buffer, &token_buffer_size, &pname_buffer, &pname_buffer_size, &nname_buffer, &nname_buffer_size, current_node, root_name, rec); @@ -492,12 +510,17 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r return res; } +/* for ABI compatibility */ int xml_parser_build_tree(xml_node_t **root_node) { + return xml_parser_build_tree_r(static_xml_parser, root_node); +} + +int xml_parser_build_tree_r(xml_parser_t *xml_parser, xml_node_t **root_node) { xml_node_t *tmp_node; int res; tmp_node = new_xml_node(); - res = xml_parser_get_node(tmp_node, "", 0); + res = xml_parser_get_node(xml_parser, tmp_node, "", 0); if ((tmp_node->child) && (!tmp_node->child->next)) { *root_node = tmp_node->child; free_xml_node(tmp_node); @@ -530,7 +553,7 @@ const char *xml_parser_get_property (const xml_node_t *node, const char *name) { return NULL; } -int xml_parser_get_property_int (const xml_node_t *node, const char *name, +int xml_parser_get_property_int (const xml_node_t *node, const char *name, int def_value) { const char *v; @@ -547,7 +570,7 @@ int xml_parser_get_property_int (const xml_node_t *node, const char *name, return ret; } -int xml_parser_get_property_bool (const xml_node_t *node, const char *name, +int xml_parser_get_property_bool (const xml_node_t *node, const char *name, int def_value) { const char *v; @@ -590,7 +613,7 @@ static int xml_escape_string_internal (char *buf, const char *s, char *xml_escape_string (const char *s, xml_escape_quote_t quote_type) { - char *buf = xine_xmalloc (xml_escape_string_internal (NULL, s, quote_type)); + char *buf = calloc (1, xml_escape_string_internal (NULL, s, quote_type)); return buf ? (xml_escape_string_internal (buf, s, quote_type), buf) : NULL; } @@ -598,11 +621,10 @@ static void xml_parser_dump_node (const xml_node_t *node, int indent) { xml_property_t *p; xml_node_t *n; - int l; printf ("%*s<%s ", indent, "", node->name); - l = strlen (node->name); + size_t l = strlen (node->name); p = node->props; while (p) { diff --git a/src/xine-utils/xmlparser.h b/src/xine-utils/xmlparser.h index 98695a756..832925bd0 100644 --- a/src/xine-utils/xmlparser.h +++ b/src/xine-utils/xmlparser.h @@ -22,6 +22,10 @@ #ifndef XML_PARSER_H #define XML_PARSER_H +#ifndef XINE_DEPRECATED +#define XINE_DEPRECATED +#endif + #ifndef XINE_PROTECTED #define XINE_PROTECTED #endif @@ -51,16 +55,25 @@ typedef struct xml_node_s { struct xml_node_s *next; } xml_node_t; -void xml_parser_init(const char * buf, int size, int mode) XINE_PROTECTED; +/* xml parser */ +typedef struct xml_parser_s { + struct lexer *lexer; + int mode; +} xml_parser_t; + +void xml_parser_init(const char * buf, int size, int mode) XINE_DEPRECATED XINE_PROTECTED; +xml_parser_t *xml_parser_init_r(const char * buf, int size, int mode) XINE_PROTECTED; +void xml_parser_finalize_r(xml_parser_t *xml_parser) XINE_PROTECTED; -int xml_parser_build_tree(xml_node_t **root_node) XINE_PROTECTED; +int xml_parser_build_tree(xml_node_t **root_node) XINE_DEPRECATED XINE_PROTECTED; +int xml_parser_build_tree_r(xml_parser_t *xml_parser, xml_node_t **root_node) XINE_PROTECTED; void xml_parser_free_tree(xml_node_t *root_node) XINE_PROTECTED; const char *xml_parser_get_property (const xml_node_t *node, const char *name) XINE_PROTECTED; -int xml_parser_get_property_int (const xml_node_t *node, const char *name, +int xml_parser_get_property_int (const xml_node_t *node, const char *name, int def_value) XINE_PROTECTED; -int xml_parser_get_property_bool (const xml_node_t *node, const char *name, +int xml_parser_get_property_bool (const xml_node_t *node, const char *name, int def_value) XINE_PROTECTED; /* for output: |