diff options
Diffstat (limited to 'src')
36 files changed, 976 insertions, 913 deletions
diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c index 7f3dadeb7..279da6336 100644 --- a/src/demuxers/demux_ac3.c +++ b/src/demuxers/demux_ac3.c @@ -135,10 +135,10 @@ static int open_ac3_file(demux_ac3_t *this) { uint8_t *peak; blocksize = this->input->get_blocksize(this->input); - if (blocksize) { + if (blocksize && INPUT_IS_SEEKABLE(this->input)) { this->input->seek(this->input, 0, SEEK_SET); buf_element_t *buf = this->input->read_block(this->input, - this->audio_fifo, + this->stream->audio_fifo, blocksize); this->input->seek(this->input, 0, SEEK_SET); diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c index 7baeae377..a9541b6f7 100644 --- a/src/demuxers/demux_dts.c +++ b/src/demuxers/demux_dts.c @@ -85,10 +85,10 @@ static int open_dts_file(demux_dts_t *this) { lprintf("open_dts_file\n"); blocksize = this->input->get_blocksize(this->input); - if (blocksize) { - this->input->seek(this->input, 0, SEEK_SET); + if (blocksize && INPUT_IS_SEEKABLE(this->input)) { + // this->input->seek(this->input, 0, SEEK_SET); buf_element_t *buf = this->input->read_block(this->input, - this->audio_fifo, + this->stream->audio_fifo, blocksize); this->input->seek(this->input, 0, SEEK_SET); diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c index c5769e3e3..fbfde4e60 100644 --- a/src/demuxers/demux_mpeg_pes.c +++ b/src/demuxers/demux_mpeg_pes.c @@ -1135,17 +1135,20 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen */ if (this->mpeg12_h264_detected & 1) { buf_type = BUF_VIDEO_H264; - int nal_type_code = -1; - if (payload_size >= 4 && p[2] == 0x01 && p[1] == 0x00 && p[0] == 0x00) - 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; - this->video_fifo->put (this->video_fifo, b); + /* omit sending BUF_FLAG_FRAME_END for the first AUD occurence */ + 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; + 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; + this->video_fifo->put (this->video_fifo, b); + } } } diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index f837a2272..0624dc673 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -918,9 +918,15 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->edit_list_table[j].media_time); } - } else if (current_atom == MDHD_ATOM) - trak->timescale = BE_32(&trak_atom[i + 0x10]); - else if (current_atom == STSD_ATOM) { + } 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 */ + + trak->timescale = BE_32(&trak_atom[i + (version == 0 ? 0x10 : 0x18) ]); + } else if (current_atom == STSD_ATOM) { debug_atom_load ("demux_qt: stsd atom\n"); #if DEBUG_ATOM_LOAD diff --git a/src/input/input_cdda.c b/src/input/input_cdda.c index 7dd9ae21a..0b1f046e8 100644 --- a/src/input/input_cdda.c +++ b/src/input/input_cdda.c @@ -617,7 +617,10 @@ static int read_cdrom_frames(cdda_input_plugin_t *this_gen, int frame, int num_f #elif defined(__FreeBSD__) || defined(__NetBSD__) #include <sys/cdio.h> + +#ifdef HAVE_SYS_SCSIIO_H #include <sys/scsiio.h> +#endif static int read_cdrom_toc(int fd, cdrom_toc *toc) { diff --git a/src/input/input_dvb.c b/src/input/input_dvb.c index 10d6eca55..ae7c0c21e 100644 --- a/src/input/input_dvb.c +++ b/src/input/input_dvb.c @@ -77,6 +77,8 @@ #include <assert.h> #include <stdio.h> #include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <string.h> @@ -703,7 +705,7 @@ static int find_param(const Param *list, const char *name) return list->value;; } -static int extract_channel_from_string(channel_t * channel,char * str,fe_type_t fe_type) +static int extract_channel_from_string_internal(channel_t * channel,char * str,fe_type_t fe_type) { /* try to extract channel data from a string in the following format @@ -864,55 +866,69 @@ static int extract_channel_from_string(channel_t * channel,char * str,fe_type_t return 0; } -static channel_t *load_channels(dvb_input_plugin_t *this, int *num_ch, fe_type_t fe_type) { +static int extract_channel_from_string(channel_t *channel, char *str, fe_type_t fe_type) +{ + channel->name = NULL; + if (!extract_channel_from_string_internal(channel, str, fe_type)) + return 0; + free (channel->name); /* without this, we have a possible memleak */ + return -1; +} + +static channel_t *load_channels(xine_t *xine, xine_stream_t *stream, int *num_ch, fe_type_t fe_type) { FILE *f; char str[BUFSIZE]; char filename[BUFSIZE]; - channel_t *channels; - int num_channels; + channel_t *channels = NULL; + int num_channels = 0; + int num_alloc = 0; int i; - xine_t *xine = this->class->xine; + struct stat st; snprintf(filename, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir()); - f = fopen(filename, "rb"); + f = fopen(filename, "r"); if (!f) { - xprintf(xine, XINE_VERBOSITY_LOG, _("input_dvb: failed to open dvb channel file '%s'\n"), filename); - _x_message(this->stream, XINE_MSG_FILE_NOT_FOUND, filename, "Please run the dvbscan utility.", NULL); + xprintf(xine, XINE_VERBOSITY_LOG, _("input_dvb: failed to open dvb channel file '%s': %s\n"), filename, strerror (errno)); + if (!f && stream) + _x_message(stream, XINE_MSG_FILE_NOT_FOUND, filename, "Please run the dvbscan utility.", NULL); return NULL; } - - /* - * count and alloc channels - */ - num_channels = 0; - while ( fgets (str, BUFSIZE, f)) { - num_channels++; - } - fclose (f); - - if(num_channels > 0) - xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: expecting %d channels...\n", num_channels); - else { - xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: no channels found in the file: giving up.\n"); + if (fstat(fileno(f), &st) || !S_ISREG (st.st_mode)) { + xprintf(xine, XINE_VERBOSITY_LOG, _("input_dvb: dvb channel file '%s' is not a plain file\n"), filename); + fclose(f); return NULL; } - channels = xine_xmalloc (sizeof (channel_t) * num_channels); - - _x_assert(channels != NULL); - /* * load channel list */ - f = fopen (filename, "rb"); - num_channels = 0; while ( fgets (str, BUFSIZE, f)) { - if (extract_channel_from_string(&(channels[num_channels]),str,fe_type) < 0) + channel_t channel = {0}; + + /* lose trailing spaces & control characters */ + 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) continue; + if (num_channels >= num_alloc) { + channel_t *new_channels = xine_xmalloc((num_alloc += 32) * sizeof (channel_t)); + _x_assert(new_channels != NULL); + memcpy(new_channels, channels, num_channels * sizeof (channel_t)); + free(channels); + channels = new_channels; + } + + channels[num_channels] = channel; + /* 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) @@ -922,6 +938,9 @@ static channel_t *load_channels(dvb_input_plugin_t *this, int *num_ch, fe_type_t } fclose(f); + /* free any trailing unused entries */ + channels = realloc (channels, num_channels * sizeof (channel_t)); + if(num_channels > 0) xprintf (xine, XINE_VERBOSITY_DEBUG, "input_dvb: found %d channels...\n", num_channels); else { @@ -934,6 +953,14 @@ static channel_t *load_channels(dvb_input_plugin_t *this, int *num_ch, fe_type_t return channels; } +static void free_channel_list (channel_t *channels, int num_channels) +{ + if (channels) + while (--num_channels >= 0) + free(channels[num_channels].name); + free(channels); +} + static int tuner_set_diseqc(tuner_t *this, channel_t *c) { struct dvb_diseqc_master_cmd cmd = @@ -2624,7 +2651,7 @@ static void dvb_plugin_dispose (input_plugin_t *this_gen) { } } if (this->channels) - free (this->channels); + free_channel_list (this->channels, this->num_channels); /* Make the EPG updater thread return. */ @@ -2719,7 +2746,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, &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); @@ -3120,77 +3147,46 @@ 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; - FILE *f; - char *tmpbuffer=xine_xmalloc(BUFSIZE); - char *foobuffer=xine_xmalloc(BUFSIZE); - char *str=tmpbuffer; - int num_channels; - int nlines=0; - int default_channel; - xine_cfg_entry_t lastchannel_enable; + char foobuffer[BUFSIZE]; + int ch, apch, num_channels; + int default_channel = -1; + xine_cfg_entry_t lastchannel_enable = {0}; xine_cfg_entry_t lastchannel; - _x_assert(tmpbuffer != NULL); - _x_assert(foobuffer != NULL); - - snprintf(tmpbuffer, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir()); - num_channels = 0; - f=fopen (tmpbuffer,"rb"); - if(!f){ /* channels.conf not found in .xine */ + if (!(channels = load_channels(class->xine, NULL, &num_channels, 0))) { + /* channels.conf not found in .xine */ class->mrls[0]="Sorry, No channels.conf found"; class->mrls[1]="Please run the dvbscan utility"; class->mrls[2]="from the dvb drivers apps package"; class->mrls[3]="and place the file in ~/.xine/"; *num_files=4; - free(tmpbuffer); - free(foobuffer); return class->mrls; - } else { - while (fgets(str, BUFSIZE, f)) - nlines++; } - fclose (f); - if (xine_config_lookup_entry(class->xine, "media.dvb.remember_channel", &lastchannel_enable)) - if (lastchannel_enable.num_value){ - num_channels++; - if (xine_config_lookup_entry(class->xine, "media.dvb.last_channel", &lastchannel)) - default_channel = lastchannel.num_value; - } - - if (nlines+lastchannel_enable.num_value >= MAX_AUTOCHANNELS) - nlines = MAX_AUTOCHANNELS-lastchannel_enable.num_value; - - snprintf(tmpbuffer, BUFSIZE, "%s/.xine/channels.conf", xine_get_homedir()); - - - f=fopen (tmpbuffer,"rb"); - channels=xine_xmalloc(sizeof(channel_t)*(nlines+lastchannel_enable.num_value)); - - _x_assert(channels != NULL); - - - while (fgets(str,BUFSIZE,f) && num_channels < nlines+lastchannel_enable.num_value) { - if (extract_channel_from_string (&(channels[num_channels]), str, 0) < 0) - continue; - - sprintf(foobuffer,"dvb://%s",channels[num_channels].name); - if(class->autoplaylist[num_channels]) - free(class->autoplaylist[num_channels]); - class->autoplaylist[num_channels]=xine_xmalloc(128); + if (xine_config_lookup_entry(class->xine, "media.dvb.remember_channel", &lastchannel_enable) + && lastchannel_enable.num_value + && xine_config_lookup_entry(class->xine, "media.dvb.last_channel", &lastchannel)) + { + default_channel = lastchannel.num_value - 1; + if (default_channel < 0 || default_channel >= num_channels) + default_channel = -1; + } - _x_assert(class->autoplaylist[num_channels] != NULL); - - class->autoplaylist[num_channels]=strdup(foobuffer); - num_channels++; - } + 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); + } if (lastchannel_enable.num_value){ - if (lastchannel.num_value > -1 && lastchannel.num_value < num_channels) + if (default_channel != -1) /* plugin has been used before - channel is valid */ - sprintf (foobuffer, "dvb://%s", channels[lastchannel.num_value].name); + sprintf (foobuffer, "dvb://%s", channels[default_channel].name); else /* set a reasonable default - the first channel */ sprintf (foobuffer, "dvb://%s", num_channels ? channels[0].name : "0"); @@ -3198,13 +3194,10 @@ static char **dvb_class_get_autoplay_list(input_class_t * this_gen, class->autoplaylist[0]=strdup(foobuffer); } - free(tmpbuffer); - free(foobuffer); - free(channels); - fclose(f); + free_channel_list(channels, num_channels); - *num_files = num_channels; - class->numchannels=nlines; + *num_files = num_channels + lastchannel_enable.num_value; + class->numchannels = *num_files; return class->autoplaylist; } diff --git a/src/input/input_http.c b/src/input/input_http.c index 3adbc836b..6b7ae9158 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -181,7 +181,7 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { /* \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) ) { lprintf("host '%s' is localhost\n", host); - return 1; + return 0; } /* TODO: IPv6 check */ } @@ -200,13 +200,13 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { /* special-case domain beginning with '=' -> is a host name */ if (domain[0] == '=' && strcmp(target, domain + 1) == 0) { lprintf("host '%s' is in no-proxy domain '%s'\n", target, domain); - return 1; + return 0; } noprox_len = strlen(domain); /* special-case host==domain, avoiding dot checks */ if (host_len == noprox_len && strcmp(target, domain) == 0) { lprintf("host '%s' is in no-proxy domain '%s'\n", target, domain); - return 1; + return 0; } /* check for host in domain, and require that (if matched) the domain * name is preceded by a dot, either in the host or domain strings, @@ -216,7 +216,7 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { && (domain[0] == '.' || target[host_len - noprox_len - 1] == '.') && strcmp(target + host_len - noprox_len, domain) == 0) { lprintf("host '%s' is in no-proxy domain '%s'\n", target, domain); - return 1; + return 0; } lprintf("host '%s' isn't in no-proxy domain '%s'\n", target, domain); } @@ -225,7 +225,7 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { } free(no_proxy); - return 0; + return 1; } static int http_plugin_basicauth (const char *user, const char *password, char* dest, int len) { @@ -663,9 +663,8 @@ static int http_plugin_open (input_plugin_t *this_gen ) { _x_message(this->stream, XINE_MSG_GENERAL_WARNING, "malformed url", NULL); return 0; } - if (use_proxy && _x_use_proxy(this_class, this->host)) { - use_proxy = 0; - } + use_proxy = use_proxy && _x_use_proxy(this_class, this->host); + if (this->port == 0) this->port = DEFAULT_HTTP_PORT; diff --git a/src/libdts/Makefile.am b/src/libdts/Makefile.am index 207755f1f..ea09aab2e 100644 --- a/src/libdts/Makefile.am +++ b/src/libdts/Makefile.am @@ -24,5 +24,5 @@ else xineplug_decode_dts_la_LIBADD = $(XINE_LIB) -lm endif -noinst_HEADERS = bitstream.h dts.h dts_internal.h tables.h tables_adpcm.h \ +noinst_HEADERS = bitstream.h internal-dts.h dts_internal.h tables.h tables_adpcm.h \ tables_fir.h tables_huffman.h tables_quantization.h tables_vq.h diff --git a/src/libdts/bitstream.c b/src/libdts/bitstream.c index 8a5c4caac..50b2b9fe8 100644 --- a/src/libdts/bitstream.c +++ b/src/libdts/bitstream.c @@ -26,7 +26,7 @@ #include <inttypes.h> -#include "dts.h" +#include "internal-dts.h" #include "dts_internal.h" #include "bitstream.h" diff --git a/src/libdts/downmix.c b/src/libdts/downmix.c index 3614c5e8b..fe7136a72 100644 --- a/src/libdts/downmix.c +++ b/src/libdts/downmix.c @@ -27,7 +27,7 @@ #include <string.h> #include <inttypes.h> -#include "dts.h" +#include "internal-dts.h" #include "dts_internal.h" #define CONVERT(acmod,output) (((output) << DTS_CHANNEL_BITS) + (acmod)) diff --git a/src/libdts/dts.h b/src/libdts/internal-dts.h index 30f3a197b..30f3a197b 100644 --- a/src/libdts/dts.h +++ b/src/libdts/internal-dts.h diff --git a/src/libdts/parse.c b/src/libdts/parse.c index 3806a5594..67067addb 100644 --- a/src/libdts/parse.c +++ b/src/libdts/parse.c @@ -34,7 +34,7 @@ #define M_PI 3.1415926535897932384626433832795029 #endif -#include "dts.h" +#include "internal-dts.h" #include "dts_internal.h" #include "bitstream.h" diff --git a/src/libdts/xine_dts_decoder.c b/src/libdts/xine_dts_decoder.c index 902d8c5b6..0ef9afa17 100644 --- a/src/libdts/xine_dts_decoder.c +++ b/src/libdts/xine_dts_decoder.c @@ -49,7 +49,12 @@ #include "xineutils.h" #include "audio_out.h" #include "buffer.h" -#include "dts.h" + +#ifdef HAVE_DTS_H +# include <dts.h> +#else +# include "internal-dts.h" +#endif #define MAX_AC5_FRAME 4096 diff --git a/src/libffmpeg/libavcodec/i386/Makefile.am b/src/libffmpeg/libavcodec/i386/Makefile.am index e3285d9cd..b9d33c3a7 100644 --- a/src/libffmpeg/libavcodec/i386/Makefile.am +++ b/src/libffmpeg/libavcodec/i386/Makefile.am @@ -14,6 +14,9 @@ dsputil_mmx.o dsputil_mmx.lo: CFLAGS=$(shell echo @CFLAGS@ | sed -e 's/-funroll- # 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'` +# Avoid errors with -O0 +mpegvideo_mmx.o mpegvideo_mmx.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/-O0\?\s/-Os /g'` + ASFLAGS = noinst_LTLIBRARIES = libavcodec_mmx.la diff --git a/src/libffmpeg/libavcodec/libpostproc/Makefile.am b/src/libffmpeg/libavcodec/libpostproc/Makefile.am index af1976b48..66bd17e53 100644 --- a/src/libffmpeg/libavcodec/libpostproc/Makefile.am +++ b/src/libffmpeg/libavcodec/libpostproc/Makefile.am @@ -4,6 +4,10 @@ include $(top_srcdir)/misc/Makefile.common # work, but at least it compiles. AM_CFLAGS = -fomit-frame-pointer -fno-strict-aliasing 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'` + ASFLAGS = noinst_LTLIBRARIES = libpostprocess.la diff --git a/src/libreal/real_common.c b/src/libreal/real_common.c index 925a5cc71..22c33aa03 100644 --- a/src/libreal/real_common.c +++ b/src/libreal/real_common.c @@ -83,8 +83,8 @@ void _x_real_codecs_init(xine_t *const xine) { default_real_codecs_path = path; #define try_real_subpath(path) \ try_real_path("/usr/" path) \ - else try_real_path("/usr/local" path) \ - else try_real_path("/opt" path) + else try_real_path("/usr/local/" path) \ + else try_real_path("/opt/" path) /* The priority is for the first found */ try_real_subpath("lib/win32") diff --git a/src/post/goom/Makefile.am b/src/post/goom/Makefile.am index e6bae3374..53a806a7a 100644 --- a/src/post/goom/Makefile.am +++ b/src/post/goom/Makefile.am @@ -8,6 +8,9 @@ EXTRA_DIST = mmx.c xmmx.c ppc_drawings.s ppc_zoom_ultimate.s diff_against_releas #CFLAGS = `echo @CFLAGS@ | sed -e 's/-fomit-frame-pointer//g;s/-Os/-O2/g'` CFLAGS = `echo @CFLAGS@ | sed -e 's/-Os/-O2/g'` +# Avoid errors with -O0 +xineplug_post_goom_la-xmmx.o xineplug_post_goom_la-xmmx.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/-O0\?\s/-Os /g'` + xinepost_LTLIBRARIES = xineplug_post_goom.la ## doesn't work diff --git a/src/post/planar/Makefile.am b/src/post/planar/Makefile.am index 5fc425cdf..826f378a6 100644 --- a/src/post/planar/Makefile.am +++ b/src/post/planar/Makefile.am @@ -15,6 +15,11 @@ endif # work, but at least it compiles. AM_CFLAGS = $(ff_cflags) -fomit-frame-pointer +# Avoid errors with -O0 +xineplug_post_planar_la-eq.o xineplug_post_planar_la-eq.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/-O0\?\s/-Os /g'` +xineplug_post_planar_la-eq2.o xineplug_post_planar_la-eq2.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/-O0\?\s/-Os /g'` +xineplug_post_planar_la-noise.o xineplug_post_planar_la-noise.lo: CFLAGS=`echo @CFLAGS@ | sed -e 's/-O0\?\s/-Os /g'` + xinepost_LTLIBRARIES = xineplug_post_planar.la xineplug_post_planar_la_SOURCES = planar.c invert.c expand.c fill.c boxblur.c \ diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 34971377c..148eda84c 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -5,7 +5,7 @@ AM_LDFLAGS = $(xineplug_ldflags) SUBDIRS = libdha vidix macosx -EXTRA_DIST = video_out_directfb.c video_out_directx.c video_out_macosx.m +EXTRA_DIST = video_out_directfb.c video_out_directfb_fb.c video_out_directfb_x.c video_out_directx.c video_out_macosx.m VIDIX_CFLAGS = -I$(top_builddir)/src/video_out/vidix \ -I$(top_srcdir)/src/video_out/vidix @@ -64,6 +64,9 @@ endif if HAVE_DIRECTFB directfb_module = xineplug_vo_out_directfb.la +if HAVE_X11 +directfb_module += xineplug_vo_out_xdirectfb.la +endif endif if HAVE_SDL @@ -162,10 +165,14 @@ xineplug_vo_out_fb_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c \ xineplug_vo_out_fb_la_LIBADD = $(MLIB_LIBS) $(XINE_LIB) $(PTHREAD_LIBS) xineplug_vo_out_fb_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) -xineplug_vo_out_directfb_la_SOURCES = video_out_directfb.c $(X11OSD) -xineplug_vo_out_directfb_la_LIBADD = $(XINE_LIB) $(DIRECTFB_LIBS) $(X_LIBS) $(PTHREAD_LIBS) +xineplug_vo_out_directfb_la_SOURCES = video_out_directfb_fb.c +xineplug_vo_out_directfb_la_LIBADD = $(XINE_LIB) $(DIRECTFB_LIBS) $(PTHREAD_LIBS) xineplug_vo_out_directfb_la_CFLAGS = $(VISIBILITY_FLAG) $(DIRECTFB_CFLAGS) -fno-strict-aliasing +xineplug_vo_out_xdirectfb_la_SOURCES = video_out_directfb_x.c $(X11OSD) +xineplug_vo_out_xdirectfb_la_LIBADD = $(XINE_LIB) $(DIRECTFB_LIBS) $(X_LIBS) $(PTHREAD_LIBS) +xineplug_vo_out_xdirectfb_la_CFLAGS = $(VISIBILITY_FLAG) $(DIRECTFB_CFLAGS) -fno-strict-aliasing + xineplug_vo_out_sdl_la_SOURCES = video_out_sdl.c xineplug_vo_out_sdl_la_LIBADD = $(SDL_LIBS) $(X_LIBS) $(XINE_LIB) $(PTHREAD_LIBS) xineplug_vo_out_sdl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(SDL_CFLAGS) diff --git a/src/video_out/macosx/XineOpenGLView.h b/src/video_out/macosx/XineOpenGLView.h index 063a33eb2..b63738047 100644 --- a/src/video_out/macosx/XineOpenGLView.h +++ b/src/video_out/macosx/XineOpenGLView.h @@ -23,6 +23,7 @@ #define __HAVE_XINE_OPENGL_VIEW_H__ #import <Cocoa/Cocoa.h> +#import <OpenGL/gl.h> #import "XineVideoWindow.h" @@ -32,74 +33,106 @@ extern NSString *XineViewDidResizeNotification; @interface XineOpenGLView : NSOpenGLView { + @private IBOutlet id <NSObject, XineOpenGLViewDelegate> delegate; - int video_width, video_height; - char *texture_buffer; - unsigned long i_texture; - BOOL initDone; - BOOL isFullScreen; - XineVideoWindowFullScreenMode fullscreen_mode; - NSOpenGLContext *fullScreenContext; - NSOpenGLContext *currentContext; - NSLock *mutex; - BOOL keepsVideoAspectRatio; - BOOL resizeViewOnVideoSizeChange; - NSCursor *currentCursor; - id <NSObject, XineOpenGLViewDelegate> _xineController; - NSColor *initialColor; - unsigned int initialColorYUV; - BOOL initialColorYUVIsSet; + IBOutlet id <NSObject, XineOpenGLViewDelegate> controller; + + NSRecursiveLock * mutex; + BOOL initDone; + + NSSize videoSize; + char * textureBuffer; + GLuint texture; + + BOOL keepsVideoAspectRatio; + BOOL resizeViewOnVideoSizeChange; + NSCursor * currentCursor; + + NSColor * initialColor; + unsigned int initialColorYUV; + BOOL initialColorYUVIsSet; + + BOOL isFullScreen; + BOOL isFullScreenPrepared; + XineVideoWindowFullScreenMode fullScreenMode; + NSOpenGLContext * fullScreenContext; } -- (void) displayTexture; -- (void) drawQuad; -- (void) drawRect: (NSRect) rect; -- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode; -- (void) exitFullScreen; -- (BOOL) isFullScreen; -- (void) reshape; -- (void) initTextures; -- (void) reloadTexture; -- (char *) getTextureBuffer; -- (void) setViewSizeInMainThread:(NSSize)size; -// TODO: replace set...Size below with setSize:(double)videoSizeMultiplier -- (void) setNormalSize; -- (void) setHalfSize; -- (void) setDoubleSize; -- (void) setResizeViewOnVideoSizeChange:(BOOL)flag; -- (BOOL) resizeViewOnVideoSizeChange; -- (void) resetCursorRectsInMainThread; - -// Accessors -- (void) setVideoSize:(NSSize)size; -- (NSSize) videoSize; -- (void) setKeepsVideoAspectRatio:(BOOL)flag; -- (BOOL) keepsVideoAspectRatio; -- (void) setCurrentCursor:(NSCursor *)cursor; -- (NSCursor *) currentCursor; -- (void) setXineController:(id)controller; -- (id) xineController; -- (void) setInitialColor:(NSColor *)color; -- (NSColor *) initialColor; - -// Delegate Methods -- (id) delegate; -- (void) setDelegate:(id)aDelegate; ++ (NSOpenGLPixelFormat *)defaultPixelFormat; ++ (NSOpenGLPixelFormat *)fullScreenPixelFormat; -@end +- (id)initWithCoder:(NSCoder *)coder; +- (id)initWithFrame:(NSRect)frame; +- (id)initWithFrame:(NSRect)frame pixelFormat:(NSOpenGLPixelFormat *)pixelFormat; -/* XineOpenGLView delegate methods */ +- (void)dealloc; + +- (void)encodeWithCoder:(NSCoder *)coder; + +- (NSOpenGLContext *)openGLContext; +- (void)prepareOpenGL; +- (void)reshape; +- (void)update; + +- (void)initTextures; +- (void)updateTexture; +- (void)drawRect:(NSRect)rect; + +- (NSColor *)initialColor; +- (void)setInitialColor:(NSColor *)color; + +- (void)setNormalSize; +- (void)setHalfSize; +- (void)setDoubleSize; -@interface NSObject (XineOpenGLViewDelegate) +- (NSSize)videoSize; -- (NSSize) xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; -- (void) xineViewDidResize:(NSNotification *)aNotification; -- (void) mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) otherMouseDown:(NSEvent *)theEvent - inXineView:(XineOpenGLView *)theView; -- (void) rightMouseDown:(NSEvent *)theEvent - inXineView:(XineOpenGLView *)theView; +- (BOOL)keepsVideoAspectRatio; +- (void)setKeepsVideoAspectRatio:(BOOL)flag; +- (BOOL)resizeViewOnVideoSizeChange; +- (void)setResizeViewOnVideoSizeChange:(BOOL)flag; + +- (void)setViewSize:(NSValue *)sizeWrapper; +- (void)setViewSizeInMainThread:(NSSize)size; + +- (NSCursor *)currentCursor; +- (void)setCurrentCursor:(NSCursor *)cursor; + +- (BOOL)isFullScreen; +- (void)goFullScreen:(XineVideoWindowFullScreenMode)mode; +- (void)exitFullScreen; + +- (id)delegate; +- (void)setDelegate:(id)aDelegate; +- (id)xineController; +- (void)setXineController:(id)aController; + +- (BOOL)acceptsFirstResponder; +- (BOOL)mouseDownCanMoveWindow; + +// Not intended for public use: +- (char *)textureBuffer; +- (void)setVideoSize:(NSSize)size; +- (void)resetCursorRects; +- (void)resetCursorRectsInMainThread; +- (void)calcFullScreenAspect; +- (void)releaseInMainThread; +- (void)passEventToDelegate:(NSEvent *)theEvent withSelector:(SEL)selector; + +- (BOOL)acceptsFirstResponder; +- (BOOL)mouseDownCanMoveWindow; + +@end + +/* XineOpenGLView delegate methods */ +@protocol XineOpenGLViewDelegate + +- (void)mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void)mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void)otherMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (void)rightMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; +- (NSSize)xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; +- (void)xineViewDidResize:(NSNotification *)note; @end diff --git a/src/video_out/macosx/XineOpenGLView.m b/src/video_out/macosx/XineOpenGLView.m index e939575a0..c29f95dc7 100644 --- a/src/video_out/macosx/XineOpenGLView.m +++ b/src/video_out/macosx/XineOpenGLView.m @@ -19,7 +19,6 @@ * */ - /* #define LOG */ @@ -37,700 +36,411 @@ # include <xine/xineutils.h> #endif +NSString *XineViewDidResizeNotification EXPORTED = @"XineViewDidResizeNotification"; -NSString *XineViewDidResizeNotification = @"XineViewDidResizeNotification"; - - -/* XineOpenGLView delegate methods */ - -@protocol XineOpenGLViewDelegate - -- (void) mouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) mouseMoved:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) otherMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (void) rightMouseDown:(NSEvent *)theEvent inXineView:(XineOpenGLView *)theView; -- (NSSize) xineViewWillResize:(NSSize)oldSize toSize:(NSSize)proposedSize; -- (void) xineViewDidResize:(NSNotification *)note; - -@end - +static uint32_t +NSColorToYUV(NSColor *color) +{ + float red, green, blue, alpha; + uint32_t yuv; + unsigned char r, g, b; + unsigned char y, u, v; -static uint32_t NSColorToYUV (NSColor *color); + NSColor *calibratedColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; + [calibratedColor getRed:&red green:&green blue:&blue alpha:&alpha]; + r = red * 255; + g = green * 255; + b = blue * 255; -@implementation XineOpenGLView + init_yuv_conversion(); -- (void) setKeepsVideoAspectRatio:(BOOL)flag -{ - keepsVideoAspectRatio = flag; -} + y = COMPUTE_Y(r, g, b); + u = COMPUTE_U(r, g, b); + v = COMPUTE_V(r, g, b); -- (BOOL) keepsVideoAspectRatio -{ - return keepsVideoAspectRatio; + yuv = (y << 24) | (u << 16) | (y << 8) | v; + return yuv; } -- (void) setResizeViewOnVideoSizeChange:(BOOL)flag -{ - resizeViewOnVideoSizeChange = flag; -} +@implementation XineOpenGLView -- (BOOL) resizeViewOnVideoSizeChange ++ (NSOpenGLPixelFormat *)defaultPixelFormat { - return resizeViewOnVideoSizeChange; -} + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAWindow, + 0 + }; -- (BOOL)mouseDownCanMoveWindow -{ - return YES; + return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; } -- (void)passEventToDelegate:(NSEvent *)theEvent withSelector:(SEL)selector ++ (NSOpenGLPixelFormat *)fullScreenPixelFormat { - NSPoint point = [self convertPoint:[theEvent locationInWindow] - fromView:nil]; - - if (!NSMouseInRect(point, [self bounds], [self isFlipped])) return; - - if ([delegate respondsToSelector:selector]) - { - [delegate performSelector:selector - withObject:theEvent - withObject:self]; - return; - } + NSOpenGLPixelFormatAttribute attributes[] = { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAFullScreen, + NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay), + 0 + }; - if ([_xineController respondsToSelector:selector]) - { - [_xineController performSelector:selector - withObject:theEvent - withObject:self]; - return; - } + return [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease]; } -- (void)mouseMoved:(NSEvent *)theEvent +- (id)initWithCoder:(NSCoder *)coder { - [self passEventToDelegate:theEvent - withSelector:@selector(mouseMoved:inXineView:)]; - - [super mouseMoved:theEvent]; -} + NSColor *color; -- (void)mouseDown:(NSEvent *)theEvent -{ - [self passEventToDelegate:theEvent - withSelector:@selector(mouseDown:inXineView:)]; - - [super mouseDown:theEvent]; -} + if ((self = [super initWithCoder:coder]) != nil) { + videoSize = [self frame].size; + mutex = [[NSRecursiveLock alloc] init]; + currentCursor = [[NSCursor arrowCursor] retain]; -- (void)rightMouseDown:(NSEvent *)theEvent -{ - [self passEventToDelegate:theEvent - withSelector:@selector(rightMouseDown:inXineView:)]; - - [super rightMouseDown:theEvent]; -} + if ([coder allowsKeyedCoding]) { + keepsVideoAspectRatio = [coder decodeBoolForKey:@"keepsVideoAspectRatio"]; + resizeViewOnVideoSizeChange = [coder decodeBoolForKey:@"resizeViewOnVideoSizeChange"]; + color = [coder decodeObjectForKey:@"initialColor"]; + } + else { /* Must decode values in the same order as encodeWithCoder: */ + [coder decodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; + [coder decodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; + color = [coder decodeObject]; + } + [self setInitialColor:color]; -- (void)otherMouseDown:(NSEvent *)theEvent -{ - [self passEventToDelegate:theEvent - withSelector:@selector(otherMouseDown:inXineView:)]; - - [super otherMouseDown:theEvent]; +#ifdef LOG + NSLog(@"XineOpenGLView: initWithCoder called"); +#endif + } + return self; } -- (NSSize)videoSize +- (id)initWithFrame:(NSRect)frame { - return NSMakeSize(video_width, video_height); -} - -- (void) displayTexture { - if ([self lockFocusIfCanDraw]) - { - [self drawRect: [self bounds]]; - [self reloadTexture]; - [self unlockFocus]; - } + return [self initWithFrame:frame pixelFormat:[[self class] defaultPixelFormat]]; } -- (id) initWithFrame: (NSRect) frame +- (id)initWithFrame:(NSRect)frame pixelFormat:(NSOpenGLPixelFormat *)format { - NSOpenGLPixelFormatAttribute attribs[] = { - NSOpenGLPFAAccelerated, - NSOpenGLPFANoRecovery, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 24, - NSOpenGLPFAWindow, - 0 - }; - - NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] - initWithAttributes: attribs]; - - if (!fmt) - { - NSLog (@"Cannot create NSOpenGLPixelFormat\n"); - return nil; - } - - self = [super initWithFrame:frame pixelFormat:fmt]; - - currentContext = [self openGLContext]; - [currentContext makeCurrentContext]; - [mutex lock]; - [currentContext update]; - [mutex unlock]; - - i_texture = 0; - initDone = NO; - isFullScreen = NO; - video_width = frame.size.width; - video_height = frame.size.height; - texture_buffer = nil; - mutex = [[NSLock alloc] init]; - currentCursor = [[NSCursor arrowCursor] retain]; - initialColor = nil; - initialColorYUV = 0; - initialColorYUVIsSet = NO; - _xineController = nil; - - [self initTextures]; - - /* Set GL_COLOR_BUFFER_BIT to black */ - glClearColor (0.0, 0.0, 0.0, 0.0); + format = (format ? : [[self class] defaultPixelFormat]); + if ((self = [super initWithFrame:frame pixelFormat:format]) != nil) { + videoSize = frame.size; + mutex = [[NSRecursiveLock alloc] init]; + currentCursor = [[NSCursor arrowCursor] retain]; + [self setInitialColor:nil]; #ifdef LOG - NSLog(@"XineOpenGLView: initWithFrame called"); + NSLog(@"XineOpenGLView: initWithFrame called"); #endif - + } return self; } -- (void) awakeFromNib -{ -#ifdef LOG - NSLog(@"XineOpenGLView: awakeFromNib called"); -#endif -} - -- (id) initWithCoder:(NSCoder *)coder +- (void)dealloc { - self = [super initWithCoder:coder]; - - self = [self initWithFrame:[self frame]]; - - if ([coder allowsKeyedCoding]) - { - keepsVideoAspectRatio = [coder decodeBoolForKey:@"keepsVideoAspectRatio"]; - resizeViewOnVideoSizeChange = [coder decodeBoolForKey: - @"resizeViewOnVideoSizeChange"]; - - NSColor *color = [coder decodeObjectForKey:@"initialColor"]; - if (color) - initialColor = [color copy]; + if (isFullScreen) { + [self exitFullScreen]; } - else - { - /* Must decode values in the same order as encodeWithCoder: */ - [coder decodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; - [coder decodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; - NSColor *color = [coder decodeObject]; - if (color) - initialColor = [color copy]; + if (texture) { + [[self openGLContext] makeCurrentContext]; + glDeleteTextures(1, &texture); + texture = 0; } + free(textureBuffer); - [self initTextures]; + [currentCursor release], currentCursor = nil; + [initialColor release], initialColor = nil; + [delegate release], delegate = nil; + [controller release], controller = nil; + [mutex release], mutex = nil; -#ifdef LOG - NSLog(@"XineOpenGLView: initWithCoder called"); -#endif - - return self; + [super dealloc]; } -- (void) encodeWithCoder:(NSCoder *)coder +- (void)encodeWithCoder:(NSCoder *)coder { [super encodeWithCoder:coder]; - if ([coder allowsKeyedCoding]) - { + if ([coder allowsKeyedCoding]) { [coder encodeBool:keepsVideoAspectRatio forKey:@"keepsVideoAspectRatio"]; - [coder encodeBool:resizeViewOnVideoSizeChange - forKey:@"resizeViewOnVideoSizeChange"]; + [coder encodeBool:resizeViewOnVideoSizeChange forKey:@"resizeViewOnVideoSizeChange"]; [coder encodeObject:initialColor forKey:@"initialColor"]; } - else - { + else { [coder encodeValueOfObjCType:@encode(BOOL) at:&keepsVideoAspectRatio]; [coder encodeValueOfObjCType:@encode(BOOL) at:&resizeViewOnVideoSizeChange]; [coder encodeObject:initialColor]; } } -- (void) dealloc { - if (texture_buffer) - free (texture_buffer); - - if (fullScreenContext) - { - [NSOpenGLContext clearCurrentContext]; - [mutex lock]; - [fullScreenContext clearDrawable]; - [fullScreenContext release]; - [mutex unlock]; - if (currentContext == fullScreenContext) currentContext = nil; - fullScreenContext = nil; - } - - if (currentContext) - { - [NSOpenGLContext clearCurrentContext]; - [mutex lock]; - [currentContext clearDrawable]; - [currentContext release]; - [mutex unlock]; - currentContext = nil; - } - - [mutex dealloc]; +- (NSOpenGLContext *)openGLContext +{ + NSOpenGLContext *context; - if (currentCursor) - { - [currentCursor release]; - currentCursor = NULL; + [mutex lock]; + if (!(context = [[fullScreenContext retain] autorelease])) { + context = [[[super openGLContext] retain] autorelease]; } - - if (initialColor) - { - [initialColor release]; - initialColor = NULL; + else if (!isFullScreenPrepared) { + [self prepareOpenGL]; + isFullScreenPrepared = YES; } + [mutex unlock]; - // Enabling the [super dealloc] below (which should be correct behaviour) - // crashes -- not sure why ... - // - // [super dealloc]; - // - // Maybe dealloc in main thread? + return context; } -- (void) reshape +// NOTE: This does not exist prior to Panther (10.3) +- (void)prepareOpenGL { + long swapInterval = 1; + [mutex lock]; - - if (!initDone) - { - [mutex unlock]; - return; - } - - [currentContext makeCurrentContext]; - - NSRect bounds = [self bounds]; - glViewport (0, 0, bounds.size.width, bounds.size.height); - -#ifdef LOG - NSLog(@"XineOpenGLView: Reshape: %x%x%x%x%x%x%x%x", - texture_buffer[0], - texture_buffer[1], - texture_buffer[2], - texture_buffer[3], - texture_buffer[4], - texture_buffer[5], - texture_buffer[6], - texture_buffer[7] - ); -#endif + [super prepareOpenGL]; + + [[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + + [self initTextures]; + + /* Set GL_COLOR_BUFFER_BIT to black */ + glClearColor (0.0, 0.0, 0.0, 0.0); [mutex unlock]; } -- (void) setNormalSize +- (void)reshape { - NSSize size; - - if (isFullScreen) - return; - - size.width = video_width; - size.height = video_height; - - [self setViewSizeInMainThread:size]; + [mutex lock]; + [super reshape]; + if (initDone) { + [[self openGLContext] makeCurrentContext]; + + NSRect bounds = [self bounds]; + glViewport(0, 0, bounds.size.width, bounds.size.height); + +#ifdef LOG + NSLog(@"XineOpenGLView: Reshape: %x%x%x%x%x%x%x%x", + textureBuffer[0], textureBuffer[1], textureBuffer[2], textureBuffer[3], + textureBuffer[4], textureBuffer[5], textureBuffer[6], textureBuffer[7]); +#endif + } + [mutex unlock]; } -- (void) setHalfSize +- (void)update { - NSSize size; - - if (isFullScreen) - return; - - size.width = video_width / 2; - size.height = video_height / 2; - - [self setViewSizeInMainThread:size]; + [mutex lock]; + [super update]; + [mutex unlock]; } -- (void) setDoubleSize +- (void)initTextures { - NSSize size; - - if (isFullScreen) - return; - - size.width = video_width * 2; - size.height = video_height * 2; - - [self setViewSizeInMainThread:size]; -} + uint32_t *p, *q, yuv; -- (void) initTextures -{ [mutex lock]; - [currentContext makeCurrentContext]; - /* Free previous texture if any */ - if (i_texture) - glDeleteTextures (1, &i_texture); + if (texture) { + glDeleteTextures(1, &texture); + texture = 0; + } - if (texture_buffer) - { - texture_buffer = realloc (texture_buffer, sizeof (char) * - video_width * video_height * 3); + if (!initialColorYUVIsSet && initialColor) { + initialColorYUV = NSColorToYUV(initialColor); + initialColorYUVIsSet = YES; } - else - { - texture_buffer = malloc (sizeof (char) * - video_width * video_height * 3); - - { - // There _has_ to be a better way of doing this ... - - uint32_t *p, *q; - p = (uint32_t *) texture_buffer; - q = (uint32_t *) (char *) (texture_buffer + (sizeof(char) * video_width * video_height * 3)); - - for (; p < q; p++) *p = initialColorYUV; - } + if (textureBuffer) { + textureBuffer = (char *)realloc(textureBuffer, videoSize.width * videoSize.height * 4); } + else { + textureBuffer = (char *)malloc(videoSize.width * videoSize.height * 4); - if (!initialColorYUVIsSet && initialColor) - { - initialColorYUV = NSColorToYUV(initialColor); - initialColorYUVIsSet = YES; + // There _has_ to be a better way of doing this ... + + yuv = OSSwapHostToBigInt32(initialColorYUV); + q = (uint32_t *)(char *)(textureBuffer + (int)(videoSize.width * videoSize.height * 4)); + for (p = (uint32_t *)textureBuffer; p < q; *p++ = yuv); } /* Create textures */ - glGenTextures (1, &i_texture); + glGenTextures(1, &texture); - glEnable (GL_TEXTURE_RECTANGLE_EXT); - glEnable (GL_UNPACK_CLIENT_STORAGE_APPLE); + glEnable(GL_TEXTURE_RECTANGLE_EXT); + glEnable(GL_UNPACK_CLIENT_STORAGE_APPLE); - glPixelStorei (GL_UNPACK_ALIGNMENT, 1); - glPixelStorei (GL_UNPACK_ROW_LENGTH, video_width); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glPixelStorei(GL_UNPACK_ROW_LENGTH, videoSize.width); - glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); /* Use VRAM texturing */ - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_STORAGE_HINT_APPLE, GL_STORAGE_CACHED_APPLE); /* Tell the driver not to make a copy of the texture but to use our buffer */ - glPixelStorei (GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); /* Linear interpolation */ - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* I have no idea what this exactly does, but it seems to be necessary for scaling */ - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_RECTANGLE_EXT, - GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, - video_width, video_height, 0, - GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, - texture_buffer); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, + GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, + videoSize.width, videoSize.height, 0, GL_YCBCR_422_APPLE, +#if WORDS_BIGENDIAN + GL_UNSIGNED_SHORT_8_8_APPLE, +#else + GL_UNSIGNED_SHORT_8_8_REV_APPLE, +#endif + textureBuffer); initDone = YES; [mutex unlock]; #ifdef LOG NSLog(@"XineOpenGLView: initTextures called: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx", - texture_buffer[0], - texture_buffer[1], - texture_buffer[2], - texture_buffer[3], - texture_buffer[4], - texture_buffer[5], - texture_buffer[6], - texture_buffer[7] - ); + textureBuffer[0], textureBuffer[1], textureBuffer[2], textureBuffer[3], + textureBuffer[4], textureBuffer[5], textureBuffer[6], textureBuffer[7]); #endif } -- (void) reloadTexture +- (void)updateTexture { - if (!initDone) - { - return; - } - [mutex lock]; - - [currentContext makeCurrentContext]; - - glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); - glPixelStorei (GL_UNPACK_ROW_LENGTH, video_width); - + [[self openGLContext] makeCurrentContext]; + + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture); + glPixelStorei(GL_UNPACK_ROW_LENGTH, videoSize.width); + // glTexSubImage2D is faster than glTexImage2D // http://developer.apple.com/samplecode/Sample_Code/Graphics_3D/TextureRange/MainOpenGLView.m.htm - glTexSubImage2D (GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, - video_width, video_height, - GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, - texture_buffer); - - [mutex unlock]; - -#ifdef LOG - NSLog(@"reloadTexture called"); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, 0, 0, + videoSize.width, videoSize.height, GL_YCBCR_422_APPLE, +#if WORDS_BIG_ENDIAN + GL_UNSIGNED_SHORT_8_8_APPLE, +#else + GL_UNSIGNED_SHORT_8_8_REV_APPLE, #endif + textureBuffer); + + [self setNeedsDisplay:YES]; + [mutex unlock]; } -- (void) calcFullScreenAspect +- (void)drawRect:(NSRect)rect { - int fs_width, fs_height, x = 0, y = 0, w = 0, h = 0; - - fs_width = CGDisplayPixelsWide (kCGDirectMainDisplay); - fs_height = CGDisplayPixelsHigh (kCGDirectMainDisplay); - - switch (fullscreen_mode) { - case XINE_FULLSCREEN_OVERSCAN: - if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) - { - w = (float) video_width * ((float) fs_height / (float) video_height); - h = fs_height; - x = (fs_width - w) / 2; - y = 0; - } - else - { - w = fs_width; - h = (float) video_height * ((float) fs_width / (float) video_width); - x = 0; - y = (fs_height - h) / 2; - } - break; - - case XINE_FULLSCREEN_CROP: - if (((float) fs_width / (float) fs_height) > ((float) video_width / (float) video_height)) - { - w = fs_width; - h = (float) video_height * ((float) fs_width / (float) video_width); - x = 0; - y = (fs_height - h) / 2; - } - else - { - w = (float) video_width * ((float) fs_height / (float) video_height); - h = fs_height; - x = (fs_width - w) / 2; - y = 0; - } - break; - } - - NSLog(@"MacOSX fullscreen mode: %dx%d => %dx%d @ %d,%d\n", - video_width, video_height, w, h, x, y); - [mutex lock]; - glViewport (x, y, w, h); + if (initDone && texture) { + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, texture); + glBegin(GL_QUADS); + glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, 1.0); // top left + glTexCoord2f(0.0, videoSize.height); glVertex2f(-1.0, -1.0); // bottom left + glTexCoord2f(videoSize.width, videoSize.height); glVertex2f( 1.0, -1.0); // bottom right + glTexCoord2f(videoSize.width, 0.0); glVertex2f( 1.0, 1.0); // top right + glEnd(); + [[self openGLContext] flushBuffer]; + } [mutex unlock]; } -- (void) goFullScreen: (XineVideoWindowFullScreenMode) mode +- (NSColor *)initialColor +{ + return initialColor; +} + +- (void) setInitialColor:(NSColor *)color +{ + [initialColor autorelease]; + initialColor = (color ? [color copy] : [[NSColor blackColor] retain]); +} + +- (void)setNormalSize { [mutex lock]; - - /* Create the new pixel format */ - NSOpenGLPixelFormatAttribute attribs[] = - { - NSOpenGLPFAAccelerated, - NSOpenGLPFANoRecovery, - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAColorSize, 24, - NSOpenGLPFAAlphaSize, 8, - NSOpenGLPFADepthSize, 24, - NSOpenGLPFAFullScreen, - NSOpenGLPFAScreenMask, - CGDisplayIDToOpenGLDisplayMask (kCGDirectMainDisplay), - 0 - }; - - NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] - initWithAttributes: attribs]; - - if (!fmt) - { - NSLog (@"Cannot create NSOpenGLPixelFormat\n"); - return; - } - - /* Create the new OpenGL context */ - fullScreenContext = [[NSOpenGLContext alloc] - initWithFormat: fmt shareContext: nil]; - - if (!fullScreenContext) - { - NSLog(@"Failed to create new NSOpenGLContext\n"); - return; + if (!isFullScreen) { + [self setViewSizeInMainThread:videoSize]; } - currentContext = fullScreenContext; - - /* Capture display, switch to fullscreen */ - if (CGCaptureAllDisplays() != CGDisplayNoErr) - { - NSLog(@"CGCaptureAllDisplays() failed\n"); - return; - } - - [fullScreenContext setFullScreen]; - [fullScreenContext makeCurrentContext]; [mutex unlock]; - - fullscreen_mode = mode; - - [self initTextures]; - [self calcFullScreenAspect]; - - /* Redraw the last picture */ - [self setNeedsDisplay: YES]; - - isFullScreen = YES; } -- (void) exitFullScreen +- (void)setHalfSize { - initDone = NO; - - currentContext = [self openGLContext]; - - /* Free current OpenGL context */ - [NSOpenGLContext clearCurrentContext]; + NSSize size; + [mutex lock]; - [fullScreenContext clearDrawable]; + if (!isFullScreen) { + size.width = trunc(videoSize.width / 2); + size.height = trunc(videoSize.height / 2); + [self setViewSizeInMainThread:size]; + } [mutex unlock]; - [fullScreenContext release]; - fullScreenContext = nil; - CGReleaseAllDisplays(); - - [self reshape]; - [self initTextures]; - - /* Redraw the last picture */ - [self setNeedsDisplay: YES]; - - isFullScreen = NO; - initDone = YES; } -- (void) drawQuad +- (void)setDoubleSize { - float f_x = 1.0, f_y = 1.0; - - glBegin (GL_QUADS); - /* Top left */ - glTexCoord2f (0.0, 0.0); - glVertex2f (-f_x, f_y); - /* Bottom left */ - glTexCoord2f (0.0, (float) video_height); - glVertex2f (-f_x, -f_y); - /* Bottom right */ - glTexCoord2f ((float) video_width, (float) video_height); - glVertex2f (f_x, -f_y); - /* Top right */ - glTexCoord2f ((float) video_width, 0.0); - glVertex2f (f_x, f_y); - glEnd(); -} - -- (void) drawRect: (NSRect) rect -{ - [currentContext makeCurrentContext]; - - if (!initDone) - return; - + NSSize size; + [mutex lock]; - - // Swap buffers only during the vertical retrace of the monitor. - // http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL/chap5/chapter_5_section_44.html - - long params[] = { 1 }; - CGLSetParameter (CGLGetCurrentContext(), kCGLCPSwapInterval, params); - - /* Draw */ - glBindTexture (GL_TEXTURE_RECTANGLE_EXT, i_texture); - [self drawQuad]; - - /* Wait for the job to be done */ - [currentContext flushBuffer]; - + if (!isFullScreen) { + size.width = videoSize.width * 2; + size.height = videoSize.height * 2; + [self setViewSizeInMainThread:size]; + } [mutex unlock]; } -- (char *) getTextureBuffer +- (NSSize)videoSize { - return texture_buffer; + return videoSize; } -- (void) setVideoSize:(NSSize)size +- (BOOL)keepsVideoAspectRatio { - video_width = size.width; - video_height = size.height; - - if (resizeViewOnVideoSizeChange) - [self setViewSizeInMainThread:size]; - - [self initTextures]; + return keepsVideoAspectRatio; } -- (void) setViewSizeInMainThread:(NSSize)size +- (void)setKeepsVideoAspectRatio:(BOOL)flag { - // Create an autorelease pool, since we're running in a xine thread that - // may not have a pool of its own */ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSValue *sizeWrapper = [NSValue valueWithBytes:&size - objCType:@encode(NSSize)]; - - [self performSelectorOnMainThread:@selector(setViewSize:) - withObject:sizeWrapper - waitUntilDone:NO]; - -#ifdef LOG - NSLog(@"setViewSizeInMainThread called"); -#endif - - [pool release]; + keepsVideoAspectRatio = flag; +} + +- (BOOL)resizeViewOnVideoSizeChange +{ + return resizeViewOnVideoSizeChange; +} + +- (void)setResizeViewOnVideoSizeChange:(BOOL)flag +{ + resizeViewOnVideoSizeChange = flag; } -- (void) setViewSize:(NSValue *)sizeWrapper +- (void)setViewSize:(NSValue *)sizeWrapper { - NSSize proposedSize, newSize, currentSize; + NSSize currentSize, newSize, proposedSize; [sizeWrapper getValue:&proposedSize]; newSize = proposedSize; @@ -742,19 +452,17 @@ static uint32_t NSColorToYUV (NSColor *color); return; } - /* If our controller handles xineViewWillResize:toSize:, send the - * message to him first. Note that the delegate still has a chance - * to override the controller's resize preference ... */ - if ([_xineController respondsToSelector:@selector(xineViewWillResize:toSize:)]) - { + // If our controller handles xineViewWillResize:toSize:, send the + // message to him first. Note that the delegate still has a chance + // to override the controller's resize preference ... + if ([controller respondsToSelector:@selector(xineViewWillResize:toSize:)]) { NSSize oldSize = [self frame].size; - newSize = [_xineController xineViewWillResize:oldSize toSize:proposedSize]; + newSize = [controller xineViewWillResize:oldSize toSize:proposedSize]; } - /* If our delegate handles xineViewWillResize:toSize:, send the - * message to him; otherwise, just resize ourselves */ - if ([delegate respondsToSelector:@selector(xineViewWillResize:toSize:)]) - { + // If our delegate handles xineViewWillResize:toSize:, send the + // message to him; otherwise, just resize ourselves + if ([delegate respondsToSelector:@selector(xineViewWillResize:toSize:)]) { NSSize oldSize = [self frame].size; newSize = [delegate xineViewWillResize:oldSize toSize:proposedSize]; } @@ -769,110 +477,294 @@ static uint32_t NSColorToYUV (NSColor *color); object:self]; [[NSNotificationCenter defaultCenter] postNotification:note]; - if ([_xineController respondsToSelector:@selector(xineViewDidResize:)]) - [_xineController xineViewDidResize:note]; + if ([controller respondsToSelector:@selector(xineViewDidResize:)]) { + [controller xineViewDidResize:note]; + } - if ([delegate respondsToSelector:@selector(xineViewDidResize:)]) + if ([delegate respondsToSelector:@selector(xineViewDidResize:)]) { [delegate xineViewDidResize:note]; - - if (isFullScreen) + } + + [mutex lock]; + [[self openGLContext] makeCurrentContext]; + if (isFullScreen) { [self calcFullScreenAspect]; - + } [self initTextures]; + [mutex unlock]; +} + +- (void)setViewSizeInMainThread:(NSSize)size +{ + // Create an autorelease pool, since we're running in a xine thread that + // may not have a pool of its own + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSValue *sizeWrapper = [NSValue valueWithBytes:&size + objCType:@encode(NSSize)]; + + [self performSelectorOnMainThread:@selector(setViewSize:) + withObject:sizeWrapper + waitUntilDone:NO]; + +#ifdef LOG + NSLog(@"setViewSizeInMainThread called"); +#endif + + [pool release]; +} + +- (NSCursor *)currentCursor +{ + return currentCursor; +} + +- (void)setCurrentCursor:(NSCursor *)cursor +{ + [currentCursor autorelease]; + currentCursor = [cursor retain]; + [self resetCursorRectsInMainThread]; } -- (BOOL) isFullScreen +- (BOOL)isFullScreen { return isFullScreen; } -- (id) delegate +- (void)goFullScreen:(XineVideoWindowFullScreenMode)mode { - return delegate; + NSOpenGLPixelFormat *pixelFormat; + + if (!(pixelFormat = [[self class] fullScreenPixelFormat])) { + NSLog(@"Cannot create NSOpenGLPixelFormat for full screen mode"); + return; + } + + if (!(fullScreenContext = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil])) { + NSLog(@"Cannot create NSOpenGLContext for full screen mode"); + return; + } + + if (CGCaptureAllDisplays() != CGDisplayNoErr) { + [fullScreenContext release], fullScreenContext = nil; + NSLog(@"CGCaptureAllDisplays() failed"); + return; + } + + [mutex lock]; + fullScreenMode = mode; + isFullScreenPrepared = NO; + + [fullScreenContext setFullScreen]; + [[self openGLContext] makeCurrentContext]; + + // Redraw the last picture + [self setNeedsDisplay:YES]; + + isFullScreen = YES; + [mutex unlock]; } -- (void) setDelegate:(id)aDelegate { - delegate = aDelegate; +- (void)exitFullScreen +{ + NSOpenGLContext *context; + + [mutex lock]; + if (isFullScreen) { + context = fullScreenContext; + fullScreenContext = nil; + [[self openGLContext] makeCurrentContext]; + + [context clearDrawable]; + [context release]; + + [self reshape]; + [self initTextures]; + + CGReleaseAllDisplays(); + [self setNeedsDisplay:YES]; + isFullScreen = NO; + } + [mutex unlock]; } -- (BOOL)acceptsFirstResponder { - return YES; +- (id)delegate +{ + return [[delegate retain] autorelease]; } -- (void) setCurrentCursor:(NSCursor *)cursor +- (void)setDelegate:(id)aDelegate { - currentCursor = cursor; - [currentCursor retain]; - [self resetCursorRectsInMainThread]; + [delegate autorelease]; + delegate = [aDelegate retain]; } -- (NSCursor *) currentCursor +- (id)xineController { - return currentCursor; + return controller; } -- (void) resetCursorRectsInMainThread +- (void)setXineController:(id)aController { - [self discardCursorRects]; - [self performSelectorOnMainThread:@selector(resetCursorRects) - withObject:nil - waitUntilDone:NO]; + [controller autorelease]; + controller = [aController retain]; } -- (void) resetCursorRects +- (char *)textureBuffer { - [self addCursorRect:[self visibleRect] cursor:currentCursor]; - [currentCursor set]; + return textureBuffer; } -- (void) setXineController:(id)controller +- (void)setVideoSize:(NSSize)size { - [_xineController autorelease]; - _xineController = controller; - [_xineController retain]; + [mutex lock]; + videoSize = size; + if (resizeViewOnVideoSizeChange) { + [self setViewSizeInMainThread:size]; + } + + if (initDone) { + [[self openGLContext] makeCurrentContext]; + [self initTextures]; + } + [mutex unlock]; } -- (id) xineController +- (void)resetCursorRects { - return _xineController; + [mutex lock]; + [self discardCursorRects]; + [self addCursorRect:[self visibleRect] cursor:currentCursor]; + [currentCursor set]; + [mutex unlock]; } -- (void) setInitialColor:(NSColor *)color +- (void)resetCursorRectsInMainThread { - [initialColor autorelease]; - initialColor = [color copy]; + [self performSelectorOnMainThread:@selector(resetCursorRects) + withObject:nil + waitUntilDone:NO]; } -- (NSColor *) initialColor +- (void)releaseInMainThread { - return initialColor; + [self performSelectorOnMainThread:@selector(release) + withObject:nil + waitUntilDone:NO]; } -@end /* XineOpenGLView */ +- (void)calcFullScreenAspect +{ + float fs_height, fs_width, h, w, x, y; + + // Feh, should go to main or should go to current display of window? + fs_width = CGDisplayPixelsWide(kCGDirectMainDisplay); + fs_height = CGDisplayPixelsHigh(kCGDirectMainDisplay); + + switch (fullScreenMode) { + case XINE_FULLSCREEN_OVERSCAN: + if ((fs_width / fs_height) > (videoSize.width / videoSize.height)) { + w = videoSize.width * (fs_height / videoSize.height); + h = fs_height; + x = (fs_width - w) / 2; + y = 0; + } + else { + w = fs_width; + h = videoSize.height * (fs_width / videoSize.width); + x = 0; + y = (fs_height - h) / 2; + } + break; + + case XINE_FULLSCREEN_CROP: + if ((fs_width / fs_height) > (videoSize.width / videoSize.height)) { + w = fs_width; + h = videoSize.height * (fs_width / videoSize.width); + x = 0; + y = (fs_height - h) / 2; + } + else { + w = videoSize.width * (fs_height / videoSize.height); + h = fs_height; + x = (fs_width - w) / 2; + y = 0; + } + break; + + default: + NSLog(@"Mac OS X fullscreen mode unrecognized: %d", fullScreenMode); + return; + } + +#ifdef LOG + NSLog(@"Mac OS X fullscreen mode: %fx%f => %fx%f @ %f,%f\n", + videoSize.width, videoSize.height, w, h, x, y); +#endif + // Assumes locked and current context set + glViewport(x, y, w, h); +} -static uint32_t NSColorToYUV (NSColor *color) +- (void)passEventToDelegate:(NSEvent *)theEvent withSelector:(SEL)selector { - float red, green, blue, alpha; - unsigned char r, g, b; - unsigned char y, u, v; - uint32_t yuv; + NSPoint point = [self convertPoint:[theEvent locationInWindow] + fromView:nil]; + + if (NSMouseInRect(point, [self bounds], [self isFlipped])) { + if ([delegate respondsToSelector:selector]) { + [delegate performSelector:selector + withObject:theEvent + withObject:self]; + } + else if ([controller respondsToSelector:selector]) { + [controller performSelector:selector + withObject:theEvent + withObject:self]; + } + } +} - NSColor *calibratedColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; - [calibratedColor getRed:&red green:&green blue:&blue alpha:&alpha]; +- (void)mouseMoved:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(mouseMoved:inXineView:)]; + + [super mouseMoved:theEvent]; +} - r = red * 255; - g = green * 255; - b = blue * 255; +- (void)mouseDown:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(mouseDown:inXineView:)]; + + [super mouseDown:theEvent]; +} - init_yuv_conversion(); +- (void)rightMouseDown:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(rightMouseDown:inXineView:)]; + + [super rightMouseDown:theEvent]; +} - y = COMPUTE_Y(r, g, b); - u = COMPUTE_U(r, g, b); - v = COMPUTE_V(r, g, b); +- (void)otherMouseDown:(NSEvent *)theEvent +{ + [self passEventToDelegate:theEvent + withSelector:@selector(otherMouseDown:inXineView:)]; + + [super otherMouseDown:theEvent]; +} - yuv = y << 24 | u << 16 | y << 8 | v; +- (BOOL)acceptsFirstResponder +{ + return YES; +} - return yuv; +- (BOOL)mouseDownCanMoveWindow +{ + return YES; } +@end diff --git a/src/video_out/macosx/XineVideoWindow.m b/src/video_out/macosx/XineVideoWindow.m index b61a5b418..0dd2caa28 100644 --- a/src/video_out/macosx/XineVideoWindow.m +++ b/src/video_out/macosx/XineVideoWindow.m @@ -108,7 +108,7 @@ } -- (XineOpenGLView *) xineView +- (id) xineView { return xineView; } diff --git a/src/video_out/video_out_directfb.c b/src/video_out/video_out_directfb.c index a51940952..efbb30f2d 100644 --- a/src/video_out/video_out_directfb.c +++ b/src/video_out/video_out_directfb.c @@ -31,7 +31,7 @@ #include <stdlib.h> #include <string.h> -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 # include <X11/Xlib.h> #endif @@ -44,7 +44,7 @@ #include "xineutils.h" #include "vo_scale.h" -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 # include "x11osd.h" #endif @@ -118,7 +118,7 @@ typedef struct directfb_driver_s { int flicker_filtering; int field_parity; -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 /* X11 related stuff */ Display *display; int screen; @@ -317,7 +317,7 @@ static void directfb_update_frame_format (vo_driver_t *this_gen, frame->ratio = ratio; } -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 static uint32_t directfb_colorkey_to_pixel (directfb_driver_t *this) { switch (this->depth) { case 8: @@ -343,7 +343,7 @@ static uint32_t directfb_colorkey_to_pixel (directfb_driver_t *this) { static void directfb_clean_output_area (directfb_driver_t *this) { if (this->visual_type == XINE_VISUAL_TYPE_X11 || this->visual_type == XINE_VISUAL_TYPE_X11_2) { -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->config.options & DLOP_DST_COLORKEY) { int i; @@ -410,7 +410,7 @@ static void directfb_overlay_begin (vo_driver_t *this_gen, this->ovl_changed += changed; if (this->ovl_changed) { -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->xoverlay) { LOCK_DISPLAY(); x11osd_clear (this->xoverlay); @@ -554,7 +554,7 @@ static void directfb_overlay_blend (vo_driver_t *this_gen, if (overlay->unscaled) { if (!this->ovl_changed) return; -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->xoverlay) { LOCK_DISPLAY(); x11osd_blend (this->xoverlay, overlay); @@ -586,7 +586,7 @@ static void directfb_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) directfb_driver_t *this = (directfb_driver_t *) this_gen; if (this->ovl_changed) { -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->xoverlay) { LOCK_DISPLAY(); x11osd_expose (this->xoverlay); @@ -1120,7 +1120,7 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen, switch (data_type) { case XINE_GUI_SEND_DRAWABLE_CHANGED: lprintf ("drawable changed.\n"); -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->visual_type == XINE_VISUAL_TYPE_X11 || this->visual_type == XINE_VISUAL_TYPE_X11_2) { this->drawable = (Drawable) data; @@ -1140,7 +1140,7 @@ static int directfb_gui_data_exchange (vo_driver_t *this_gen, case XINE_GUI_SEND_EXPOSE_EVENT: lprintf ("expose event.\n"); -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->visual_type == XINE_VISUAL_TYPE_X11 || this->visual_type == XINE_VISUAL_TYPE_X11_2) { if (this->xoverlay) { @@ -1182,7 +1182,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 HAVE_X11 +#ifdef DIRECTFB_X11 if (this->visual_type == XINE_VISUAL_TYPE_X11 || this->visual_type == XINE_VISUAL_TYPE_X11_2) { LOCK_DISPLAY(); @@ -1280,7 +1280,7 @@ static void update_config_cb (void *data, xine_cfg_entry_t *entry) { this->layer->SetDstColorKey (this->layer, (this->colorkey & 0xff0000) >> 16, (this->colorkey & 0x00ff00) >> 8, (this->colorkey & 0x0000ff) >> 0); -#ifdef HAVE_X11 +#ifdef DIRECTFB_X11 if (this->xoverlay) { x11osd_colorkey (this->xoverlay, directfb_colorkey_to_pixel(this), &this->sc); @@ -1893,6 +1893,7 @@ static void dispose_class_fb (video_driver_class_t *this_gen) { free (this); } +#ifndef DIRECTFB_X11 static void *init_class_fb (xine_t *xine, void *visual_gen) { directfb_class_t *this; const char *error; @@ -1925,7 +1926,7 @@ static const vo_info_t vo_info_directfb_fb = { /*** XDirectFB plugin functions ****/ -#ifdef HAVE_X11 +#else static vo_driver_t *open_plugin_x11 (video_driver_class_t *class_gen, const void *visual_gen) { directfb_class_t *class = (directfb_class_t *) class_gen; directfb_driver_t *this; @@ -2163,9 +2164,10 @@ static const vo_info_t vo_info_directfb_x11_2 = { const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ +#ifndef DIRECTFB_X11 { PLUGIN_VIDEO_OUT, VIDEO_OUT_DRIVER_IFACE_VERSION, "DirectFB", XINE_VERSION_CODE, &vo_info_directfb_fb, init_class_fb }, -#ifdef HAVE_X11 +#else { PLUGIN_VIDEO_OUT, VIDEO_OUT_DRIVER_IFACE_VERSION, "XDirectFB", XINE_VERSION_CODE, &vo_info_directfb_x11, init_class_x11 }, { PLUGIN_VIDEO_OUT, VIDEO_OUT_DRIVER_IFACE_VERSION, "XDirectFB", diff --git a/src/video_out/video_out_directfb_fb.c b/src/video_out/video_out_directfb_fb.c new file mode 100644 index 000000000..182a56941 --- /dev/null +++ b/src/video_out/video_out_directfb_fb.c @@ -0,0 +1,25 @@ +/* + * 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 + * 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 + * + * + * DirectFB output plugin (console version wrapper) + */ + +#undef DIRECTFB_X11 +#include "video_out_directfb.c" diff --git a/src/video_out/video_out_directfb_x.c b/src/video_out/video_out_directfb_x.c new file mode 100644 index 000000000..b3a1f53b7 --- /dev/null +++ b/src/video_out/video_out_directfb_x.c @@ -0,0 +1,25 @@ +/* + * 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 + * 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 + * + * + * DirectFB output plugin (X version wrapper) + */ + +#define DIRECTFB_X11 +#include "video_out_directfb.c" diff --git a/src/video_out/video_out_macosx.m b/src/video_out/video_out_macosx.m index 1a8fb821d..845bd9b94 100644 --- a/src/video_out/video_out_macosx.m +++ b/src/video_out/video_out_macosx.m @@ -170,7 +170,9 @@ static void macosx_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_fr } + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [this->view setVideoSize:video_size]; + [pool release]; if((format == XINE_IMGFMT_YV12 && (frame->vo_frame.base[0] == NULL @@ -189,29 +191,35 @@ static void macosx_update_frame_format(vo_driver_t *vo_driver, vo_frame_t *vo_fr static void macosx_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) { macosx_driver_t *driver = (macosx_driver_t *)vo_driver; macosx_frame_t *frame = (macosx_frame_t *)vo_frame; - char *texture_buffer = [driver->view getTextureBuffer]; - - switch (vo_frame->format) { - case XINE_IMGFMT_YV12: - yv12_to_yuy2 (vo_frame->base[0], vo_frame->pitches[0], - vo_frame->base[1], vo_frame->pitches[1], - vo_frame->base[2], vo_frame->pitches[2], - texture_buffer, vo_frame->width * 2, - vo_frame->width, vo_frame->height, 0); + char *texture_buffer; - [driver->view displayTexture]; - break; - case XINE_IMGFMT_YUY2: - xine_fast_memcpy (texture_buffer, vo_frame->base[0], - vo_frame->pitches[0] * vo_frame->height * 2); - [driver->view displayTexture]; - break; - default: - /* unsupported frame format, do nothing. */ - break; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + if ((texture_buffer = [driver->view textureBuffer]) != NULL) { + switch (vo_frame->format) { + case XINE_IMGFMT_YV12: + yv12_to_yuy2 (vo_frame->base[0], vo_frame->pitches[0], + vo_frame->base[1], vo_frame->pitches[1], + vo_frame->base[2], vo_frame->pitches[2], + (unsigned char *)texture_buffer, + vo_frame->width * 2, + vo_frame->width, vo_frame->height, 0); + + [driver->view updateTexture]; + break; + case XINE_IMGFMT_YUY2: + xine_fast_memcpy (texture_buffer, vo_frame->base[0], + vo_frame->pitches[0] * vo_frame->height * 2); + [driver->view updateTexture]; + break; + default: + /* unsupported frame format, do nothing. */ + break; + } } frame->vo_frame.free(&frame->vo_frame); + [pool release]; } static void macosx_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, @@ -228,11 +236,11 @@ static void macosx_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, if (frame->format == XINE_IMGFMT_YV12) /* TODO: It may be possible to accelerate the blending via Quartz * Extreme ... */ - 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 - 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); } @@ -299,6 +307,7 @@ static void macosx_dispose(vo_driver_t *vo_driver) { macosx_driver_t *this = (macosx_driver_t *) vo_driver; _x_alphablend_free(&this->alphablend_extra_data); + [this->view releaseInMainThread]; free(this); } @@ -318,7 +327,7 @@ static vo_driver_t *open_plugin(video_driver_class_t *driver_class, const void * driver->config = class->config; driver->xine = class->xine; driver->ratio = XINE_VO_ASPECT_AUTO; - driver->view = view; + driver->view = [view retain]; driver->vo_driver.get_capabilities = macosx_get_capabilities; driver->vo_driver.alloc_frame = macosx_alloc_frame; @@ -377,7 +386,7 @@ static const vo_info_t vo_info_macosx = { XINE_VISUAL_TYPE_MACOSX /* Visual type */ }; -plugin_info_t xine_plugin_info[] = { +plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ /* work around the problem that dlclose() is not allowed to * get rid of an image module which contains objective C code and simply diff --git a/src/video_out/video_out_xcbxv.c b/src/video_out/video_out_xcbxv.c index db4be14fa..432d93416 100644 --- a/src/video_out/video_out_xcbxv.c +++ b/src/video_out/video_out_xcbxv.c @@ -37,8 +37,6 @@ #include "config.h" #endif -#ifdef HAVE_XV - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -1618,5 +1616,3 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_VIDEO_OUT, 21, "xv", XINE_VERSION_CODE, &vo_info_xv, init_class }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; - -#endif diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index 55340a9e7..2cba3c2b6 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -36,8 +36,6 @@ #include "config.h" #endif -#ifdef HAVE_XV - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -1676,5 +1674,3 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_VIDEO_OUT, 21, "xv", XINE_VERSION_CODE, &vo_info_xv_2, init_class_2 }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; - -#endif diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c index 9947da365..25c223272 100644 --- a/src/xine-engine/alphablend.c +++ b/src/xine-engine/alphablend.c @@ -1052,8 +1052,7 @@ 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, int x_odd, +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; @@ -1062,46 +1061,38 @@ static void blend_yuv_exact(uint8_t *dst_cr, uint8_t *dst_cb, /* get opacity of the 4 pixels that share chroma */ int o00 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 0 ]; int o01 = (*blend_yuv_data)[ 0 ][ 0 ][ x + 1 ]; + int o = o00 + o01; int o10 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 0 ]; + o += o10; int o11 = (*blend_yuv_data)[ 0 ][ 1 ][ x + 1 ]; + o += o11; /* are there any pixels a little bit opaque? */ - if (o00 || o01 || o10 || o11) { + if (o) { /* get the chroma components of the 4 pixels */ - int cr00 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 0 ]; - int cr01 = -128 + (*blend_yuv_data)[ 1 ][ 0 ][ x + 1 ]; - int cr10 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 0 ]; - int cr11 = -128 + (*blend_yuv_data)[ 1 ][ 1 ][ x + 1 ]; + int cr00 = (*blend_yuv_data)[ 1 ][ 0 ][ x + 0 ]; + 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 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 0 ]; - int cb01 = -128 + (*blend_yuv_data)[ 2 ][ 0 ][ x + 1 ]; - int cb10 = -128 + (*blend_yuv_data)[ 2 ][ 1 ][ x + 0 ]; - int cb11 = -128 + (*blend_yuv_data)[ 2 ][ 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 ]; + int cb11 = (*blend_yuv_data)[ 2 ][ 1 ][ x + 1 ]; /* are all pixels completely opaque? */ - if (o00 >= 0xf && o01 >= 0xf && o10 >= 0xf && o11 >= 0xf) { + if (o >= 4*0xf) { /* set the output chroma to the average of the four pixels */ - *dst_cr = 128 + (cr00 + cr01 + cr10 + cr11) / 4; - *dst_cb = 128 + (cb00 + cb01 + cb10 + cb11) / 4; + *dst_cr = (cr00 + cr01 + cr10 + cr11) / 4; + *dst_cb = (cb00 + cb01 + cb10 + cb11) / 4; } else { - int t4, cr, cb; - - /* blending required, so clamp opacity values to allowed range */ - if (o00 > 0xf) o00 = 0xf; - if (o01 > 0xf) o01 = 0xf; - if (o10 > 0xf) o10 = 0xf; - if (o11 > 0xf) o11 = 0xf; - /* calculate transparency of background over the four pixels */ - t4 = (0xf - o00) + (0xf - o01) + (0xf - o10) + (0xf - o11); - - /* get background chroma */ - cr = -128 + *dst_cr; - cb = -128 + *dst_cb; + int t4 = 4*0xf - o; /* blend the output chroma to the average of the four pixels */ - *dst_cr = 128 + (cr * t4 + cr00 * o00 + cr01 * o01 + cr10 * o10 + cr11 * o11) / (4 * 0xf); - *dst_cb = 128 + (cb * t4 + cb00 * o00 + cb01 * o01 + cb10 * o10 + cb11 * o11) / (4 * 0xf); + /* for explanation of the used equation, see blend_yuy2_exact() */ + *dst_cr = ((*dst_cr * t4 + cr00 * o00 + cr01 * o01 + cr10 * o10 + cr11 * o11) * (0x1111+1)) >> 18; + *dst_cb = ((*dst_cb * t4 + cb00 * o00 + cb01 * o01 + cb10 * o10 + cb11 * o11) * (0x1111+1)) >> 18; } } @@ -1440,7 +1431,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } - blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data); + blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, blend_yuv_data); any_line_buffered = 0; } @@ -1461,7 +1452,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, memset(&(*blend_yuv_data)[ 0 ][ 1 ][ 0 ], 0, exact_blend_width_m2); } - blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, x_odd, blend_yuv_data); + blend_yuv_exact(dst_cr, dst_cb, exact_blend_width, blend_yuv_data); } } @@ -1470,8 +1461,7 @@ void _x_blend_yuv (uint8_t *dst_base[3], vo_overlay_t * img_overl, #endif } -static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, - int src_width, int x_odd, +static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, int src_width, uint8_t *(*blend_yuy2_data)[ 3 ]) { int x; @@ -1480,38 +1470,71 @@ static void blend_yuy2_exact(uint8_t *dst_cr, uint8_t *dst_cb, /* get opacity of the 2 pixels that share chroma */ int o0 = (*blend_yuy2_data)[ 0 ][ x + 0 ]; int o1 = (*blend_yuy2_data)[ 0 ][ x + 1 ]; + int o = o0 + o1; /* are there any pixels a little bit opaque? */ - if (o0 || o1) { + if (o) { /* get the chroma components of the 2 pixels */ - int cr0 = -128 + (*blend_yuy2_data)[ 1 ][ x + 0 ]; - int cr1 = -128 + (*blend_yuy2_data)[ 1 ][ x + 1 ]; + int cr0 = (*blend_yuy2_data)[ 1 ][ x + 0 ]; + int cr1 = (*blend_yuy2_data)[ 1 ][ x + 1 ]; - int cb0 = -128 + (*blend_yuy2_data)[ 2 ][ x + 0 ]; - int cb1 = -128 + (*blend_yuy2_data)[ 2 ][ x + 1 ]; + int cb0 = (*blend_yuy2_data)[ 2 ][ x + 0 ]; + int cb1 = (*blend_yuy2_data)[ 2 ][ x + 1 ]; /* are all pixels completely opaque? */ - if (o0 >= 0xf && o1 >= 0xf) { + if (o >= 2*0xf) { /* set the output chroma to the average of the two pixels */ - *dst_cr = 128 + (cr0 + cr1) / 2; - *dst_cb = 128 + (cb0 + cb1) / 2; + *dst_cr = (cr0 + cr1) / 2; + *dst_cb = (cb0 + cb1) / 2; } else { - int t2, cr, cb; - - /* blending required, so clamp opacity values to allowed range */ - if (o0 > 0xf) o0 = 0xf; - if (o1 > 0xf) o1 = 0xf; - /* calculate transparency of background over the two pixels */ - t2 = (0xf - o0) + (0xf - o1); - - /* get background chroma */ - cr = -128 + *dst_cr; - cb = -128 + *dst_cb; + int t2 = 2*0xf - o; + + /* + * No need to adjust chroma values with +/- 128: + * *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); + * = 128 + (*dst_cb * t2 + cb0 * o0 + cb1 * o1 + (2*0xf*(-128))) / (2 * 0xf); + * = 128 + (*dst_cb * t2 + cb0 * o0 + cb1 * o1) / (2 * 0xf) - 128; + * = (*dst_cb * t2 + cb0 * o0 + cb1 * o1) / (2 * 0xf); + * + * Convert slow divisions to multiplication and shift: + * X/0xf + * = X * (1/0xf) + * = X * (0x1111/0x1111) * (1/0xf) + * = X * 0x1111/0xffff + * =(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 + * range of [0 ... 0xff*0xf*4]. This results in error of + * X*0x1112/0x10000 - X/0xf + * = X*(0x1112/0x10000 - 1/0xf) + * = X*(0x0.1112 - 0x0.111111...) + * = X*0.0000eeeeee.... + * = [0 ... 0.37c803fc...] when X in [0...3bc4] + * 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 + * 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). + * + * 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 + */ /* blend the output chroma to the average of the two pixels */ - *dst_cr = 128 + (cr * t2 + cr0 * o0 + cr1 * o1) / (2 * 0xf); - *dst_cb = 128 + (cb * t2 + cb0 * o0 + cb1 * o1) / (2 * 0xf); + /* *dst_cr = 128 + ((*dst_cr-128) * t2 + (cr0-128) * o0 + (cr1-128) * o1) / (2 * 0xf); */ + *dst_cr = ((*dst_cr * t2 + cr0 * o0 + cr1 * o1) * (0x1111+1)) >> 17; + *dst_cb = ((*dst_cb * t2 + cb0 * o0 + cb1 * o1) * (0x1111+1)) >> 17; } } @@ -1855,7 +1878,7 @@ void _x_blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, 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, x_odd, blend_yuy2_data); + 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; } diff --git a/src/xine-engine/input_cache.c b/src/xine-engine/input_cache.c index a566e1f84..75c4beb43 100644 --- a/src/xine-engine/input_cache.c +++ b/src/xine-engine/input_cache.c @@ -74,7 +74,11 @@ static off_t cache_plugin_read(input_plugin_t *this_gen, char *buf, off_t len) { if (len <= (this->buf_len - this->buf_pos)) { /* all bytes are in the buffer */ switch (len) { -#if !(defined(sparc) || defined(__sparc__) || defined __ia64__) +#if defined(__i386__) || defined(__x86_64__) + /* These are restricted to x86 and amd64. Some other architectures don't + * handle unaligned accesses in the same way, quite possibly requiring + * extra code over and above simple byte copies. + */ case 8: *((uint64_t *)buf) = *(uint64_t *)(&(this->buf[this->buf_pos])); break; diff --git a/src/xine-engine/io_helper.c b/src/xine-engine/io_helper.c index ad36c565e..67dddcfdc 100644 --- a/src/xine-engine/io_helper.c +++ b/src/xine-engine/io_helper.c @@ -276,7 +276,7 @@ int _x_io_select (xine_stream_t *stream, int fd, int state, int timeout_msec) { wset = (state & XIO_WRITE_READY) ? &fdset : NULL; ret = select (fd + 1, rset, wset, NULL, &select_timeout); - if (ret == -1) { + if (ret == -1 && errno != EINTR) { /* select error */ return XIO_ERROR; } else if (ret == 1) { diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 7b42c43ed..085752dd8 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -255,6 +255,8 @@ struct xine_video_port_s { the palette. This should probably be classified as a bug. */ #define OVL_PALETTE_SIZE 256 +#define OVL_MAX_OPACITY 0x0f + /* number of recent frames to keep in memory these frames are needed by some deinterlace algorithms FIXME: we need a method to flush the recent frames (new stream) diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index 7bd9292c8..231aa5a70 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -288,10 +288,18 @@ static int32_t video_overlay_add_event(video_overlay_manager_t *this_gen, void } if( event->object.overlay ) { + int i; + for(i = 0; i < OVL_PALETTE_SIZE; i++) { + if(event->object.overlay->trans[i] >= OVL_MAX_OPACITY) + event->object.overlay->trans[i] = OVL_MAX_OPACITY; + if(event->object.overlay->hili_trans[i] >= OVL_MAX_OPACITY) + 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, event->object.overlay, sizeof(vo_overlay_t)); - + /* We took the callers rle and data, therefore it will be our job to free it */ /* clear callers overlay so it will not be freed twice */ memset(event->object.overlay,0,sizeof(vo_overlay_t)); diff --git a/src/xine-utils/attributes.h b/src/xine-utils/attributes.h index b533286c8..13c787925 100644 --- a/src/xine-utils/attributes.h +++ b/src/xine-utils/attributes.h @@ -1,8 +1,10 @@ /* * attributes.h * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> + * Copyright (C) 2001-2007 xine developers * - * This file is part of mpeg2dec, a free MPEG-2 video stream decoder. + * This file was originally part of mpeg2dec, a free MPEG-2 video stream + * decoder. * * mpeg2dec is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/xine-utils/xmllexer.c b/src/xine-utils/xmllexer.c index 575c37611..754a006f9 100644 --- a/src/xine-utils/xmllexer.c +++ b/src/xine-utils/xmllexer.c @@ -120,6 +120,10 @@ int lexer_get_token(char * tok, int tok_size) { state = 7; break; + case '\'': /* " */ + state = 12; + break; + case '-': state = 10; tok[tok_pos] = c; @@ -322,6 +326,17 @@ int lexer_get_token(char * tok, int tok_size) { } break; + /* T_STRING (single quotes) */ + case 12: + tok[tok_pos] = c; + lexbuf_pos++; + if (c == '\'') { /* " */ + tok[tok_pos] = '\0'; /* FIXME */ + return T_STRING; + } + tok_pos++; + break; + /* IDENT */ case 100: switch (c) { diff --git a/src/xine-utils/xmlparser.c b/src/xine-utils/xmlparser.c index 47096705a..363c6381f 100644 --- a/src/xine-utils/xmlparser.c +++ b/src/xine-utils/xmlparser.c @@ -413,7 +413,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r } break; - /* > expected */ + /* ?> expected */ case 8: switch (res) { case (T_TI_STOP): @@ -425,7 +425,7 @@ static int xml_parser_get_node (xml_node_t *current_node, char *root_name, int r } break; - /* ?> expected */ + /* > expected */ case 9: switch (res) { case (T_M_STOP_1): |