subtitle.cpp/h: fix dvb subtitles for HBO
[enigma2.git] / lib / dvb / subtitle.cpp
index 23ea6dce11edaa6d50cbedddd8735b546db25241..642327bb0e522d5c1275767b3f91a0eef37f5103 100644 (file)
@@ -80,6 +80,7 @@ void eDVBSubtitleParser::subtitle_process_line(subtitle_page *page, int object_i
                                        break;
                                }
 //                             //eDebug("inserting %d bytes (into region %d)", len, region->region_id);
+//                             eDebug("put data to region_buffer %p", &(*region->region_buffer));
                                memcpy((__u8*)region->region_buffer->surface->data + region->region_width * y + x, data, len);
                        }
                        object = object->next;
@@ -287,13 +288,15 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
        segment_length |= *segment++;
        if (segment_type == 0xFF)
                return segment_length + 6;
-//     //eDebug("have %d bytes of segment data", segment_length);
+       if (page_id != m_composition_page_id && page_id != m_ancillary_page_id)
+               return segment_length + 6;
+       //eDebug("have %d bytes of segment data", segment_length);
 
-//     //eDebug("page_id %d, segtype %02x", page_id, segment_type);
+       //eDebug("page_id %d, segtype %02x", page_id, segment_type);
 
        subtitle_page *page, **ppage;
 
-       page = this->pages; ppage = &this->pages;
+       page = m_pages; ppage = &m_pages;
 
        while (page)
        {
@@ -337,24 +340,42 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
                                // if no update, just skip this data.
                        if (page->page_version_number == page_version_number)
                        {
-                               eDebug("skip data... ");
+//                             eDebug("skip data... ");
                                break;
                        }
                }
 
-//             eDebug("page updated: old: %d, new: %d", page->page_version_number, page_version_number);
+               page->state = page_state;
+
+               //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)
                        {
                                subtitle_page_region *p = page->page_regions->next;
+                               //eDebug("delete page_region %d", page->page_regions->region_id);
                                delete page->page_regions;
                                page->page_regions = p;
                        }
+                       while (page->regions)
+                       {
+                               subtitle_region *p = page->regions->next;
+                               //eDebug("delete region %d", page->regions->region_id);
+                               while(page->regions->region_objects)
+                               {
+                                       //eDebug("delete region object");
+                                       subtitle_region_object *ob = page->regions->region_objects->next;
+                                       delete page->regions->region_objects;
+                                       page->regions->region_objects = ob;
+                               }
+                               delete page->regions;
+                               page->regions = p;
+                       }
+
                }
 
-//             eDebug("new page.. (%d)", page_state);
+               //eDebug("new page.. (%d)", page_state);
 
                page->page_time_out = page_time_out;
 
@@ -368,6 +389,12 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
                while (*r)
                        r = &(*r)->next;
 
+               if (processed_length == segment_length && !page->page_regions)
+               {
+                       //eDebug("no regions in page.. clear screen!!");
+                       subtitle_redraw(page->page_id);
+               }
+
                while (processed_length < segment_length)
                {
                        subtitle_page_region *pr;
@@ -425,12 +452,15 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
 
                if (!region)
                {
+                       //eDebug("create region !!!!!!!!!!");
                        *pregion = region = new subtitle_region;
                        region->next = 0;
+                       region->committed = false;
                }
                else if (region->region_version_number != region_version_number)
                {
                        subtitle_region_object *objects = region->region_objects;
+                       //eDebug("unequal version %p %p", objects, objects?objects->next:objects);
                        while (objects)
                        {
                                subtitle_region_object *n = objects->next;
@@ -439,10 +469,10 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
                        }
                        if (region->region_buffer)
                        {
-                               if (region->region_buffer->surface)
-                                       delete region->region_buffer->surface;
+                               //eDebug("no more need of region_buffer %p", &(*region->region_buffer));
                                region->region_buffer=0;
                        }
+                       region->committed = false;
                }
                else
                        break;
@@ -461,6 +491,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
                processed_length += 2;
 
                region->region_buffer = new gPixmap(eSize(region->region_width, region->region_height), 8);
+               //eDebug("new region_buffer %p", &(*region->region_buffer));
 
                int region_level_of_compatibility, region_depth;
 
@@ -487,6 +518,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
 
                if (region_fill_flag)
                {
+                       //eDebug("region fill region_buffer %p", &(*region->region_buffer));
                        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)
@@ -663,7 +695,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
 
                        bottom_field_data_blocklength  = *segment++ << 8;
                        bottom_field_data_blocklength |= *segment++;
-                       //eDebug("%d / %d bytes", top_field_data_blocklength, bottom_field_data_blocklength);
+                       eDebug("%d / %d bytes", top_field_data_blocklength, bottom_field_data_blocklength);
                        processed_length += 4;
 
                        i = 0;
@@ -712,7 +744,7 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
        }
        case 0x80: // end of display set segment
        {
-//             eDebug("end of display set segment");
+               //eDebug("end of display set segment");
                subtitle_redraw_all();
        }
        case 0xFF: // stuffing
@@ -726,9 +758,10 @@ int eDVBSubtitleParser::subtitle_process_segment(__u8 *segment)
 
 void eDVBSubtitleParser::subtitle_process_pes(__u8 *pkt, int len)
 {
-//     eDebug("subtitle_process_pes");
-       if (!extract_pts(show_time, pkt))
+       eDebugNoNewLine("subtitle_process_pes");
+       if (!extract_pts(m_show_time, pkt))
        {
+               eDebug(" %lld", m_show_time);
                pkt += 6; len -= 6;
                // skip PES header
                pkt++; len--;
@@ -760,54 +793,55 @@ void eDVBSubtitleParser::subtitle_process_pes(__u8 *pkt, int len)
                        pkt += l;
                        len -= l;
                }
-       //      if (len && *pkt != 0xFF)
-       //              eDebug("strange data at the end");
+               if (len && *pkt != 0xFF)
+                       eDebug("strange data at the end");
        }
        else
