From 3ecd3b8d7f2d52fd7b5956c1fe08f926cc2a2858 Mon Sep 17 00:00:00 2001 From: Andreas Monzner Date: Wed, 25 Oct 2006 18:06:01 +0000 Subject: [PATCH] dvb subtitles are working now --- lib/dvb/subtitle.cpp | 309 ++++++++++++++++++-------- lib/dvb/subtitle.h | 57 ++--- lib/dvb/teletext.cpp | 4 +- lib/dvb/teletext.h | 2 +- lib/gui/esubtitle.cpp | 25 ++- lib/gui/esubtitle.h | 5 + lib/python/Screens/InfoBarGenerics.py | 4 +- lib/service/servicedvb.cpp | 139 ++++++++---- lib/service/servicedvb.h | 13 +- 9 files changed, 382 insertions(+), 176 deletions(-) diff --git a/lib/dvb/subtitle.cpp b/lib/dvb/subtitle.cpp index eae72056..23ea6dce 100644 --- a/lib/dvb/subtitle.cpp +++ b/lib/dvb/subtitle.cpp @@ -11,7 +11,7 @@ #include #include -void bitstream_init(struct bitstream *bit, const void *buffer, int size) +void bitstream_init(bitstream *bit, const void *buffer, int size) { bit->data = (__u8*) buffer; bit->size = size; @@ -19,7 +19,7 @@ void bitstream_init(struct bitstream *bit, const void *buffer, int size) bit->consumed = 0; } -int bitstream_get(struct bitstream *bit) +int bitstream_get(bitstream *bit) { int val; bit->avail -= bit->size; @@ -54,13 +54,13 @@ static int extract_pts(pts_t &pts, __u8 *pkt) return -1; } -void eDVBSubtitleParser::subtitle_process_line(struct subtitle_page *page, int object_id, int line, __u8 *data, int len) +void eDVBSubtitleParser::subtitle_process_line(subtitle_page *page, int object_id, int line, __u8 *data, int len) { - struct subtitle_region *region = page->regions; + 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; + subtitle_region_object *object = region->region_objects; while (object) { if (object->object_id == object_id) @@ -88,12 +88,12 @@ void eDVBSubtitleParser::subtitle_process_line(struct subtitle_page *page, int o } } -int eDVBSubtitleParser::subtitle_process_pixel_data(struct subtitle_page *page, int object_id, int *linenr, int *linep, __u8 *data) +int eDVBSubtitleParser::subtitle_process_pixel_data(subtitle_page *page, int object_id, int *linenr, int *linep, __u8 *data) { int data_type = *data++; static __u8 line[720]; - struct bitstream bit; + bitstream bit; bit.size=0; switch (data_type) { @@ -291,7 +291,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) // //eDebug("page_id %d, segtype %02x", page_id, segment_type); - struct subtitle_page *page, **ppage; + subtitle_page *page, **ppage; page = this->pages; ppage = &this->pages; @@ -348,7 +348,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) { while (page->page_regions) { - struct subtitle_page_region *p = page->page_regions->next; + subtitle_page_region *p = page->page_regions->next; delete page->page_regions; page->page_regions = p; } @@ -360,7 +360,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) page->page_version_number = page_version_number; - struct subtitle_page_region **r = &page->page_regions; + subtitle_page_region **r = &page->page_regions; //eDebug("%d / %d data left", processed_length, segment_length); @@ -370,7 +370,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) while (processed_length < segment_length) { - struct subtitle_page_region *pr; + subtitle_page_region *pr; // append new entry to list pr = new subtitle_page_region; @@ -410,7 +410,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) break; } - struct subtitle_region *region, **pregion; + subtitle_region *region, **pregion; region = page->regions; pregion = &page->regions; @@ -430,10 +430,10 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) } else if (region->region_version_number != region_version_number) { - struct subtitle_region_object *objects = region->region_objects; + subtitle_region_object *objects = region->region_objects; while (objects) { - struct subtitle_region_object *n = objects->next; + subtitle_region_object *n = objects->next; delete objects; objects = n; } @@ -500,12 +500,11 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) //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; + subtitle_region_object **pobject = ®ion->region_objects; while (processed_length < segment_length) { - - struct subtitle_region_object *object; + subtitle_region_object *object; object = new subtitle_region_object; @@ -542,7 +541,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) case 0x12: // CLUT definition segment { int CLUT_id, CLUT_version_number; - struct subtitle_clut *clut, **pclut; + subtitle_clut *clut, **pclut; if (!page) break; @@ -575,11 +574,10 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) 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; + memset(clut->entries_2bit, 0, sizeof(clut->entries_2bit)); + memset(clut->entries_4bit, 0, sizeof(clut->entries_4bit)); + memset(clut->entries_8bit, 0, sizeof(clut->entries_8bit)); //eDebug("new clut"); while (processed_length < segment_length) @@ -612,29 +610,29 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) 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; + clut->entries_8bit[CLUT_entry_id].valid = 1; } 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; + clut->entries_4bit[CLUT_entry_id].valid = 1; } 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; + clut->entries_2bit[CLUT_entry_id].valid = 1; } //eDebug(" %04x %02x %02x %02x %02x", CLUT_entry_id, v_Y, v_Cb, v_Cr, v_T); } @@ -728,7 +726,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment) void eDVBSubtitleParser::subtitle_process_pes(__u8 *pkt, int len) { - eDebug("subtitle_process_pes"); +// eDebug("subtitle_process_pes"); if (!extract_pts(show_time, pkt)) { pkt += 6; len -= 6; @@ -769,45 +767,17 @@ void eDVBSubtitleParser::subtitle_process_pes(__u8 *pkt, int len) 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(); - } + subtitle_page *page = this->pages; while(page) { subtitle_redraw(page->page_id); page = page->next; } #else - subtitle_clear_screen(); - - struct subtitle_page *page = this->pages; + subtitle_page *page = this->pages; //eDebug("----------- end of display set"); //eDebug("active pages:"); while (page) @@ -816,7 +786,7 @@ void eDVBSubtitleParser::subtitle_redraw_all() //eDebug(" page_version_number: %d", page->page_version_number); //eDebug(" active regions:"); { - struct subtitle_page_region *region = page->page_regions; + subtitle_page_region *region = page->page_regions; while (region) { //eDebug(" region_id: %04x", region->region_id); @@ -829,12 +799,12 @@ void eDVBSubtitleParser::subtitle_redraw_all() subtitle_redraw(page->page_id); //eDebug("defined regions:"); - struct subtitle_region *region = page->regions; + 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; + 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); @@ -849,23 +819,23 @@ void eDVBSubtitleParser::subtitle_redraw_all() void eDVBSubtitleParser::subtitle_reset() { - while (struct subtitle_page *page = this->pages) + while (subtitle_page *page = this->pages) { /* free page regions */ while (page->page_regions) { - struct subtitle_page_region *p = page->page_regions->next; + 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; + subtitle_region *region = page->regions; while (region->region_objects) { - struct subtitle_region_object *obj = region->region_objects; + subtitle_region_object *obj = region->region_objects; region->region_objects = obj->next; delete obj; } @@ -884,7 +854,7 @@ void eDVBSubtitleParser::subtitle_reset() /* free CLUTs */ while (page->cluts) { - struct subtitle_clut *clut = page->cluts; + subtitle_clut *clut = page->cluts; page->cluts = clut->next; delete clut; } @@ -896,7 +866,7 @@ void eDVBSubtitleParser::subtitle_reset() void eDVBSubtitleParser::subtitle_redraw(int page_id) { - struct subtitle_page *page = this->pages; + subtitle_page *page = this->pages; //eDebug("displaying page id %d", page_id); @@ -912,15 +882,17 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id) return; } - //eDebug("iterating regions.."); /* iterate all regions in this pcs */ - struct subtitle_page_region *region = page->page_regions; - while (region) + subtitle_page_region *region = page->page_regions; + + eDVBSubtitlePage Page; + Page.m_show_time = show_time; + for (; region; region=region->next) { - //eDebug("region %d", region->region_id); +// eDebug("region %d", region->region_id); /* find corresponding region */ - struct subtitle_region *reg = page->regions; + subtitle_region *reg = page->regions; while (reg) { if (reg->region_id == region->region_id) @@ -929,31 +901,22 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id) } if (reg) { - int y; - //eDebug("copy region %d to %d, %d", region->region_id, region->region_horizontal_address, region->region_vertical_address); +// 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)) + if ((x0 < 0) || (y0 < 0)) + { +// eDebug("x0 %d, y0 %d", +// x0, y0); 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; + subtitle_clut *clut = page->cluts; while (clut) { //eDebug("have %d, want %d", clut->clut_id, main_clut_id); @@ -961,22 +924,174 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id) break; clut = clut->next; } - if (clut) + + int clut_size = reg->region_buffer->surface->clut.colors = reg->region_depth == subtitle_region::bpp2 ? + 4 : reg->region_depth == subtitle_region::bpp4 ? 16 : 256; + + if (reg->region_buffer->surface->clut.data && + clut_size != reg->region_buffer->surface->clut.colors) { - // TODO fill region->surface->clut !!!!! + delete [] reg->region_buffer->surface->clut.data; + reg->region_buffer->surface->clut.data = 0; } - else + + if (!reg->region_buffer->surface->clut.data) + reg->region_buffer->surface->clut.data = new gRGB[clut_size]; + + gRGB *palette = reg->region_buffer->surface->clut.data; + + subtitle_clut_entry *entries=0; + switch(reg->region_depth) { - // apply default clut depending on region->region_depth - // TODO fill region->surface->clut !!!!! + case subtitle_region::bpp2: +// eDebug("2BPP"); + entries = clut->entries_2bit; + memset(palette, 0, 4*sizeof(gRGB)); + palette[0].a = 0xFF; + palette[2].r = palette[2].g = palette[2].b = 0xFF; + palette[3].r = palette[3].g = palette[3].b = 0x80; + break; + case subtitle_region::bpp4: +// eDebug("4BPP"); + entries = clut->entries_4bit; + memset(palette, 0, 16*sizeof(gRGB)); + for (int i=0; i < 16; ++i) + { + if (!i) + palette[i].a = 0xFF; + else if (i & 1) + { + if (i & 8) + palette[i].r = 0x80; + if (i & 4) + palette[i].g = 0x80; + if (i & 2) + palette[i].b = 0x80; + } + else + { + if (i & 8) + palette[i].r = 0xFF; + if (i & 4) + palette[i].g = 0xFF; + if (i & 2) + palette[i].b = 0xFF; + } + } + break; + case subtitle_region::bpp8: +// eDebug("8BPP"); + entries = clut->entries_8bit; + memset(palette, 0, 16*sizeof(gRGB)); + for (int i=0; i < 256; ++i) + { + switch (i & 17) + { + case 0: // b1 == 0 && b5 == 0 + if (!(i & 14)) // b2 == 0 && b3 == 0 && b4 == 0 + { + if (!(i & 224)) // b6 == 0 && b7 == 0 && b8 == 0 + palette[i].a = 0xFF; + else + { + if (i & 128) // R = 100% x b8 + palette[i].r = 0xFF; + if (i & 64) // G = 100% x b7 + palette[i].g = 0xFF; + if (i & 32) // B = 100% x b6 + palette[i].b = 0xFF; + palette[i].a = 0xBF; // T = 75% + } + break; + } + // fallthrough !! + case 16: // b1 == 0 && b5 == 1 + if (i & 128) // R = 33% x b8 + palette[i].r = 0x55; + if (i & 64) // G = 33% x b7 + palette[i].g = 0x55; + if (i & 32) // B = 33% x b6 + palette[i].b = 0x55; + if (i & 8) // R + 66,7% x b4 + palette[i].r += 0xAA; + if (i & 4) // G + 66,7% x b3 + palette[i].g += 0xAA; + if (i & 2) // B + 66,7% x b2 + palette[i].b += 0xAA; + if (i & 16) // needed for fall through from case 0!! + palette[i].a = 0x80; // T = 50% + break; + case 1: // b1 == 1 && b5 == 0 + palette[i].r = + palette[i].g = + palette[i].b = 0x80; // 50% + // fall through!! + case 17: // b1 == 1 && b5 == 1 + if (i & 128) // R += 16.7% x b8 + palette[i].r += 0x2A; + if (i & 64) // G += 16.7% x b7 + palette[i].g += 0x2A; + if (i & 32) // B += 16.7% x b6 + palette[i].b += 0x2A; + if (i & 8) // R += 33% x b4 + palette[i].r += 0x55; + if (i & 4) // G += 33% x b3 + palette[i].g += 0x55; + if (i & 2) // B += 33% x b2 + palette[i].b += 0x55; + break; + } + } + break; } - // TODO Blit Region Pixmap !!! - eDebug("blit region"); + + if (clut) + { + for (int i=0; i 0) + { + y -= 16; + cr -= 128; + cb -= 128; + palette[i].r = MAX(MIN(((298 * y + 460 * cr) / 256), 255), 0); + palette[i].g = MAX(MIN(((298 * y - 55 * cb - 137 * cr) / 256), 255), 0); + palette[i].b = MAX(MIN(((298 * y + 543 * cb ) / 256), 255), 0); + palette[i].a = (entries[i].T) & 0xFF; +// eDebug("override clut entry %d RGBA %02x%02x%02x%02x", i, +// palette[i].r, palette[i].g, palette[i].b, palette[i].a); + } + else + { +// eDebug("mist %d", i); + palette[i].r = 0; + palette[i].g = 0; + palette[i].b = 0; + palette[i].a = 0xFF; + } + } + } + } + + eDVBSubtitleRegion Region; + Region.m_pixmap = reg->region_buffer; + Region.m_position.setX(x0); + Region.m_position.setY(y0); + Page.m_regions.push_back(Region); } else eDebug("region not found"); - region = region->next; } + m_new_subtitle_page(Page); + Page.m_regions.clear(); +// eDebug("page timeout is %d", page->page_time_out); +// Page.m_show_time += (page->page_time_out * 90000); +// m_new_subtitle_page(Page); //eDebug("schon gut."); } @@ -1000,7 +1115,7 @@ eDVBSubtitleParser::~eDVBSubtitleParser() int eDVBSubtitleParser::start(int pid) { -#if 0 +#if 1 eDebug("eDVBSubtitleParser::start(%04x)", pid); if (m_pes_reader) return m_pes_reader->start(pid); @@ -1009,7 +1124,7 @@ int eDVBSubtitleParser::start(int pid) #endif } -void eDVBSubtitleParser::connectNewRegion(const Slot1 &slot, ePtr &connection) +void eDVBSubtitleParser::connectNewPage(const Slot1 &slot, ePtr &connection) { - connection = new eConnection(this, m_new_subtitle_region.connect(slot)); + connection = new eConnection(this, m_new_subtitle_page.connect(slot)); } diff --git a/lib/dvb/subtitle.h b/lib/dvb/subtitle.h index 6faad507..330147ad 100644 --- a/lib/dvb/subtitle.h +++ b/lib/dvb/subtitle.h @@ -11,17 +11,17 @@ typedef unsigned char __u8; struct subtitle_clut_entry { __u8 Y, Cr, Cb, T; + __u8 valid; }; struct subtitle_clut { unsigned char clut_id; - unsigned char size_2, size_4, size_8; unsigned char CLUT_version_number; - struct subtitle_clut_entry entries_2bit[4]; - struct subtitle_clut_entry entries_4bit[16]; - struct subtitle_clut_entry entries_8bit[256]; - struct subtitle_clut *next; + subtitle_clut_entry entries_2bit[4]; + subtitle_clut_entry entries_4bit[16]; + subtitle_clut_entry entries_8bit[256]; + subtitle_clut *next; }; struct subtitle_page_region @@ -29,7 +29,7 @@ struct subtitle_page_region int region_id; int region_horizontal_address; int region_vertical_address; - struct subtitle_page_region *next; + subtitle_page_region *next; }; struct subtitle_region_object @@ -45,7 +45,7 @@ struct subtitle_region_object int foreground_pixel_value; int background_pixel_value; - struct subtitle_region_object *next; + subtitle_region_object *next; }; struct subtitle_region @@ -58,9 +58,9 @@ struct subtitle_region int clut_id; - struct subtitle_region_object *region_objects; + subtitle_region_object *region_objects; - struct subtitle_region *next; + subtitle_region *next; }; struct subtitle_page @@ -69,13 +69,13 @@ struct subtitle_page time_t page_time_out; int page_version_number; int pcs_size; - struct subtitle_page_region *page_regions; + subtitle_page_region *page_regions; - struct subtitle_region *regions; + subtitle_region *regions; - struct subtitle_clut *cluts; + subtitle_clut *cluts; - struct subtitle_page *next; + subtitle_page *next; }; struct bitstream @@ -88,34 +88,41 @@ struct bitstream struct eDVBSubtitleRegion { - pts_t show_time; - int timeout; - ePtr region; + ePtr m_pixmap; + ePoint m_position; + eDVBSubtitleRegion &operator=(const eDVBSubtitleRegion &s) + { + m_pixmap = s.m_pixmap; + m_position = s.m_position; + return *this; + } +}; + +struct eDVBSubtitlePage +{ + std::list m_regions; + pts_t m_show_time; }; class eDVBSubtitleParser :public iObject, public ePESParser, public Object { DECLARE_REF(eDVBSubtitleParser); - struct subtitle_page *pages; - int current_clut_id, current_clut_page_id; - int screen_width, screen_height; - int bbox_left, bbox_top, bbox_right, bbox_bottom; + subtitle_page *pages; ePtr m_pes_reader; ePtr m_read_connection; pts_t show_time; - Signal1 m_new_subtitle_region; + Signal1 m_new_subtitle_page; public: eDVBSubtitleParser(iDVBDemux *demux); virtual ~eDVBSubtitleParser(); int start(int pid); - void connectNewRegion(const Slot1 &slot, ePtr &connection); + void connectNewPage(const Slot1 &slot, ePtr &connection); private: - void subtitle_process_line(struct subtitle_page *page, int object_id, int line, __u8 *data, int len); - int subtitle_process_pixel_data(struct subtitle_page *page, int object_id, int *linenr, int *linep, __u8 *data); + void subtitle_process_line(subtitle_page *page, int object_id, int line, __u8 *data, int len); + int subtitle_process_pixel_data(subtitle_page *page, int object_id, int *linenr, int *linep, __u8 *data); int subtitle_process_segment(__u8 *segment); void subtitle_process_pes(__u8 *buffer, int len); - void subtitle_clear_screen(); void subtitle_redraw_all(); void subtitle_reset(); void subtitle_redraw(int page_id); diff --git a/lib/dvb/teletext.cpp b/lib/dvb/teletext.cpp index 2a44f4f9..0515913a 100644 --- a/lib/dvb/teletext.cpp +++ b/lib/dvb/teletext.cpp @@ -269,11 +269,13 @@ void eDVBTeletextParser::handlePageEnd(int have_pts, const pts_t &pts) m_subtitle_page.m_have_pts = have_pts; m_subtitle_page.m_pts = pts; m_subtitle_page.m_timeout = 90000 * 20; /* 20s */ - sendSubtitlePage(); /* send assembled subtitle page to display */ + if (m_page_number != -1) + sendSubtitlePage(); /* send assembled subtitle page to display */ } void eDVBTeletextParser::setPage(int page) { + m_page_number = page; m_page_M = (page >> 8) & 7; /* magazine to look for */ m_page_X = page & 0xFF; /* page number */ } diff --git a/lib/dvb/teletext.h b/lib/dvb/teletext.h index af9d71f1..821a9226 100644 --- a/lib/dvb/teletext.h +++ b/lib/dvb/teletext.h @@ -48,7 +48,7 @@ private: int m_M, m_Y, m_X, m_S1, m_S2, m_S3, m_S4, m_C; - int m_page_M, m_page_X, m_page_open, m_double_height; + int m_page_number, m_page_M, m_page_X, m_page_open, m_double_height; void handlePageStart(); void handleLine(unsigned char *line, int len); diff --git a/lib/gui/esubtitle.cpp b/lib/gui/esubtitle.cpp index 167325d8..f0b899f7 100644 --- a/lib/gui/esubtitle.cpp +++ b/lib/gui/esubtitle.cpp @@ -14,6 +14,7 @@ eSubtitleWidget::eSubtitleWidget(eWidget *parent) { setBackgroundColor(gRGB(0,0,0,255)); m_page_ok = 0; + m_dvb_page_ok = 0; } void eSubtitleWidget::setPage(const eDVBTeletextSubtitlePage &p) @@ -23,9 +24,17 @@ void eSubtitleWidget::setPage(const eDVBTeletextSubtitlePage &p) invalidate(); } +void eSubtitleWidget::setPage(const eDVBSubtitlePage &p) +{ + m_dvb_page = p; + m_dvb_page_ok = 1; + invalidate(); +} + void eSubtitleWidget::clearPage() { m_page_ok = 0; + m_dvb_page_ok = 0; invalidate(); } @@ -44,10 +53,9 @@ int eSubtitleWidget::event(int event, void *data, void *data2) ePtr font = new gFont("Regular", 30); painter.setFont(font); - - if (!m_page_ok) +/* if (!m_page_ok && !m_dvb_page_ok) painter.renderText(eRect(ePoint(0, 0), size()), "waiting for subtitles...", gPainter::RT_WRAP); - else + else */if (m_page_ok) { int elements = m_page.m_elements.size(); int height = size().height(); @@ -60,6 +68,17 @@ int eSubtitleWidget::event(int event, void *data, void *data2) painter.renderText(eRect(0, size_per_element * i, size().width(), size_per_element), m_page.m_elements[i].m_text, gPainter::RT_WRAP|gPainter::RT_VALIGN_CENTER|gPainter::RT_HALIGN_CENTER); } } + else if (m_dvb_page_ok) + { + painter.setOffset(ePoint(0,0)); +// if (!m_dvb_page.m_regions.size()) +// eDebug("clear screen"); + for (std::list::iterator it(m_dvb_page.m_regions.begin()); it != m_dvb_page.m_regions.end(); ++it) + { + painter.resetClip(eRect(it->m_position, it->m_pixmap->size())); + painter.blit(it->m_pixmap, it->m_position); + } + } return 0; } default: diff --git a/lib/gui/esubtitle.h b/lib/gui/esubtitle.h index 0cd66d2c..ad4b523b 100644 --- a/lib/gui/esubtitle.h +++ b/lib/gui/esubtitle.h @@ -3,6 +3,7 @@ #include #include +#include class eDVBTeletextSubtitlePage; @@ -12,6 +13,7 @@ public: eSubtitleWidget(eWidget *parent); void setPage(const eDVBTeletextSubtitlePage &p); + void setPage(const eDVBSubtitlePage &p); void clearPage(); protected: @@ -20,6 +22,9 @@ protected: private: int m_page_ok; eDVBTeletextSubtitlePage m_page; + + int m_dvb_page_ok; + eDVBSubtitlePage m_dvb_page; }; #endif diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index b729ef7e..b61436c4 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -1146,7 +1146,7 @@ class InfoBarSubtitles: return "Enable Subtitles: " + name def enableSubtitle(self, subtitles): - print "enable subitles", subtitles + print "enable subtitles", subtitles self.selected_subtitle = subtitles self.subtitles_enabled = True @@ -1788,7 +1788,7 @@ class InfoBarSubtitleSupport(object): def setSubtitlesEnable(self, enable=True): subtitle = self.getCurrentServiceSubtitle() - if enable and self.__selected_subtitle: + if enable and self.__selected_subtitle is not None: if subtitle and not self.__subtitles_enabled: subtitle.enableSubtitles(self.subtitle_window.instance, self.selected_subtitle) self.subtitle_window.show() diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index 725909a7..098952bd 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1648,16 +1648,16 @@ void eDVBServicePlay::switchToLive() m_teletext_parser = 0; m_radiotext_parser = 0; m_subtitle_parser = 0; - m_new_dvb_subtitle_region_connection = 0; + m_new_dvb_subtitle_page_connection = 0; m_new_subtitle_page_connection = 0; m_radiotext_updated_connection = 0; /* free the timeshift service handler, we need the resources */ m_service_handler_timeshift.free(); m_timeshift_active = 0; - + m_event((iPlayableService*)this, evSeekableStatusChanged); - + updateDecoder(); } @@ -1665,23 +1665,23 @@ void eDVBServicePlay::switchToTimeshift() { if (m_timeshift_active) return; - + m_decode_demux = 0; m_decoder = 0; m_teletext_parser = 0; m_radiotext_parser = 0; m_subtitle_parser = 0; m_new_subtitle_page_connection = 0; - m_new_dvb_subtitle_region_connection = 0; + m_new_dvb_subtitle_page_connection = 0; m_radiotext_updated_connection = 0; m_timeshift_active = 1; m_event((iPlayableService*)this, evSeekableStatusChanged); - + eServiceReferenceDVB r = (eServiceReferenceDVB&)m_reference; r.path = m_timeshift_file; - + m_cue = new eCueSheet(); m_service_handler_timeshift.tune(r, 1, m_cue); /* use the decoder demux for everything */ updateDecoder(); /* mainly to switch off PCR */ @@ -1709,7 +1709,7 @@ void eDVBServicePlay::updateDecoder() { eDebugNoNewLine(" ("); for (std::vector::const_iterator - i(program.videoStreams.begin()); + i(program.videoStreams.begin()); i != program.videoStreams.end(); ++i) { if (vpid == -1) @@ -1728,7 +1728,7 @@ void eDVBServicePlay::updateDecoder() { eDebugNoNewLine(" ("); for (std::vector::const_iterator - i(program.audioStreams.begin()); + i(program.audioStreams.begin()); i != program.audioStreams.end(); ++i) { if (apid == -1 || (apidtype == eDVBAudio::aMPEG && defaultac3)) @@ -1763,7 +1763,7 @@ void eDVBServicePlay::updateDecoder() m_teletext_parser->connectNewPage(slot(*this, &eDVBServicePlay::newSubtitlePage), m_new_subtitle_page_connection); #endif m_subtitle_parser = new eDVBSubtitleParser(m_decode_demux); - m_subtitle_parser->connectNewRegion(slot(*this, &eDVBServicePlay::newDVBSubtitleRegion), m_new_dvb_subtitle_region_connection); + m_subtitle_parser->connectNewPage(slot(*this, &eDVBServicePlay::newDVBSubtitlePage), m_new_dvb_subtitle_page_connection); } if (m_decoder) @@ -1823,12 +1823,6 @@ void eDVBServicePlay::updateDecoder() m_decoder->setTextPID(tpid); - if (m_teletext_parser) - m_teletext_parser->start(tpid); - -// if (m_subtitle_parser && program.subtitleStreams.size() > 0) -// m_subtitle_parser->start(program.subtitleStreams[0].pid); - if (!m_is_primary) m_decoder->setTrickmode(1); @@ -1997,18 +1991,38 @@ RESULT eDVBServicePlay::enableSubtitles(eWidget *parent, PyObject *entry) if (m_subtitle_widget) disableSubtitles(parent); - if (!m_teletext_parser) - return -1; - if (!PyInt_Check(entry)) return -1; - + + int page = PyInt_AsLong(entry); + + if (page > 0 && !m_teletext_parser) + return -1; + if (page < 0 && !m_subtitle_parser) + return -1; + m_subtitle_widget = new eSubtitleWidget(parent); m_subtitle_widget->resize(parent->size()); /* full size */ - - int page = PyInt_AsLong(entry); - - m_teletext_parser->setPage(page); + + if (page > 0) + { + eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; + eDVBServicePMTHandler::program program; + if (h.getProgramInfo(program)) + eDebug("getting program info failed."); + else + { + eDebug("start teletext on pid %04x, page %d", program.textPid, page); + m_teletext_parser->start(program.textPid); + m_teletext_parser->setPage(page); + } + } + else + { + int pid = -page; + eDebug("start dvb subtitles on pid %04x", pid); + m_subtitle_parser->start(pid); + } return 0; } @@ -2038,8 +2052,28 @@ PyObject *eDVBServicePlay::getSubtitleList() PyTuple_SetItem(tuple, 0, PyString_FromString(desc)); PyTuple_SetItem(tuple, 1, PyInt_FromLong(*i)); PyList_Append(l, tuple); + Py_DECREF(tuple); } - + + eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; + eDVBServicePMTHandler::program program; + if (h.getProgramInfo(program)) + eDebug("getting program info failed."); + else + { + for (std::vector::iterator it(program.subtitleStreams.begin()); + it != program.subtitleStreams.end(); ++it) + { + PyObject *tuple = PyTuple_New(2); + char desc[20]; + sprintf(desc, "DVB %s", it->language_code.c_str()); + PyTuple_SetItem(tuple, 0, PyString_FromString(desc)); + PyTuple_SetItem(tuple, 1, PyInt_FromLong(-it->pid)); + PyList_Append(l, tuple); + Py_DECREF(tuple); + } + } + return l; } @@ -2048,26 +2082,41 @@ void eDVBServicePlay::newSubtitlePage(const eDVBTeletextSubtitlePage &page) if (m_subtitle_widget) { m_subtitle_pages.push_back(page); - checkSubtitleTiming(); } } void eDVBServicePlay::checkSubtitleTiming() { +// eDebug("checkSubtitleTiming"); while (1) { - if (m_subtitle_pages.empty()) + enum { TELETEXT, DVB } type; + eDVBTeletextSubtitlePage page; + eDVBSubtitlePage dvb_page; + pts_t show_time; + if (!m_subtitle_pages.empty()) + { + page = m_subtitle_pages.front(); + type = TELETEXT; + show_time = page.m_pts; + } + else if (!m_dvb_subtitle_pages.empty()) + { + dvb_page = m_dvb_subtitle_pages.front(); + type = DVB; + show_time = dvb_page.m_show_time; + } + else return; - eDVBTeletextSubtitlePage p = m_subtitle_pages.front(); - pts_t pos = 0; if (m_decoder) m_decoder->getPTS(0, pos); - - int diff = p.m_pts - pos; + +// eDebug("%lld %lld", pos, show_time); + int diff = show_time - pos; if (diff < 0) { eDebug("[late (%d ms)]", -diff / 90); @@ -2081,24 +2130,34 @@ void eDVBServicePlay::checkSubtitleTiming() if (!diff) { - m_subtitle_widget->setPage(p); - m_subtitle_pages.pop_front(); + if (type == TELETEXT) + { + eDebug("display teletext subtitle page"); + m_subtitle_widget->setPage(page); + m_subtitle_pages.pop_front(); + } + else + { + eDebug("display dvb subtitle Page"); + m_subtitle_widget->setPage(dvb_page); + m_dvb_subtitle_pages.pop_front(); + } } else { + eDebug("start subtitle delay %d", diff / 90); m_subtitle_sync_timer.start(diff / 90, 1); break; } } } -void eDVBServicePlay::newDVBSubtitleRegion(const eDVBSubtitleRegion &p) -{ - eDebug("new dvb subtitle region"); -} - -void eDVBServicePlay::checkDvbSubtitleTiming() +void eDVBServicePlay::newDVBSubtitlePage(const eDVBSubtitlePage &p) { - eDebug("check dvb subtitle timing"); + if (m_subtitle_widget) + { + m_dvb_subtitle_pages.push_back(p); + checkSubtitleTiming(); + } } int eDVBServicePlay::getAC3Delay() diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index d55cdd85..62d34169 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -245,17 +245,16 @@ private: ePtr m_teletext_parser; void newSubtitlePage(const eDVBTeletextSubtitlePage &p); ePtr m_new_subtitle_page_connection; - eTimer m_subtitle_sync_timer; std::list m_subtitle_pages; - void checkSubtitleTiming(); /* dvb subtitles */ ePtr m_subtitle_parser; - void newDVBSubtitleRegion(const eDVBSubtitleRegion &p); - ePtr m_new_dvb_subtitle_region_connection; - eTimer m_dvb_subtitle_sync_timer; - std::list m_dvb_subtitle_regions; - void checkDvbSubtitleTiming(); + void newDVBSubtitlePage(const eDVBSubtitlePage &p); + ePtr m_new_dvb_subtitle_page_connection; + std::list m_dvb_subtitle_pages; + + eTimer m_subtitle_sync_timer; + void checkSubtitleTiming(); /* radiotext */ ePtr m_radiotext_parser; -- 2.30.2