From 2e93d91c6c5caa3732f0a3e5f6713b3882e74578 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 26 Jan 2010 02:52:12 +0000 Subject: More error checking. --- src/input/input_v4l2.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 69d0a3b75..903293057 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -91,19 +91,25 @@ typedef struct { v4l2_radio_t* radio; } v4l2_input_plugin_t; -static void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx); +static int v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx); static int v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *input); static int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this); static int v4l2_input_open(input_plugin_t *this_gen) { v4l2_input_plugin_t *this = (v4l2_input_plugin_t*) this_gen; + int ret; lprintf("Opening %s\n", this->mrl); this->fd = v4l2_open(this->mrl, O_RDWR); if (this->fd) { /* TODO: Clean up this mess */ this->events = xine_event_new_queue(this->stream); - v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); + ret = v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); + if (ret < 0) + { + lprintf ("Capability query failed: %s\n", strerror (-ret)); + return 0; + } if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { this->video = malloc(sizeof(v4l2_video_t)); this->video->headerSent = 0; @@ -180,7 +186,8 @@ static int v4l2_input_setup_video_streaming(v4l2_input_plugin_t *this) { this->video->bufcount = 0; return 0; } - v4l2_input_enqueue_video_buffer(this, i); + if (v4l2_input_enqueue_video_buffer(this, i) < 0) + goto fail; } struct v4l2_format fmt; @@ -232,6 +239,11 @@ static buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffe lprintf("Sending video frame (sent %d of %d)\n", this->video->index, this->video->buffers[this->video->inbuf.index].length); /* TODO: Add audio support */ this->video->headerSent = v4l2_input_dequeue_video_buffer(this, buf); + if (this->video->headerSent < 0) + { + buf->free_buffer (buf); + buf = NULL; + } } return buf; } @@ -251,12 +263,16 @@ static uint32_t v4l2_input_blocksize(input_plugin_t *this_gen) { static int v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_element_t *output) { + int ret; + if (!this->video->index) { memset (&this->video->inbuf, 0, sizeof (this->video->inbuf)); this->video->inbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; this->video->inbuf.memory = V4L2_MEMORY_MMAP; - v4l2_ioctl(this->fd, VIDIOC_DQBUF, &this->video->inbuf); + ret = v4l2_ioctl(this->fd, VIDIOC_DQBUF, &this->video->inbuf); + if (ret < 0) + return -1; /* failure */ output->decoder_flags = BUF_FLAG_FRAME_START; } else @@ -275,20 +291,20 @@ static int v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_elemen if (this->video->index == this->video->buffers[this->video->inbuf.index].length) { output->decoder_flags |= BUF_FLAG_FRAME_END; - v4l2_input_enqueue_video_buffer(this, this->video->inbuf.index); - return 0; + ret = v4l2_input_enqueue_video_buffer(this, this->video->inbuf.index); + return -(ret < 0); } return 1; } -static void v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { +static int v4l2_input_enqueue_video_buffer(v4l2_input_plugin_t *this, int idx) { struct v4l2_buffer buf; memset(&buf, 0, sizeof(buf)); buf.index = idx; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf.memory = V4L2_MEMORY_MMAP; - v4l2_ioctl(this->fd, VIDIOC_QBUF, &buf); + return v4l2_ioctl(this->fd, VIDIOC_QBUF, &buf); } static void v4l2_input_dispose(input_plugin_t *this_gen) { -- cgit v1.2.3 From 17c42f308cccdffa51939504b39c167f0fe37aa4 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 26 Jan 2010 02:52:28 +0000 Subject: Get rid of a few compiler warnings. --- src/input/input_v4l2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 903293057..88156d405 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -236,7 +236,7 @@ static buf_element_t* v4l2_input_read_block(input_plugin_t *this_gen, fifo_buffe this->video->index = 0; buf->type = BUF_VIDEO_YUY2; } else { - lprintf("Sending video frame (sent %d of %d)\n", this->video->index, this->video->buffers[this->video->inbuf.index].length); + lprintf("Sending video frame (sent %zd of %zd)\n", this->video->index, this->video->buffers[this->video->inbuf.index].length); /* TODO: Add audio support */ this->video->headerSent = v4l2_input_dequeue_video_buffer(this, buf); if (this->video->headerSent < 0) @@ -285,7 +285,7 @@ static int v4l2_input_dequeue_video_buffer(v4l2_input_plugin_t *this, buf_elemen if (output->size > output->max_size) output->size = output->max_size; - xine_fast_memcpy (output->content, this->video->buffers[this->video->inbuf.index].start + this->video->index, output->size); + xine_fast_memcpy (output->content, (char *)this->video->buffers[this->video->inbuf.index].start + this->video->index, output->size); this->video->index += output->size; if (this->video->index == this->video->buffers[this->video->inbuf.index].length) -- cgit v1.2.3 From 2f582c13386aeb7132c64851233245db4994c63d Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 26 Jan 2010 03:05:00 +0000 Subject: Switch off logging, convert some lprintf() to xine_log(), add a startup warning. --- src/input/input_v4l2.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index 88156d405..fb27db5dc 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -26,9 +26,9 @@ #ifdef HAVE_CONFIG_H #include "config.h" #endif - +/* #define LOG - +*/ #include "input_plugin.h" #include "xine_plugin.h" #include "xine_internal.h" @@ -107,7 +107,8 @@ static int v4l2_input_open(input_plugin_t *this_gen) { ret = v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); if (ret < 0) { - lprintf ("Capability query failed: %s\n", strerror (-ret)); + xine_log (this->stream->xine, XINE_LOG_MSG, + LOG_MODULE": %s: %s\n", _("capability query failed"), strerror (-ret)); return 0; } if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { @@ -123,16 +124,19 @@ static int v4l2_input_open(input_plugin_t *this_gen) { return 1; } else { /* TODO: Fallbacks */ - lprintf("Video streaming setup failed.\n"); + xine_log (this->stream->xine, XINE_LOG_MSG, + LOG_MODULE": %s\n", _("video streaming setup failed")); return 0; } } else { /* TODO: Radio streaming */ - lprintf("Sorry, only video is supported for now.\n"); + xine_log (this->stream->xine, XINE_LOG_MSG, + LOG_MODULE": %s\n", _("sorry, only video is supported for now")); return 0; } } else { - lprintf("Device doesn't support streaming. Prod the author to support the other methods.\n"); + xine_log (this->stream->xine, XINE_LOG_MSG, + LOG_MODULE": %s\n", _("device doesn't support streaming - prod the author to support the other methods")); return 0; } } else { @@ -414,6 +418,9 @@ static input_plugin_t *v4l2_class_get_instance(input_class_t *gen_cls, xine_stre this->radio = NULL; lprintf("Ready to read!\n"); + xine_log (this->stream->xine, XINE_LOG_MSG, + LOG_MODULE": %s\n", _("WARNING: this plugin is not of release quality")); + return &this->input_plugin; } -- cgit v1.2.3 From 392689a404398eb48005f519b187341fd1f91dec Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 26 Jan 2010 21:55:45 +0000 Subject: =?UTF-8?q?Convert=20xine=5Flog=20=E2=86=92=20xprintf.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/input/input_v4l2.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c index fb27db5dc..255b1f17c 100644 --- a/src/input/input_v4l2.c +++ b/src/input/input_v4l2.c @@ -107,8 +107,8 @@ static int v4l2_input_open(input_plugin_t *this_gen) { ret = v4l2_ioctl(this->fd, VIDIOC_QUERYCAP, &(this->cap)); if (ret < 0) { - xine_log (this->stream->xine, XINE_LOG_MSG, - LOG_MODULE": %s: %s\n", _("capability query failed"), strerror (-ret)); + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE": capability query failed: %s\n", strerror (-ret)); return 0; } if (this->cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) { @@ -124,19 +124,19 @@ static int v4l2_input_open(input_plugin_t *this_gen) { return 1; } else { /* TODO: Fallbacks */ - xine_log (this->stream->xine, XINE_LOG_MSG, - LOG_MODULE": %s\n", _("video streaming setup failed")); + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE": video streaming setup failed\n"); return 0; } } else { /* TODO: Radio streaming */ - xine_log (this->stream->xine, XINE_LOG_MSG, - LOG_MODULE": %s\n", _("sorry, only video is supported for now")); + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE": sorry, only video is supported for now\n"); return 0; } } else { - xine_log (this->stream->xine, XINE_LOG_MSG, - LOG_MODULE": %s\n", _("device doesn't support streaming - prod the author to support the other methods")); + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + LOG_MODULE": device doesn't support streaming - prod the author to support the other methods\n"); return 0; } } else { @@ -418,8 +418,8 @@ static input_plugin_t *v4l2_class_get_instance(input_class_t *gen_cls, xine_stre this->radio = NULL; lprintf("Ready to read!\n"); - xine_log (this->stream->xine, XINE_LOG_MSG, - LOG_MODULE": %s\n", _("WARNING: this plugin is not of release quality")); + xprintf (this->stream->xine, XINE_VERBOSITY_NONE, + LOG_MODULE": WARNING: this plugin is not of release quality\n"); return &this->input_plugin; } -- cgit v1.2.3 From 4e0e3ada7f88ff9cdbcd031e838f9a8445f09a9e Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 28 Jan 2010 00:48:33 +0000 Subject: Clean up and extend DVB subtitle decoding. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decoding fixed (nybble extraction was broken, and some filling was wrong). Default colour tables added. The following is untested: * Support for 2-bit and 8-bit images. * Support for expansion from 2→4, 2→8 and 4→8 bits. * Support for expansion tables. * Handling of stuffing chunks (not expected to be seen). * Copying of the top field into the bottom field. --- ChangeLog | 1 + src/spu_dec/spudvb_decoder.c | 395 +++++++++++++++++++++++++++++++------------ 2 files changed, 289 insertions(+), 107 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3ad813221..e01584f5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -41,6 +41,7 @@ xine-lib (1.1.90) (Unreleased) * The XML parser handles CDATA elements. * Text handling within XML is improved. * DVB subtitles' opacity is now controllable. + * Extend DVB subtitling capabilities. (Still bitmap-only.) * The internal copies of libcdio and libvcd are no longer present, you need to use an installed copy of them if you want VCD support. * Replace get_* functions for literals with direct string access. diff --git a/src/spu_dec/spudvb_decoder.c b/src/spu_dec/spudvb_decoder.c index 4b6032a5c..149917ad5 100644 --- a/src/spu_dec/spudvb_decoder.c +++ b/src/spu_dec/spudvb_decoder.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 the xine project + * Copyright (C) 2010 the xine project * * This file is part of xine, a free video player. * @@ -72,12 +72,14 @@ typedef struct { unsigned int curr_reg[64]; uint8_t *buf; int i; - int nibble_flag; + int i_bits; int in_scanline; + int compat_depth; page_t page; region_t regions[MAX_REGIONS]; clut_t colours[MAX_REGIONS*256]; unsigned char trans[MAX_REGIONS*256]; + unsigned char lut24[4], lut28[4], lut48[16]; } dvbsub_func_t; typedef struct dvb_spu_class_s { @@ -112,6 +114,9 @@ typedef struct dvb_spu_decoder_s { int show; } dvb_spu_decoder_t; +static clut_t default_clut[256]; +static unsigned char default_trans[256]; +static int default_colours_init = 0; static void update_osd(dvb_spu_decoder_t *this, int region_id) { @@ -210,106 +215,221 @@ 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 const uint8_t *lookup_lut (const dvbsub_func_t *dvbsub) +{ + static const uint8_t identity_lut[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + + switch (dvbsub->compat_depth) + { + case 012: return dvbsub->lut24; + case 013: return dvbsub->lut28; + case 023: return dvbsub->lut48; + default: return identity_lut; + } +} + +static unsigned char next_datum (dvb_spu_decoder_t * this, int width) { - unsigned char x; dvbsub_func_t *dvbsub = this->dvbsub; + unsigned char x = 0; - if (dvbsub->nibble_flag == 0) { - x = (dvbsub->buf[dvbsub->i] & 0xf0) >> 4; - dvbsub->nibble_flag = 1; + if (!dvbsub->i_bits) + dvbsub->i_bits = 8; + + if (dvbsub->i_bits < width) + { + /* need to read from more than one byte; split it up */ + width -= dvbsub->i_bits; + x = dvbsub->buf[dvbsub->i++] & ((1 << dvbsub->i_bits) - 1); + dvbsub->i_bits = 8; + return x << width | next_datum (this, width); } - else { - x = (dvbsub->buf[dvbsub->i++] & 0x0f); - dvbsub->nibble_flag = 0; + + dvbsub->i_bits = (dvbsub->i_bits - width) & 7; + x = (dvbsub->buf[dvbsub->i] >> dvbsub->i_bits) & ((1 << width) - 1); + + if (!dvbsub->i_bits) + ++dvbsub->i; + + return x; +} + +static void decode_2bit_pixel_code_string (dvb_spu_decoder_t * this, int r, int object_id, int ofs, int n) +{ + dvbsub_func_t *dvbsub = this->dvbsub; + int j; + const uint8_t *lut = lookup_lut (dvbsub); + + if (dvbsub->in_scanline == 0) + dvbsub->in_scanline = 1; + + dvbsub->i_bits = 0; + j = dvbsub->i + n; + + while (dvbsub->i < j) + { + int next_bits = next_datum (this, 2); + int run_length; + + if (next_bits) + { + /* single pixel */ + plot (this, r, 1, lut[next_bits]); + continue; + } + + /* switch 1 */ + if (next_datum (this, 1) == 0) + { + /* run length, 3 to 10 pixels, colour given */ + run_length = next_datum (this, 3); + plot (this, r, run_length + 3, lut[next_datum (this, 2)]); + continue; + } + + /* switch 2 */ + if (next_datum (this, 1) == 1) + { + /* single pixel, colour 0 */ + plot (this, r, 1, lut[0]); + continue; + } + + /* switch 3 */ + switch (next_datum (this, 2)) + { + case 0: /* end-of-string */ + j = dvbsub->i; /* set the while cause FALSE */ + break; + case 1: /* two pixels, colour 0 */ + plot (this, r, 2, lut[0]); + break; + case 2: /* run length, 12 to 27 pixels (4-bit), colour given */ + run_length = next_datum (this, 4); + plot (this, r, run_length + 12, lut[next_datum (this, 2)]); + break; + case 3: /* run length, 29 to 284 pixels (8-bit), colour given */ + run_length = next_datum (this, 8); + plot (this, r, run_length + 29, lut[next_datum (this, 2)]); + } + } + + if (dvbsub->i_bits) { + dvbsub->i++; + dvbsub->i_bits = 0; } - return (x); } 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; + const uint8_t *lut = lookup_lut (dvbsub); - if (dvbsub->in_scanline == 0) { + if (dvbsub->in_scanline == 0) dvbsub->in_scanline = 1; - } - dvbsub->nibble_flag = 0; + + dvbsub->i_bits = 0; j = dvbsub->i + n; - while (dvbsub->i < j) { - bits = 0; - pixel_code = 0; - next_bits = next_nibble (this); + while (dvbsub->i < j) + { + int next_bits = next_datum (this, 4); + int run_length; - if (next_bits != 0) { - pixel_code = next_bits; - plot (this, r, 1, pixel_code); - bits += 4; + if (next_bits) + { + /* single pixel */ + plot (this, r, 1, lut[next_bits]); + continue; } - else { - bits += 4; - data = next_nibble (this); - switch_1 = (data & 0x08) >> 3; - bits++; - if (switch_1 == 0) { - run_length = (data & 0x07); - bits += 3; - if (run_length != 0) { - plot (this, r, run_length + 2, pixel_code); - } - else { - break; - } - } - else { - switch_2 = (data & 0x04) >> 2; - bits++; - if (switch_2 == 0) { - run_length = (data & 0x03); - bits += 2; - pixel_code = next_nibble (this); - bits += 4; - plot (this, r, run_length + 4, pixel_code); - } - else { - switch_3 = (data & 0x03); - bits += 2; - switch (switch_3) { - case 0: - plot (this, r, 1, pixel_code); - break; - case 1: - plot (this, r, 2, pixel_code); - 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); - 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); - } - } - } + + /* switch 1 */ + if (next_datum (this, 1) == 0) + { + run_length = next_datum (this, 3); + if (!run_length) + /* end-of-string */ + break; + + /* run length, 3 to 9 pixels, colour 0 */ + plot (this, r, run_length + 2, lut[0]); + continue; } + /* switch 2 */ + if (next_datum (this, 1) == 0) + { + /* run length, 4 to 7 pixels, colour given */ + run_length = next_datum (this, 2); + plot (this, r, run_length + 4, lut[next_datum (this, 4)]); + continue; + } + + /* switch 3 */ + switch (next_datum (this, 2)) + { + case 0: /* single pixel, colour 0 */ + plot (this, r, 1, lut[0]); + break; + case 1: /* two pixels, colour 0 */ + plot (this, r, 2, lut[0]); + break; + case 2: /* run length, 9 to 24 pixels (4-bit), colour given */ + run_length = next_datum (this, 4); + plot (this, r, run_length + 9, lut[next_datum (this, 4)]); + break; + case 3: /* run length, 25 to 280 pixels (8-bit), colour given */ + run_length = next_datum (this, 8); + plot (this, r, run_length + 25, lut[next_datum (this, 4)]); + } } - if (dvbsub->nibble_flag == 1) { + + if (dvbsub->i_bits) { dvbsub->i++; - dvbsub->nibble_flag = 0; + dvbsub->i_bits = 0; + } +} + +static void decode_8bit_pixel_code_string (dvb_spu_decoder_t * this, int r, int object_id, int ofs, int n) +{ + dvbsub_func_t *dvbsub = this->dvbsub; + int j; + + if (dvbsub->in_scanline == 0) + dvbsub->in_scanline = 1; + + j = dvbsub->i + n; + + while (dvbsub->i < j) + { + int next_bits = dvbsub->buf[dvbsub->i++]; + int run_length; + + if (next_bits) + { + /* single pixel */ + plot (this, r, 1, next_bits); + continue; + } + + /* switch 1 */ + run_length = dvbsub->buf[dvbsub->i] & 127; + + if (dvbsub->buf[dvbsub->i++] & 128) + { + /* run length, 3 to 127 pixels, colour given */ + if (run_length > 2) + plot (this, r, run_length + 4, dvbsub->buf[dvbsub->i++]); + continue; + } + + if (!run_length) + /* end-of-string */ + break; + + /* run length, 1 to 127 pixels, colour 0 */ + plot (this, r, run_length + 2, 0); } } @@ -415,9 +535,31 @@ static void process_pixel_data_sub_block (dvb_spu_decoder_t * this, int r, int o switch (data_type) { case 0: dvbsub->i++; + case 0x10: + decode_2bit_pixel_code_string (this, r, o, ofs, n - 1); + break; case 0x11: decode_4bit_pixel_code_string (this, r, o, ofs, n - 1); break; + case 0x12: + decode_8bit_pixel_code_string (this, r, o, ofs, n - 1); + break; + case 0x20: /* 2-to-4bit colour index map */ + /* should this be implemented since we have an 8-bit overlay? */ + dvbsub->lut24[0] = dvbsub->buf[dvbsub->i ] >> 4; + dvbsub->lut24[1] = dvbsub->buf[dvbsub->i ] & 0x0f; + dvbsub->lut24[2] = dvbsub->buf[dvbsub->i + 1] >> 4; + dvbsub->lut24[3] = dvbsub->buf[dvbsub->i + 1] & 0x0f; + dvbsub->i += 2; + break; + case 0x21: /* 2-to-8bit colour index map */ + memcpy (dvbsub->lut28, dvbsub->buf + dvbsub->i, 4); + dvbsub->i += 4; + break; + case 0x22: + memcpy (dvbsub->lut48, dvbsub->buf + dvbsub->i, 16); + dvbsub->i += 16; + break; case 0xf0: dvbsub->in_scanline = 0; dvbsub->x = (dvbsub->regions[r].object_pos[o]) >> 16; @@ -502,6 +644,7 @@ static void process_region_composition_segment (dvb_spu_decoder_t * this) dvbsub->i += 2; region_level_of_compatibility = (dvbsub->buf[dvbsub->i] & 0xe0) >> 5; region_depth = (dvbsub->buf[dvbsub->i] & 0x1c) >> 2; + dvbsub->compat_depth = region_level_of_compatibility << 3 | region_depth; dvbsub->i++; CLUT_id = dvbsub->buf[dvbsub->i++]; region_8_bit_pixel_code = dvbsub->buf[dvbsub->i++]; @@ -589,6 +732,13 @@ static void process_object_data_segment (dvb_spu_decoder_t * this) process_pixel_data_sub_block (this, r, object_id, 0, top_field_data_block_length); + if (bottom_field_data_block_length == 0) + { + /* handle bottom field == top field */ + bottom_field_data_block_length = top_field_data_block_length; + dvbsub->i = old_i + 4; + } + process_pixel_data_sub_block (this, r, object_id, 1, bottom_field_data_block_length); } } @@ -596,6 +746,11 @@ static void process_object_data_segment (dvb_spu_decoder_t * this) } } +static void process_display_definition_segment(dvb_spu_decoder_t *this) +{ + /* FIXME: not implemented. */ +} + static void unlock_mutex_cancellation_func(void *mutex_gen) { pthread_mutex_t *mutex = (pthread_mutex_t*) mutex_gen; @@ -804,6 +959,25 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) /* completely ignore pts since it makes a lot of problems with various providers */ this->vpts = 0; + /* Reset the colour LUTs */ + for (i = 0; i < MAX_REGIONS; ++i) + { + memcpy (this->dvbsub->colours + i * 256, default_clut, sizeof (default_clut)); + memcpy (this->dvbsub->trans + i * 256, default_trans, sizeof (default_trans)); + } + + /* Reset the colour index LUTs */ + this->dvbsub->lut24[0] = 0x0; + this->dvbsub->lut24[1] = 0x7; + this->dvbsub->lut24[2] = 0x8; + this->dvbsub->lut24[3] = 0xF; + this->dvbsub->lut28[0] = 0x00; + this->dvbsub->lut28[1] = 0x77; + this->dvbsub->lut28[2] = 0x88; + this->dvbsub->lut28[3] = 0xFF; + for (i = 0; i < 16; ++i) + this->dvbsub->lut48[i] = i | i << 4; + /* process the pes section */ PES_packet_length = this->pes_pkt_size; @@ -843,10 +1017,15 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) case 0x13: process_object_data_segment (this); break; + case 0x14: + process_display_definition_segment(this); + break; case 0x80: /* Page is now completely rendered */ recalculate_trans(this); draw_subtitles( this ); break; + case 0xFF: /* stuffing */ + break; default: return; break; @@ -854,32 +1033,6 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) } this->dvbsub->i = new_i; } - - /* 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) @@ -940,6 +1093,34 @@ static spu_decoder_t *dvb_spu_class_open_plugin (spu_decoder_class_t * class_gen dvb_spu_decoder_t *this = calloc(1, sizeof (dvb_spu_decoder_t)); dvb_spu_class_t *class = (dvb_spu_class_t *)class_gen; +#define YUVA(r, g, b, a) (clut_t) { COMPUTE_V(r, g, b), COMPUTE_U(r, g, b), COMPUTE_V(r, g, b), a } +#define GETBIT(s, v1, v2, tr) \ + r = s + ((i & 1) ? v1 : 0) + ((i & 0x10) ? v2 : 0); \ + g = s + ((i & 2) ? v1 : 0) + ((i & 0x20) ? v2 : 0); \ + b = s + ((i & 4) ? v1 : 0) + ((i & 0x40) ? v2 : 0); \ + a = tr + + if (!default_colours_init) + { + int i; + default_clut[0] = YUVA(0, 0, 0, 0); + for (i = 1; i < 256; i++) { + uint8_t r, g, b, a; + if (i < 8) { + GETBIT(0, 255, 0, 63); + } else switch (i & 0x88) { + case 0x00: GETBIT( 0, 85, 170, 255); break; + case 0x08: GETBIT( 0, 85, 170, 127); break; + case 0x80: GETBIT(127, 43, 85, 255); break; + default : GETBIT( 0, 43, 85, 255); break; + } + default_trans[i] = a; + default_clut[i] = YUVA(r, g, b, a); + } + default_colours_init = 1; + } + + this->spu_decoder.decode_data = spudec_decode_data; this->spu_decoder.reset = spudec_reset; this->spu_decoder.discontinuity = spudec_discontinuity; -- cgit v1.2.3 From b27fec744ea66cb04bcc0c44ebc270575ed07e03 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 28 Jan 2010 02:29:48 +0000 Subject: Make the index LUTs per-region; put the colour reset code in its own function. --- src/spu_dec/spudvb_decoder.c | 78 +++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/spu_dec/spudvb_decoder.c b/src/spu_dec/spudvb_decoder.c index 149917ad5..197b1cd49 100644 --- a/src/spu_dec/spudvb_decoder.c +++ b/src/spu_dec/spudvb_decoder.c @@ -79,7 +79,9 @@ typedef struct { region_t regions[MAX_REGIONS]; clut_t colours[MAX_REGIONS*256]; unsigned char trans[MAX_REGIONS*256]; - unsigned char lut24[4], lut28[4], lut48[16]; + struct { + unsigned char lut24[4], lut28[4], lut48[16]; + } lut[MAX_REGIONS]; } dvbsub_func_t; typedef struct dvb_spu_class_s { @@ -118,6 +120,33 @@ static clut_t default_clut[256]; static unsigned char default_trans[256]; static int default_colours_init = 0; +static void reset_clut (dvbsub_func_t *dvbsub) +{ + int i, r; + + /* Reset the colour LUTs */ + for (r = 0; r < MAX_REGIONS; ++r) + { + memcpy (dvbsub->colours + r * 256, default_clut, sizeof (default_clut)); + memcpy (dvbsub->trans + r * 256, default_trans, sizeof (default_trans)); + } + + /* Reset the colour index LUTs */ + for (r = 0; r < MAX_REGIONS; ++r) + { + dvbsub->lut[r].lut24[0] = 0x0; + dvbsub->lut[r].lut24[1] = 0x7; + dvbsub->lut[r].lut24[2] = 0x8; + dvbsub->lut[r].lut24[3] = 0xF; + dvbsub->lut[r].lut28[0] = 0x00; + dvbsub->lut[r].lut28[1] = 0x77; + dvbsub->lut[r].lut28[2] = 0x88; + dvbsub->lut[r].lut28[3] = 0xFF; + for (i = 0; i < 16; ++i) + dvbsub->lut[r].lut48[i] = i | i << 4; + } +} + static void update_osd(dvb_spu_decoder_t *this, int region_id) { dvbsub_func_t *dvbsub = this->dvbsub; @@ -215,15 +244,15 @@ static void plot (dvb_spu_decoder_t * this, int r, int run_length, unsigned char } } -static const uint8_t *lookup_lut (const dvbsub_func_t *dvbsub) +static const uint8_t *lookup_lut (const dvbsub_func_t *dvbsub, int r) { static const uint8_t identity_lut[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; switch (dvbsub->compat_depth) { - case 012: return dvbsub->lut24; - case 013: return dvbsub->lut28; - case 023: return dvbsub->lut48; + case 012: return dvbsub->lut[r].lut24; + case 013: return dvbsub->lut[r].lut28; + case 023: return dvbsub->lut[r].lut48; default: return identity_lut; } } @@ -258,7 +287,7 @@ static void decode_2bit_pixel_code_string (dvb_spu_decoder_t * this, int r, int { dvbsub_func_t *dvbsub = this->dvbsub; int j; - const uint8_t *lut = lookup_lut (dvbsub); + const uint8_t *lut = lookup_lut (dvbsub, r); if (dvbsub->in_scanline == 0) dvbsub->in_scanline = 1; @@ -324,7 +353,7 @@ static void decode_4bit_pixel_code_string (dvb_spu_decoder_t * this, int r, int { dvbsub_func_t *dvbsub = this->dvbsub; int j; - const uint8_t *lut = lookup_lut (dvbsub); + const uint8_t *lut = lookup_lut (dvbsub, r); if (dvbsub->in_scanline == 0) dvbsub->in_scanline = 1; @@ -456,7 +485,7 @@ static void set_clut(dvb_spu_decoder_t *this,int CLUT_id,int CLUT_entry_id,int Y dvbsub_func_t *dvbsub = this->dvbsub; - if ((CLUT_id>=MAX_REGIONS) || (CLUT_entry_id>15)) { + if ((CLUT_id>=MAX_REGIONS) || (CLUT_entry_id>255)) { return; } @@ -546,18 +575,18 @@ static void process_pixel_data_sub_block (dvb_spu_decoder_t * this, int r, int o break; case 0x20: /* 2-to-4bit colour index map */ /* should this be implemented since we have an 8-bit overlay? */ - dvbsub->lut24[0] = dvbsub->buf[dvbsub->i ] >> 4; - dvbsub->lut24[1] = dvbsub->buf[dvbsub->i ] & 0x0f; - dvbsub->lut24[2] = dvbsub->buf[dvbsub->i + 1] >> 4; - dvbsub->lut24[3] = dvbsub->buf[dvbsub->i + 1] & 0x0f; + dvbsub->lut[r].lut24[0] = dvbsub->buf[dvbsub->i ] >> 4; + dvbsub->lut[r].lut24[1] = dvbsub->buf[dvbsub->i ] & 0x0f; + dvbsub->lut[r].lut24[2] = dvbsub->buf[dvbsub->i + 1] >> 4; + dvbsub->lut[r].lut24[3] = dvbsub->buf[dvbsub->i + 1] & 0x0f; dvbsub->i += 2; break; case 0x21: /* 2-to-8bit colour index map */ - memcpy (dvbsub->lut28, dvbsub->buf + dvbsub->i, 4); + memcpy (dvbsub->lut[r].lut28, dvbsub->buf + dvbsub->i, 4); dvbsub->i += 4; break; case 0x22: - memcpy (dvbsub->lut48, dvbsub->buf + dvbsub->i, 16); + memcpy (dvbsub->lut[r].lut48, dvbsub->buf + dvbsub->i, 16); dvbsub->i += 16; break; case 0xf0: @@ -890,7 +919,6 @@ static void draw_subtitles (dvb_spu_decoder_t * this) pthread_mutex_unlock(&this->dvbsub_osd_mutex); } - 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; @@ -959,25 +987,7 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) /* completely ignore pts since it makes a lot of problems with various providers */ this->vpts = 0; - /* Reset the colour LUTs */ - for (i = 0; i < MAX_REGIONS; ++i) - { - memcpy (this->dvbsub->colours + i * 256, default_clut, sizeof (default_clut)); - memcpy (this->dvbsub->trans + i * 256, default_trans, sizeof (default_trans)); - } - - /* Reset the colour index LUTs */ - this->dvbsub->lut24[0] = 0x0; - this->dvbsub->lut24[1] = 0x7; - this->dvbsub->lut24[2] = 0x8; - this->dvbsub->lut24[3] = 0xF; - this->dvbsub->lut28[0] = 0x00; - this->dvbsub->lut28[1] = 0x77; - this->dvbsub->lut28[2] = 0x88; - this->dvbsub->lut28[3] = 0xFF; - for (i = 0; i < 16; ++i) - this->dvbsub->lut48[i] = i | i << 4; - + reset_clut (this->dvbsub); /* process the pes section */ PES_packet_length = this->pes_pkt_size; -- cgit v1.2.3 From a588599bd24399e45f82fcb19b6a28fb6537771f Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Thu, 28 Jan 2010 02:33:16 +0000 Subject: Do the dvbsub CLUT reset in spudec_reset. This is probably still wrong, but at least works properly with BBC subtitling. --- src/spu_dec/spudvb_decoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spu_dec/spudvb_decoder.c b/src/spu_dec/spudvb_decoder.c index 197b1cd49..b6720acdf 100644 --- a/src/spu_dec/spudvb_decoder.c +++ b/src/spu_dec/spudvb_decoder.c @@ -987,7 +987,6 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) /* completely ignore pts since it makes a lot of problems with various providers */ this->vpts = 0; - reset_clut (this->dvbsub); /* process the pes section */ PES_packet_length = this->pes_pkt_size; @@ -1058,8 +1057,9 @@ static void spudec_reset (spu_decoder_t * this_gen) this->dvbsub->regions[i].version_number = -1; } this->dvbsub->page.page_version_number = -1; - pthread_mutex_unlock(&this->dvbsub_osd_mutex); + reset_clut (this->dvbsub); + pthread_mutex_unlock(&this->dvbsub_osd_mutex); } static void spudec_discontinuity (spu_decoder_t * this_gen) -- cgit v1.2.3 From 81e86315a6966e172f4988f8925f830e01072c53 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 29 Jan 2010 18:36:36 +0000 Subject: Link the v4l2 plugin with libv4l2 (if required); use pkgconfig to locate it. --- configure.ac | 13 ++++++++----- src/input/Makefile.am | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 6ca597502..01d0a5eb6 100644 --- a/configure.ac +++ b/configure.ac @@ -694,11 +694,14 @@ dnl ---------------------------------------------- AC_ARG_ENABLE([libv4l], AS_HELP_STRING([--disable-libv4l], [do not build with libv4l support])) -if test "x$enable_libv4l" != "xno"; then - AC_CHECK_HEADERS([libv4l2.h], [have_libv4l=yes], [have_libv4l=no]) - if test "x$enable_libv4l" = "xyes" && test "x$have_libv4l" = "xno"; then - AC_MSG_ERROR([libv4l requested but not found.]) - fi +if test "x$have_v4l" = xyes; then + have_libv4l=no + PKG_CHECK_MODULES([V4L2], [libv4l2], + [have_libv4l=yes + AC_DEFINE([HAVE_LIBV4L2_H], [1], [Define this if you have libv4l installed])]) + if test "x$enable_libv4l" = "xyes" && test "x$have_libv4l" = "xno"; then + AC_MSG_ERROR([libv4l requested but not found.]) + fi fi diff --git a/src/input/Makefile.am b/src/input/Makefile.am index 3c700ea46..1c34f9aaa 100644 --- a/src/input/Makefile.am +++ b/src/input/Makefile.am @@ -141,8 +141,8 @@ xineplug_inp_v4l_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) xineplug_inp_v4l_la_LDFLAGS = -avoid-version -module xineplug_inp_v4l2_la_SOURCES = input_v4l2.c -xineplug_inp_v4l2_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) -xineplug_inp_v4l2_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) +xineplug_inp_v4l2_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) $(LTLIBINTL) $(V4L2_LIBS) +xineplug_inp_v4l2_la_CFLAGS = $(VISIBILITY_FLAG) $(AM_CFLAGS) $(V4L2_CFLAGS) xineplug_inp_v4l2_la_LDFLAGS = -avoid-version -module xineplug_inp_gnome_vfs_la_SOURCES = input_gnome_vfs.c net_buf_ctrl.c -- cgit v1.2.3 From e0d73e94178127b08b922f2a0ca607fd320a9d9c Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Sat, 30 Jan 2010 01:36:54 +0000 Subject: Add dummy alt attributes to ensure valid XHTML 1.0 Transitional. This is less than ideal. Really, we want DocBook 5. --- doc/hackersguide/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/hackersguide/Makefile.am b/doc/hackersguide/Makefile.am index 37269eaf0..e7e9289c4 100644 --- a/doc/hackersguide/Makefile.am +++ b/doc/hackersguide/Makefile.am @@ -52,6 +52,7 @@ hackersguide.html: $(hackersguide_docbook) touch $^; \ fi endif + $(SED) -i -e '/]*alt=/! s/