summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/input/Makefile.am4
-rw-r--r--src/input/input_v4l2.c53
-rw-r--r--src/spu_dec/spudvb_decoder.c411
3 files changed, 341 insertions, 127 deletions
diff --git a/src/input/Makefile.am b/src/input/Makefile.am
index c740351d6..608b7e68f 100644
--- a/src/input/Makefile.am
+++ b/src/input/Makefile.am
@@ -126,8 +126,8 @@ xineplug_inp_v4l_la_LIBADD = $(XINE_LIB) $(ALSA_LIBS) $(LTLIBINTL)
xineplug_inp_v4l_la_CFLAGS = $(AM_CFLAGS) $(ALSA_CFLAGS)
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 = $(AM_CFLAGS) $(ALSA_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
diff --git a/src/input/input_v4l2.c b/src/input/input_v4l2.c
index 2ecb5bf0c..ef08a63ee 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 <xine/input_plugin.h>
#include <xine/xine_plugin.h>
#include <xine/xine_internal.h>
@@ -91,19 +91,26 @@ 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)
+ {
+ 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) {
this->video = malloc(sizeof(v4l2_video_t));
this->video->headerSent = 0;
@@ -117,16 +124,19 @@ static int v4l2_input_open(input_plugin_t *this_gen) {
return 1;
} else {
/* TODO: Fallbacks */
- lprintf("Video streaming setup failed.\n");
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE": video streaming setup failed\n");
return 0;
}
} else {
/* TODO: Radio streaming */
- lprintf("Sorry, only video is supported for now.\n");
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE": sorry, only video is supported for now\n");
return 0;
}
} else {
- lprintf("Device doesn't support streaming. Prod the author to support the other methods.\n");
+ 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 {
@@ -180,7 +190,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;
@@ -229,9 +240,14 @@ 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)
+ {
+ buf->free_buffer (buf);
+ buf = NULL;
+ }
}
return buf;
}
@@ -251,12 +267,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
@@ -269,26 +289,26 @@ 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)
{
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) {
@@ -398,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");
+ xprintf (this->stream->xine, XINE_VERBOSITY_NONE,
+ LOG_MODULE": WARNING: this plugin is not of release quality\n");
+
return &this->input_plugin;
}
diff --git a/src/spu_dec/spudvb_decoder.c b/src/spu_dec/spudvb_decoder.c
index 4b6032a5c..b6720acdf 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,16 @@ 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];
+ struct {
+ unsigned char lut24[4], lut28[4], lut48[16];
+ } lut[MAX_REGIONS];
} dvbsub_func_t;
typedef struct dvb_spu_class_s {
@@ -112,6 +116,36 @@ 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 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)
{
@@ -210,106 +244,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, 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->lut[r].lut24;
+ case 013: return dvbsub->lut[r].lut28;
+ case 023: return dvbsub->lut[r].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, r);
+
+ 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, r);
- 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);
}
}
@@ -336,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;
}
@@ -415,9 +564,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->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->lut[r].lut28, dvbsub->buf + dvbsub->i, 4);
+ dvbsub->i += 4;
+ break;
+ case 0x22:
+ memcpy (dvbsub->lut[r].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 +673,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 +761,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 +775,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;
@@ -735,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;
@@ -843,10 +1026,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 +1042,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)
@@ -895,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)
@@ -940,6 +1103,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;