Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Updated] Optimized DVB subtitles handling code #1089

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 44 additions & 12 deletions lib/dvb/subtitle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,10 @@ int eDVBSubtitleParser::subtitle_process_pixel_data(subtitle_region *region, sub
return 0;
}

int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)
int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment, bool isBufferProcess)
{
int segment_type, page_id, segment_length, processed_length;
if (*segment++ != 0x0F)
if (*segment++ != DVB_SUB_SYNC_BYTE)
{
eDebug("[eDVBSubtitleParser] out of sync.");
return -1;
Expand All @@ -267,9 +267,9 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)
page_id |= *segment++;
segment_length = *segment++ << 8;
segment_length |= *segment++;
if (segment_type == 0xFF)
if (segment_type == DVB_SUB_SEGMENT_STUFFING)
return segment_length + 6;
if (page_id != m_composition_page_id && page_id != m_ancillary_page_id)
if (page_id != m_composition_page_id && page_id != m_ancillary_page_id && !isBufferProcess)
return segment_length + 6;

subtitle_page *page, **ppage;
Expand All @@ -288,7 +288,7 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)

switch (segment_type)
{
case 0x10: // page composition segment
case DVB_SUB_SEGMENT_PAGE_COMPOSITION:
{
int page_time_out = *segment++; processed_length++;
int page_version_number = *segment >> 4;
Expand Down Expand Up @@ -380,7 +380,7 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)

break;
}
case 0x11: // region composition segment
case DVB_SUB_SEGMENT_REGION_COMPOSITION:
{
int region_id = *segment++; processed_length++;
int version_number = *segment >> 4;
Expand Down Expand Up @@ -518,7 +518,7 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)

break;
}
case 0x12: // CLUT definition segment
case DVB_SUB_SEGMENT_CLUT_DEFINITION:
{
int CLUT_id, CLUT_version_number;
subtitle_clut *clut, **pclut;
Expand Down Expand Up @@ -620,7 +620,7 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)
}
break;
}
case 0x13: // object data segment
case DVB_SUB_SEGMENT_OBJECT_DATA:
{
int object_id;
int object_coding_method;
Expand Down Expand Up @@ -717,7 +717,7 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)
}
break;
}
case 0x14: // display definition segment
case DVB_SUB_SEGMENT_DISPLAY_DEFINITION:
{
if (segment_length > 4)
{
Expand Down Expand Up @@ -749,12 +749,12 @@ int eDVBSubtitleParser::subtitle_process_segment(uint8_t *segment)
eDebug("[eDVBSubtitleParser] display definition segment to short %d!", segment_length);
break;
}
case 0x80: // end of display set segment
case DVB_SUB_SEGMENT_END_OF_DISPLAY_SET:
{
subtitle_redraw_all();
m_seen_eod = true;
}
case 0xFF: // stuffing
case DVB_SUB_SEGMENT_STUFFING:
break;
default:
eDebug("[eDVBSubtitleParser] unhandled segment type %02x", segment_type);
Expand Down Expand Up @@ -787,7 +787,7 @@ void eDVBSubtitleParser::subtitle_process_pes(uint8_t *pkt, int len)

m_seen_eod = false;

while (len && *pkt == 0x0F)
while (len && *pkt == DVB_SUB_SYNC_BYTE)
{
int l = subtitle_process_segment(pkt);
if (l < 0)
Expand All @@ -801,6 +801,34 @@ void eDVBSubtitleParser::subtitle_process_pes(uint8_t *pkt, int len)
}
}

void eDVBSubtitleParser::processBuffer(uint8_t *data, size_t len, pts_t pts)
{
m_show_time = pts;

if (*data != 0x20) {
eWarning("[eDVBSubtitleParser] Tried to handle a PES packet private data that isn't a subtitle packet (does not start with 0x20)");
return;
}

data++; len--; // data identifier
data++; len--; // stream id;


m_seen_eod = false;
while (len && *data == DVB_SUB_SYNC_BYTE)
{
int l = subtitle_process_segment(data, true);
if (l < 0)
break;
data += l;
len -= l;
}

if (len && *data != DVB_SUB_SEGMENT_STUFFING)
eDebug("[eDVBSubtitleParser] strange data at the end");

}


void eDVBSubtitleParser::subtitle_redraw_all()
{
Expand Down Expand Up @@ -1067,6 +1095,10 @@ void eDVBSubtitleParser::subtitle_redraw(int page_id)

DEFINE_REF(eDVBSubtitleParser);

eDVBSubtitleParser::eDVBSubtitleParser()
:m_pages(0), m_display_size(720,576)
{ }

eDVBSubtitleParser::eDVBSubtitleParser(iDVBDemux *demux)
:m_pages(0), m_display_size(720,576)
{
Expand Down
14 changes: 13 additions & 1 deletion lib/dvb/subtitle.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@
#include <lib/dvb/pesparse.h>
#include <lib/gdi/gpixmap.h>

#define DVB_SUB_SEGMENT_PAGE_COMPOSITION 0x10
#define DVB_SUB_SEGMENT_REGION_COMPOSITION 0x11
#define DVB_SUB_SEGMENT_CLUT_DEFINITION 0x12
#define DVB_SUB_SEGMENT_OBJECT_DATA 0x13
#define DVB_SUB_SEGMENT_DISPLAY_DEFINITION 0x14
#define DVB_SUB_SEGMENT_END_OF_DISPLAY_SET 0x80
#define DVB_SUB_SEGMENT_STUFFING 0xFF

#define DVB_SUB_SYNC_BYTE 0x0F

struct subtitle_clut_entry
{
uint8_t Y, Cr, Cb, T;
Expand Down Expand Up @@ -121,15 +131,17 @@ class eDVBSubtitleParser
bool m_seen_eod;
eSize m_display_size;
public:
eDVBSubtitleParser();
eDVBSubtitleParser(iDVBDemux *demux);
virtual ~eDVBSubtitleParser();
int start(int pid, int composition_page_id, int ancillary_page_id);
void processBuffer(uint8_t *data, size_t len, pts_t pts);
int stop();
void connectNewPage(const sigc::slot<void(const eDVBSubtitlePage&)> &slot, ePtr<eConnection> &connection);
private:
void subtitle_process_line(subtitle_region *region, subtitle_region_object *object, int line, uint8_t *data, int len);
int subtitle_process_pixel_data(subtitle_region *region, subtitle_region_object *object, int *linenr, int *linep, uint8_t *data);
int subtitle_process_segment(uint8_t *segment);
int subtitle_process_segment(uint8_t *segment, bool isBufferProcess=false);
void subtitle_process_pes(uint8_t *buffer, int len);
void subtitle_redraw_all();
void subtitle_reset();
Expand Down
Loading