diff options
| author | Andreas Monzner <andreas.monzner@multimedia-labs.de> | 2006-10-23 10:52:20 +0000 |
|---|---|---|
| committer | Andreas Monzner <andreas.monzner@multimedia-labs.de> | 2006-10-23 10:52:20 +0000 |
| commit | 0adf3ed39b6fe254154e3b4c38feea616e5aece1 (patch) | |
| tree | 0f98fc2a3d8550660fb28838086ecb9618b25ddd /lib/dvb/subtitle.cpp | |
| parent | 26b914c452fab2f4d24113354cdc6d0c3776fddc (diff) | |
| download | enigma2-0adf3ed39b6fe254154e3b4c38feea616e5aece1.tar.gz enigma2-0adf3ed39b6fe254154e3b4c38feea616e5aece1.zip | |
prepare for dvb subtitle support (not finished yet)
cache query of eDVBServicePMThandler::getProgram
Diffstat (limited to 'lib/dvb/subtitle.cpp')
| -rw-r--r-- | lib/dvb/subtitle.cpp | 996 |
1 files changed, 996 insertions, 0 deletions
diff --git a/lib/dvb/subtitle.cpp b/lib/dvb/subtitle.cpp new file mode 100644 index 00000000..5510997b --- /dev/null +++ b/lib/dvb/subtitle.cpp @@ -0,0 +1,996 @@ +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <memory.h> +#include <time.h> + +#include <asm/types.h> +#include <lib/dvb/idemux.h> +#include <lib/dvb/subtitle.h> +#include <lib/base/smartptr.h> +#include <lib/base/eerror.h> +#include <lib/gdi/gpixmap.h> + +void bitstream_init(struct bitstream *bit, const void *buffer, int size) +{ + bit->data = (__u8*) buffer; + bit->size = size; + bit->avail = 8; + bit->consumed = 0; +} + +int bitstream_get(struct bitstream *bit) +{ + int val; + bit->avail -= bit->size; + val = ((*bit->data) >> bit->avail) & ((1<<bit->size) - 1); + if (!bit->avail) + { + bit->data++; + bit->consumed++; + bit->avail = 8; + } + return val; +} + +static int extract_pts(pts_t &pts, const __u8 *pkt) +{ + pkt += 7; + int flags = *pkt++; + + pkt++; // header length + + if (flags & 0x80) /* PTS present? */ + { + /* damn gcc bug */ + pts = ((unsigned long long)(((pkt[0] >> 1) & 7))) << 30; + pts |= pkt[1] << 22; + pts |= (pkt[2]>>1) << 15; + pts |= pkt[3] << 7; + pts |= (pkt[5]>>1); + + return 0; + } else + return -1; +} + +void eDVBSubtitleParser::subtitle_process_line(struct subtitle_page *page, int object_id, int line, const __u8 *data, int len) +{ + struct subtitle_region *region = page->regions; +// eDebug("line for %d:%d", page->page_id, object_id); + while (region) + { + struct subtitle_region_object *object = region->region_objects; + while (object) + { + if (object->object_id == object_id) + { + int x = object->object_horizontal_position; + int y = object->object_vertical_position + line; + if (x + len > region->region_width) + { + //eDebug("[SUB] !!!! XCLIP %d + %d > %d", x, len, region->region_width); + len = region->region_width - x; + } + if (len < 0) + break; + if (y >= region->region_height) + { + //eDebug("[SUB] !!!! YCLIP %d >= %d", y, region->region_height); + break; + } +// //eDebug("inserting %d bytes (into region %d)", len, region->region_id); + memcpy((__u8*)region->region_buffer->surface->data + region->region_width * y + x, data, len); + } + object = object->next; + } + region = region->next; + } +} + +int eDVBSubtitleParser::subtitle_process_pixel_data(struct subtitle_page *page, int object_id, int *linenr, int *linep, const __u8 *data) +{ + int data_type = *data++; + static __u8 line[720]; + + struct bitstream bit; + bit.size=0; + switch (data_type) + { + case 0x10: // 2bit pixel data + bitstream_init(&bit, data, 2); + while (1) + { + int len=0, col=0; + int code = bitstream_get(&bit); + if (code) + { + col = code; + len = 1; + } else + { + code = bitstream_get(&bit); + if (!code) + { + code = bitstream_get(&bit); + if (code == 1) + { + col = 0; + len = 2; + } else if (code == 2) + { + len = bitstream_get(&bit) << 2; + len |= bitstream_get(&bit); + len += 12; + col = bitstream_get(&bit); + } else if (code == 3) + { + len = bitstream_get(&bit) << 6; + len |= bitstream_get(&bit) << 4; + len |= bitstream_get(&bit) << 2; + len |= bitstream_get(&bit); + len += 29; + col = bitstream_get(&bit); + } else + break; + } else if (code==1) + { + col = 0; + len = 1; + } else if (code&2) + { + if (code&1) + len = 3 + 4 + bitstream_get(&bit); + else + len = 3 + bitstream_get(&bit); + col = bitstream_get(&bit); + } + } + while (len && ((*linep) < 720)) + { + line[(*linep)++] = col; + len--; + } + } + while (bit.avail != 8) + bitstream_get(&bit); + return bit.consumed + 1; + case 0x11: // 4bit pixel data + bitstream_init(&bit, data, 4); + while (1) + { + int len=0, col=0; + int code = bitstream_get(&bit); + if (code) + { + col = code; + len = 1; + } else + { + code = bitstream_get(&bit); + if (!code) + break; + else if (code == 0xC) + { + col = 0; + len = 1; + } else if (code == 0xD) + { + col = 0; + len = 2; + } else if (code < 8) + { + col = 0; + len = (code & 7) + 2; + } else if ((code & 0xC) == 0x8) + { + col = bitstream_get(&bit); + len = (code & 3) + 4; + } else if (code == 0xE) + { + len = bitstream_get(&bit) + 9; + col = bitstream_get(&bit); + } else if (code == 0xF) + { + len = bitstream_get(&bit) << 4; + len |= bitstream_get(&bit); + len += 25; + col = bitstream_get(&bit); + } + } + while (len && ((*linep) < 720)) + { + line[(*linep)++] = col; + len--; + } + } + while (bit.avail != 8) + bitstream_get(&bit); + return bit.consumed + 1; + case 0x12: // 8bit pixel data + bitstream_init(&bit, data, 8); + while(1) + { + int len=0, col=0; + int code = bitstream_get(&bit); + if (code) + { + col = code; + len = 1; + } else + { + code = bitstream_get(&bit); + if ((code & 0x80) == 0x80) + { + len = code&0x7F; + col = bitstream_get(&bit); + } else if (code&0x7F) + { + len = code&0x7F; + col = 0; + } else + break; + } + while (len && ((*linep) < 720)) + { + line[(*linep)++] = col; + len--; + } + } + return bit.consumed + 1; + case 0x20: // ignore 2 -> 4bit map table + bitstream_init(&bit, data, 4); + for ( int i=0; i < 4; ++i ) + bitstream_get(&bit); + break; + case 0x21: // ignore 2 -> 8bit map table + bitstream_init(&bit, data, 8); + for ( int i=0; i < 4; ++i ) + bitstream_get(&bit); + break; + case 0x22: // ignore 4 -> 8bit map table + bitstream_init(&bit, data, 8); + for ( int i=0; i < 16; ++i ) + bitstream_get(&bit); + break; + case 0xF0: + subtitle_process_line(page, object_id, *linenr, line, *linep); +/* { + int i; + for (i=0; i<720; ++i) + //eDebugNoNewLine("%d ", line[i]); + //eDebug(""); + } */ + (*linenr)+=2; // interlaced + *linep = 0; +// //eDebug("[SUB] EOL"); + return 1; + default: + eDebug("subtitle_process_pixel_data: invalid data_type %02x", data_type); + return -1; + } + return 0; +} + +int eDVBSubtitleParser::subtitle_process_segment(const __u8 *segment) +{ + int segment_type, page_id, segment_length, processed_length; + if (*segment++ != 0x0F) + { + eDebug("out of sync."); + return -1; + } + segment_type = *segment++; + page_id = *segment++ << 8; + page_id |= *segment++; + segment_length = *segment++ << 8; + segment_length |= *segment++; + if (segment_type == 0xFF) + return segment_length + 6; +// //eDebug("have %d bytes of segment data", segment_length); + +// //eDebug("page_id %d, segtype %02x", page_id, segment_type); + + struct subtitle_page *page, **ppage; + + page = this->pages; ppage = &this->pages; + + while (page) + { + if (page->page_id == page_id) + break; + ppage = &page->next; + page = page->next; + } + + processed_length = 0; + + switch (segment_type) + { + case 0x10: // page composition segment + { + int page_time_out = *segment++; processed_length++; + int page_version_number = *segment >> 4; + int page_state = (*segment >> 2) & 0x3; + //eDebug("pcs with %d bytes data (%d:%d:%d)", segment_length, page_id, page_version_number, page_state); + segment++; + processed_length++; + + //eDebug("page time out: %d", page_time_out); + //eDebug("page_version_number: %d" ,page_version_number); + //eDebug("page_state: %d", page_state); + + if (!page) + { + //eDebug("page not found"); + page = new subtitle_page; + page->page_regions = 0; + page->regions = 0; + page->page_id = page_id; + page->cluts = 0; + page->next = 0; + *ppage = page; + } else + { + if (page->pcs_size != segment_length) + page->page_version_number = -1; + // if no update, just skip this data. + if (page->page_version_number == page_version_number) + { + eDebug("skip data... "); + break; + } + } + +// eDebug("page updated: old: %d, new: %d", page->page_version_number, page_version_number); + // when acquisition point or mode change: remove all displayed pages. + if ((page_state == 1) || (page_state == 2)) + { + while (page->page_regions) + { + struct subtitle_page_region *p = page->page_regions->next; + delete page->page_regions; + page->page_regions = p; + } + } + +// eDebug("new page.. (%d)", page_state); + + page->page_time_out = page_time_out; + + page->page_version_number = page_version_number; + + struct subtitle_page_region **r = &page->page_regions; + + //eDebug("%d / %d data left", processed_length, segment_length); + + // go to last entry + while (*r) + r = &(*r)->next; + + while (processed_length < segment_length) + { + struct subtitle_page_region *pr; + + // append new entry to list + pr = new subtitle_page_region; + pr->next = 0; + *r = pr; + r = &pr->next; + + pr->region_id = *segment++; processed_length++; + segment++; processed_length++; + + pr->region_horizontal_address = *segment++ << 8; + pr->region_horizontal_address |= *segment++; + processed_length += 2; + + pr->region_vertical_address = *segment++ << 8; + pr->region_vertical_address |= *segment++; + processed_length += 2; + + //eDebug("appended active region"); + } + + if (processed_length != segment_length) + eDebug("%d != %d", processed_length, segment_length); + break; + } + case 0x11: // region composition segment + { + int region_id = *segment++; processed_length++; + int region_version_number = *segment >> 4; + int region_fill_flag = (*segment >> 3) & 1; + segment++; processed_length++; + + // if we didn't yet received the pcs for this page, drop the region + if (!page) + { + eDebug("ignoring region %x, since page %02x doesn't yet exist.", region_id, page_id); + break; + } + + struct subtitle_region *region, **pregion; + + region = page->regions; pregion = &page->regions; + + while (region) + { + fflush(stdout); + if (region->region_id == region_id) + break; + pregion = ®ion->next; + region = region->next; + } + + if (!region) + { + *pregion = region = new subtitle_region; + region->next = 0; + } + else if (region->region_version_number != region_version_number) + { + struct subtitle_region_object *objects = region->region_objects; + while (objects) + { + struct subtitle_region_object *n = objects->next; + delete objects; + objects = n; + } + if (region->region_buffer) + { + if (region->region_buffer->surface) + delete region->region_buffer->surface; + region->region_buffer=0; + } + } + else + break; + + //eDebug("region %d:%d update", page_id, region_id); + + region->region_id = region_id; + region->region_version_number = region_version_number; + + region->region_width = *segment++ << 8; + region->region_width |= *segment++; + processed_length += 2; + + region->region_height = *segment++ << 8; + region->region_height |= *segment++; + processed_length += 2; + + region->region_buffer = new gPixmap(eSize(region->region_width, region->region_height), 8); + + int region_level_of_compatibility, region_depth; + + region_level_of_compatibility = (*segment >> 5) & 7; + region_depth = (*segment++ >> 2) & 7; + region->region_depth = (subtitle_region::depth) region_depth; + processed_length++; + + int CLUT_id = *segment++; processed_length++; + + region->clut_id = CLUT_id; + + int region_8bit_pixel_code, region_4bit_pixel_code, region_2bit_pixel_code; + region_8bit_pixel_code = *segment++; processed_length++; + region_4bit_pixel_code = *segment >> 4; + region_2bit_pixel_code = (*segment++ >> 2) & 3; + processed_length++; + + if (!region_fill_flag) + { + region_2bit_pixel_code = region_4bit_pixel_code = region_8bit_pixel_code = 0; + region_fill_flag = 1; + } + + if (region_fill_flag) + { + if (region_depth == 1) + memset(region->region_buffer->surface->data, region_2bit_pixel_code, region->region_height * region->region_width); + else if (region_depth == 2) + memset(region->region_buffer->surface->data, region_4bit_pixel_code, region->region_height * region->region_width); + else if (region_depth == 3) + memset(region->region_buffer->surface->data, region_8bit_pixel_code, region->region_height * region->region_width); + else + eDebug("!!!! invalid depth"); + } + + //eDebug("region %02x, version %d, %dx%d", region->region_id, region->region_version_number, region->region_width, region->region_height); + + region->region_objects = 0; + struct subtitle_region_object **pobject = ®ion->region_objects; + + while (processed_length < segment_length) + { + + struct subtitle_region_object *object; + + object = new subtitle_region_object; + + *pobject = object; + object->next = 0; + pobject = &object->next; + + object->object_id = *segment++ << 8; + object->object_id |= *segment++; processed_length += 2; + + object->object_type = *segment >> 6; + object->object_provider_flag = (*segment >> 4) & 3; + object->object_horizontal_position = (*segment++ & 0xF) << 8; + object->object_horizontal_position |= *segment++; + processed_length += 2; + + object->object_vertical_position = *segment++ << 8; + object->object_vertical_position |= *segment++ ; + processed_length += 2; + + if ((object->object_type == 1) || (object->object_type == 2)) + { + object->foreground_pixel_value = *segment++; + object->background_pixel_value = *segment++; + processed_length += 2; + } + } + + if (processed_length != segment_length) + eDebug("too less data! (%d < %d)", segment_length, processed_length); + + break; + } + case 0x12: // CLUT definition segment + { + int CLUT_id, CLUT_version_number; + struct subtitle_clut *clut, **pclut; + + if (!page) + break; + + //eDebug("CLUT: %02x", *segment); + CLUT_id = *segment++; + + CLUT_version_number = *segment++ >> 4; + processed_length += 2; + + //eDebug("page %d, CLUT %02x, version %d", page->page_id, CLUT_id, CLUT_version_number); + + clut = page->cluts; pclut = &page->cluts; + + while (clut) + { + if (clut->clut_id == CLUT_id) + break; + pclut = &clut->next; + clut = clut->next; + } + + if (!clut) + { + *pclut = clut = new subtitle_clut; + clut->next = 0; + clut->clut_id = CLUT_id; + } + else if (clut->CLUT_version_number == CLUT_version_number) + break; + + clut->CLUT_version_number=CLUT_version_number; + clut->size_2 = clut->size_4 = clut->size_8 = 0; + + /* invalidate CLUT if updated. */ + if ((this->current_clut_page_id == page_id) && (this->current_clut_id == CLUT_id)) + this->current_clut_id = -1; + + //eDebug("new clut"); + while (processed_length < segment_length) + { + int CLUT_entry_id, entry_CLUT_flag, full_range; + int v_Y, v_Cr, v_Cb, v_T; + + CLUT_entry_id = *segment++; + full_range = *segment & 1; + entry_CLUT_flag = (*segment++ & 0xE0) >> 5; + processed_length += 2; + + if (full_range) + { + v_Y = *segment++; + v_Cr = *segment++; + v_Cb = *segment++; + v_T = *segment++; + processed_length += 4; + } else + { + v_Y = *segment & 0xFC; + v_Cr = (*segment++ & 3) << 6; + v_Cr |= (*segment & 0xC0) >> 2; + v_Cb = (*segment & 0x3C) << 2; + v_T = (*segment++ & 3) << 6; + processed_length += 2; + } + + if (entry_CLUT_flag & 1) // 8bit + { + ASSERT(CLUT_entry_id < 256); + ++clut->size_8; + clut->entries_8bit[CLUT_entry_id].Y = v_Y; + clut->entries_8bit[CLUT_entry_id].Cr = v_Cr; + clut->entries_8bit[CLUT_entry_id].Cb = v_Cb; + clut->entries_8bit[CLUT_entry_id].T = v_T; + } + if (entry_CLUT_flag & 2) // 4bit + { + ASSERT(CLUT_entry_id < 16); + ++clut->size_4; + clut->entries_4bit[CLUT_entry_id].Y = v_Y; + clut->entries_4bit[CLUT_entry_id].Cr = v_Cr; + clut->entries_4bit[CLUT_entry_id].Cb = v_Cb; + clut->entries_4bit[CLUT_entry_id].T = v_T; + } + if (entry_CLUT_flag & 4) // 2bit + { + ASSERT(CLUT_entry_id < 4); + ++clut->size_2; + clut->entries_2bit[CLUT_entry_id].Y = v_Y; + clut->entries_2bit[CLUT_entry_id].Cr = v_Cr; + clut->entries_2bit[CLUT_entry_id].Cb = v_Cb; + clut->entries_2bit[CLUT_entry_id].T = v_T; + } + //eDebug(" %04x %02x %02x %02x %02x", CLUT_entry_id, v_Y, v_Cb, v_Cr, v_T); + } + break; + } + case 0x13: // object data segment + { + int object_id, object_version_number, object_coding_method, non_modifying_color_flag; + + object_id = *segment++ << 8; + object_id |= *segment++; + processed_length += 2; + + object_version_number = *segment >> 4; + object_coding_method = (*segment >> 2) & 3; + non_modifying_color_flag = (*segment++ >> 1) & 1; + processed_length++; + + //eDebug("object id %04x, version %d, object_coding_method %d (page_id %d)", object_id, object_version_number, object_coding_method, page_id); + + if (object_coding_method == 0) + { + int top_field_data_blocklength, bottom_field_data_blocklength; + int i, line, linep; + + top_field_data_blocklength = *segment++ << 8; + top_field_data_blocklength |= *segment++; + + bottom_field_data_blocklength = *segment++ << 8; + bottom_field_data_blocklength |= *segment++; + //eDebug("%d / %d bytes", top_field_data_blocklength, bottom_field_data_blocklength); + processed_length += 4; + + i = 0; + line = 0; + linep = 0; + while (i < top_field_data_blocklength) + { + int len; + len = subtitle_process_pixel_data(page, object_id, &line, &linep, segment); + if (len < 0) + return -1; + segment += len; + processed_length += len; + i += len; + } + + line = 1; + linep = 0; + + if (bottom_field_data_blocklength) + { + i = 0; + while (i < bottom_field_data_blocklength) + { + int len; + len = subtitle_process_pixel_data(page, object_id, &line, &linep, segment); + if (len < 0) + return -1; + segment += len; + processed_length += len; + i += len; + } + } + else if (top_field_data_blocklength) + eDebug("!!!! unimplemented: no bottom field! (%d : %d)", top_field_data_blocklength, bottom_field_data_blocklength); + + if ((top_field_data_blocklength + bottom_field_data_blocklength) & 1) + { + segment++; processed_length++; + } + } + else if (object_coding_method == 1) + eDebug("---- object_coding_method 1 unsupported!"); + + break; + } + case 0x80: // end of display set segment + { +// eDebug("end of display set segment"); + subtitle_redraw_all(); + } + case 0xFF: // stuffing + break; + default: + eDebug("unhandled segment type %02x", segment_type); + } + + return segment_length + 6; +} + +void eDVBSubtitleParser::subtitle_process_pes(const __u8 *pkt, int len) +{ + if (!extract_pts(show_time, pkt)) + { + pkt += 6; len -= 6; + // skip PES header + pkt++; len--; + pkt++; len--; + + int hdr_len = *pkt++; len--; + + pkt+=hdr_len; len-=hdr_len; + + if (*pkt != 0x20) + { + //eDebug("data identifier is 0x%02x, but not 0x20", *pkt); + return; + } + pkt++; len--; // data identifier + *pkt++; len--; // stream id; + + if (len <= 0) + { + //eDebug("no data left (%d)", len); + return; + } + + while (len && *pkt == 0x0F) + { + int l = subtitle_process_segment(pkt); + if (l < 0) + break; + pkt += l; + len -= l; + } + // if (len && *pkt != 0xFF) + // eDebug("strange data at the end"); + } + else + eDebug("dvb subtitle packet without PTS.. ignore!!"); +} + +void eDVBSubtitleParser::subtitle_clear_screen() +{ + /* clear bbox */ + int y; + + //eDebug("BBOX clear %d:%d -> %d:%d", this->bbox_left, this->bbox_top, this->bbox_right, this->bbox_bottom); + + // do not draw when anyone has locked the + // framebuffer ( non enigma plugins... ) + this->bbox_right = 720; + if (this->bbox_right > this->bbox_left) + for (y=this->bbox_top; y < this->bbox_bottom; ++y) + ; // TODO fixmee clear subtitle screen + + this->bbox_right = 0; + this->bbox_left = this->screen_width; + this->bbox_top = this->screen_height; + this->bbox_bottom = 0; +} + +void eDVBSubtitleParser::subtitle_redraw_all() +{ +#if 1 + struct subtitle_page *page = this->pages; + if ( page ) + { + struct subtitle_page_region *region = page->page_regions; + if ( region ) + subtitle_clear_screen(); + } + while(page) + { + subtitle_redraw(page->page_id); + page = page->next; + } +#else + subtitle_clear_screen(); + + struct subtitle_page *page = this->pages; + //eDebug("----------- end of display set"); + //eDebug("active pages:"); + while (page) + { + //eDebug(" page_id %02x", page->page_id); + //eDebug(" page_version_number: %d", page->page_version_number); + //eDebug(" active regions:"); + { + struct subtitle_page_region *region = page->page_regions; + while (region) + { + //eDebug(" region_id: %04x", region->region_id); + //eDebug(" region_horizontal_address: %d", region->region_horizontal_address); + //eDebug(" region_vertical_address: %d", region->region_vertical_address); + + region = region->next; + } + } + + subtitle_redraw(page->page_id); + //eDebug("defined regions:"); + struct subtitle_region *region = page->regions; + while (region) + { + //eDebug(" region_id %04x, version %d, %dx%d", region->region_id, region->region_version_number, region->region_width, region->region_height); + + struct subtitle_region_object *object = region->region_objects; + while (object) + { + //eDebug(" object %02x, type %d, %d:%d", object->object_id, object->object_type, object->object_horizontal_position, object->object_vertical_position); + object = object->next; + } + region = region->next; + } + page = page->next; + } +#endif +} + +void eDVBSubtitleParser::subtitle_reset() +{ + while (struct subtitle_page *page = this->pages) + { + /* free page regions */ + while (page->page_regions) + { + struct subtitle_page_region *p = page->page_regions->next; + delete page->page_regions; + page->page_regions = p; + } + /* free regions */ + while (page->regions) + { + struct subtitle_region *region = page->regions; + + while (region->region_objects) + { + struct subtitle_region_object *obj = region->region_objects; + region->region_objects = obj->next; + delete obj; + } + + if (region->region_buffer) + { + if (region->region_buffer->surface) + delete region->region_buffer->surface; + region->region_buffer=0; + } + + page->regions = region->next; + delete region; + } + + /* free CLUTs */ + while (page->cluts) + { + struct subtitle_clut *clut = page->cluts; + page->cluts = clut->next; + delete clut; + } + + this->pages = page->next; + delete page; + } +} + +void eDVBSubtitleParser::subtitle_redraw(int page_id) +{ + struct subtitle_page *page = this->pages; + + //eDebug("displaying page id %d", page_id); + + while (page) + { + if (page->page_id == page_id) + break; + page = page->next; + } + if (!page) + { + //eDebug("page not found"); + return; + } + + + //eDebug("iterating regions.."); + /* iterate all regions in this pcs */ + struct subtitle_page_region *region = page->page_regions; + while (region) + { + //eDebug("region %d", region->region_id); + /* find corresponding region */ + struct subtitle_region *reg = page->regions; + while (reg) + { + if (reg->region_id == region->region_id) + break; + reg = reg->next; + } + if (reg) + { + int y; + //eDebug("copy region %d to %d, %d", region->region_id, region->region_horizontal_address, region->region_vertical_address); + + int x0 = region->region_horizontal_address; + int y0 = region->region_vertical_address; + int x1 = x0 + reg->region_width; + int y1 = y0 + reg->region_height; + + if ((x0 < 0) || (y0 < 0) || (x0 > this->screen_width) || (x0 > this->screen_height)) + continue; + + /* adjust bbox */ + if (x0 < this->bbox_left) + this->bbox_left = x0; + if (y0 < this->bbox_top) + this->bbox_top = y0; + if (x1 > this->bbox_right) + this->bbox_right = x1; + if (y1 > this->bbox_bottom) + this->bbox_bottom = y1; + + int timeout = page->page_time_out; + + /* find corresponding clut */ + struct subtitle_clut *clut = page->cluts; + while (clut) + { + //eDebug("have %d, want %d", clut->clut_id, main_clut_id); + if (clut->clut_id == reg->clut_id) + break; + clut = clut->next; + } + if (clut) + { + // TODO fill region->surface->clut !!!!! + } + else + { + // apply default clut depending on region->region_depth + // TODO fill region->surface->clut !!!!! + } + // TODO Blit Region Pixmap !!! + } + else + eDebug("region not found"); + region = region->next; + } + //eDebug("schon gut."); +} + +DEFINE_REF(eDVBSubtitleParser); + +eDVBSubtitleParser::eDVBSubtitleParser(iDVBDemux *demux) +{ + setStreamID(0xBD); + + if (demux->createPESReader(eApp, m_pes_reader)) + eDebug("failed to create dvb subtitle PES reader!"); + else + m_pes_reader->connectRead(slot(*this, &eDVBSubtitleParser::subtitle_process_pes), m_read_connection); +} + +eDVBSubtitleParser::~eDVBSubtitleParser() +{ + subtitle_reset(); +} |