-               eDebug("dvb subtitle packet without PTS.. ignore!!");
+               eDebug("\ndvb subtitle packet without PTS.. ignore!!");
 }
 
 void eDVBSubtitleParser::subtitle_redraw_all()
 {
 #if 1
-       subtitle_page *page = this->pages;
+       subtitle_page *page = m_pages;
        while(page)
        {
-               subtitle_redraw(page->page_id);
+               if (page->state != 0)
+                       subtitle_redraw(page->page_id);
                page = page->next;
        }
 #else
-       subtitle_page *page = this->pages;
-       //eDebug("----------- end of display set");
-       //eDebug("active pages:");
+       subtitle_page *page = m_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:");
+               eDebug("  page_id %02x", page->page_id);
+               eDebug("  page_version_number: %d", page->page_version_number);
+               eDebug("  active regions:");
                {
                        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);
+                               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:");
+               eDebug("defined 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);
+                       eDebug("  region_id %04x, version %d, %dx%d", region->region_id, region->region_version_number, region->region_width, region->region_height);
 
                        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);
+                               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;
@@ -819,7 +853,7 @@ void eDVBSubtitleParser::subtitle_redraw_all()
 
 void eDVBSubtitleParser::subtitle_reset()
 {
-       while (subtitle_page *page = this->pages)
+       while (subtitle_page *page = m_pages)
        {
                        /* free page regions */
                while (page->page_regions)
@@ -842,8 +876,7 @@ void eDVBSubtitleParser::subtitle_reset()
 
                        if (region->region_buffer)
                        {
-                               if (region->region_buffer->surface)
-                                       delete region->region_buffer->surface;
+//                             eDebug("no more need of region_buffer 2 %p", &(*region->region_buffer));
                                region->region_buffer=0;
                        }
 
@@ -859,16 +892,16 @@ void eDVBSubtitleParser::subtitle_reset()
                        delete clut;
                }
 
-               this->pages = page->next;
+               m_pages = page->next;
                delete page;
        }
 }
 
 void eDVBSubtitleParser::subtitle_redraw(int page_id)
 {
-       subtitle_page *page = this->pages;
+       subtitle_page *page = m_pages;
 
-       //eDebug("displaying page id %d", page_id);
+//     eDebug("displaying page id %d", page_id);
 
        while (page)
        {
@@ -887,7 +920,7 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id)
        subtitle_page_region *region = page->page_regions;
 
        eDVBSubtitlePage Page;
-       Page.m_show_time = show_time;
+       Page.m_show_time = m_show_time;
        for (; region; region=region->next)
        {
 //             eDebug("region %d", region->region_id);
@@ -901,12 +934,12 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id)
                }
                if (reg)
                {
+                       if (reg->committed)
+                               continue;
 //                     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))
                        {
@@ -928,15 +961,8 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id)
                        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)
-                       {
-                               delete [] reg->region_buffer->surface->clut.data;
-                               reg->region_buffer->surface->clut.data = 0;
-                       }
-
-                       if (!reg->region_buffer->surface->clut.data)
-                               reg->region_buffer->surface->clut.data = new gRGB[clut_size];
+                       reg->region_buffer->surface->clut.data = new gRGB[clut_size];
+//                     eDebug("create clut data for region_buffer %p", &(*reg->region_buffer));
 
                        gRGB *palette = reg->region_buffer->surface->clut.data;
 
@@ -1077,12 +1103,14 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id)
                                        }
                                }
                        }
-                       
+
+//                     eDebug("commit region_buffer %p", &(*reg->region_buffer));
                        eDVBSubtitleRegion Region;
                        Region.m_pixmap = reg->region_buffer;
                        Region.m_position.setX(x0);
                        Region.m_position.setY(y0);
                        Page.m_regions.push_back(Region);
+                       reg->committed = true;
                }
                else
                        eDebug("region not found");
@@ -1098,7 +1126,7 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id)
 DEFINE_REF(eDVBSubtitleParser);
 
 eDVBSubtitleParser::eDVBSubtitleParser(iDVBDemux *demux)
-       :pages(0)
+       :m_pages(0)
 {
        setStreamID(0xBD);
 
@@ -1113,15 +1141,27 @@ eDVBSubtitleParser::~eDVBSubtitleParser()
        subtitle_reset();
 }
 
-int eDVBSubtitleParser::start(int pid)
+int eDVBSubtitleParser::stop()
+{
+       if (m_pes_reader)
+       {
+               eDebug("disable dvb subtitles");
+               return m_pes_reader->stop();
+       }
+       return -1;
+}
+
+int eDVBSubtitleParser::start(int pid, int composition_page_id, int ancillary_page_id)
 {
-#if 1
-       eDebug("eDVBSubtitleParser::start(%04x)", pid);
        if (m_pes_reader)
+       {
+               eDebug("start dvb subtitles on pid 0x%04x with composition_page_id %d and ancillary_page_id %d",
+                       pid, composition_page_id, ancillary_page_id);
+               m_composition_page_id = composition_page_id;
+               m_ancillary_page_id = ancillary_page_id;
                return m_pes_reader->start(pid);
-       else
-               return -1;
-#endif
+       }
+       return -1;
 }
 
 void eDVBSubtitleParser::connectNewPage(const Slot1<void, const eDVBSubtitlePage&> &slot, ePtr<eConnection> &connection)