dvb subtitles are working now
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Wed, 25 Oct 2006 18:06:01 +0000 (18:06 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Wed, 25 Oct 2006 18:06:01 +0000 (18:06 +0000)
lib/dvb/subtitle.cpp
lib/dvb/subtitle.h
lib/dvb/teletext.cpp
lib/dvb/teletext.h
lib/gui/esubtitle.cpp
lib/gui/esubtitle.h
lib/python/Screens/InfoBarGenerics.py
lib/service/servicedvb.cpp
lib/service/servicedvb.h

index eae7205619421c368d538d2e0aeeb3d4b05e183f..23ea6dce11edaa6d50cbedddd8735b546db25241 100644 (file)
@@ -11,7 +11,7 @@
 #include <lib/base/eerror.h>
 #include <lib/gdi/gpixmap.h>
 
-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 = &region->region_objects;
+               subtitle_region_object **pobject = &region->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<clut_size; ++i)
+                               {
+                                       if (entries[i].valid)
+                                       {
+                                               int y = entries[i].Y,
+                                                       cr = entries[i].Cr,
+                                                       cb = entries[i].Cb;
+                                               if (y > 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<void, const eDVBSubtitleRegion&> &slot, ePtr<eConnection> &connection)
+void eDVBSubtitleParser::connectNewPage(const Slot1<void, const eDVBSubtitlePage&> &slot, ePtr<eConnection> &connection)
 {
-       connection = new eConnection(this, m_new_subtitle_region.connect(slot));
+       connection = new eConnection(this, m_new_subtitle_page.connect(slot));
 }
index 6faad507e6eb582444ad0ad6050b81e95f15ce73..330147adb67860757bc6646457f13c1712383461 100644 (file)
@@ -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<gPixmap> region;
+       ePtr<gPixmap> 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<eDVBSubtitleRegion> 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<iDVBPESReader> m_pes_reader;
        ePtr<eConnection> m_read_connection;
        pts_t show_time;
-       Signal1<void,const eDVBSubtitleRegion&> m_new_subtitle_region;
+       Signal1<void,const eDVBSubtitlePage&> m_new_subtitle_page;
 public:
        eDVBSubtitleParser(iDVBDemux *demux);
        virtual ~eDVBSubtitleParser();
        int start(int pid);
-       void connectNewRegion(const Slot1<void, const eDVBSubtitleRegion&> &slot, ePtr<eConnection> &connection);
+       void connectNewPage(const Slot1<void, const eDVBSubtitlePage&> &slot, ePtr<eConnection> &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);
index 2a44f4f9bdd1fbc4629d9537f53985b868de8be8..0515913a1066aa81dc0ebdb1b4a19b7f9ce13002 100644 (file)
@@ -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 */
 }
index af9d71f1709627b9960efd72b3569773a4138e42..821a92261cbb23f83be0f81ec74b991ffb60d68d 100644 (file)
@@ -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);
index 167325d8b4af4a694602794f6828b3396c741b9d..f0b899f750d2f2dc102078b67be458d089a25163 100644 (file)
@@ -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<gFont> 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<eDVBSubtitleRegion>::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:
index 0cd66d2ca157a6ed720369e649a7067490031e91..ad4b523bc9a88539d8779af29dc6717d1d092a40 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <lib/gui/ewidget.h>
 #include <lib/dvb/teletext.h>
+#include <lib/dvb/subtitle.h>
 
 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
index b729ef7ee1f6f0c0bceafbbd9c713d7e66bdbfd1..b61436c44c3df3a826d7ebbdeb85f9576aeeec34 100644 (file)
@@ -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()
index 725909a71beb5291ecaecd38341841c552e70e06..098952bddca95eee3f3356ec5ceb1c0de6e43934 100644 (file)
@@ -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<eDVBServicePMTHandler::videoStream>::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<eDVBServicePMTHandler::audioStream>::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<eDVBServicePMTHandler::subtitleStream>::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()
index d55cdd8562c5b5dd53f047a2405ac489ac11f311..62d341692609bd11dc20bc25ae0e6febe270e43e 100644 (file)
@@ -245,17 +245,16 @@ private:
        ePtr<eDVBTeletextParser> m_teletext_parser;
        void newSubtitlePage(const eDVBTeletextSubtitlePage &p);
        ePtr<eConnection> m_new_subtitle_page_connection;
-       eTimer m_subtitle_sync_timer;
        std::list<eDVBTeletextSubtitlePage> m_subtitle_pages;
-       void checkSubtitleTiming();
        
                /* dvb subtitles */
        ePtr<eDVBSubtitleParser> m_subtitle_parser;
-       void newDVBSubtitleRegion(const eDVBSubtitleRegion &p);
-       ePtr<eConnection> m_new_dvb_subtitle_region_connection;
-       eTimer m_dvb_subtitle_sync_timer;
-       std::list<eDVBSubtitleRegion> m_dvb_subtitle_regions;
-       void checkDvbSubtitleTiming();
+       void newDVBSubtitlePage(const eDVBSubtitlePage &p);
+       ePtr<eConnection> m_new_dvb_subtitle_page_connection;
+       std::list<eDVBSubtitlePage> m_dvb_subtitle_pages;
+
+       eTimer m_subtitle_sync_timer;
+       void checkSubtitleTiming();
 
                /* radiotext */
        ePtr<eDVBRadioTextParser> m_radiotext_parser;