https://bugs.gentoo.org/970993 From 1b12d63b4414de80ebf5561823b6a0ac8b734eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 25 Feb 2026 17:22:52 +0200 Subject: [PATCH 1/3] dvbsuboverlay: Mark parsed byte array as const Part-of: --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -373,8 +373,8 @@ dvb_sub_init (void) } static void -_dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, - gint buf_size) +_dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, + const guint8 * buf, gint buf_size) { /* FIXME: Use guint for buf_size here and in many other places? */ DVBSubRegionDisplay *display; DVBSubRegionDisplay *tmp_display_list, **tmp_ptr; @@ -451,8 +451,8 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, } static void -_dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, - gint buf_size) +_dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, + const guint8 * buf, gint buf_size) { const guint8 *buf_end = buf + buf_size; guint8 region_id; @@ -574,8 +574,8 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, } static void -_dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, - gint buf_size) +_dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, + const guint8 * buf, gint buf_size) { const guint8 *buf_end = buf + buf_size; guint8 clut_id; @@ -1076,8 +1076,8 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, } static void -_dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, - gint buf_size) +_dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, + const guint8 * buf, gint buf_size) { const guint8 *buf_end = buf + buf_size; guint object_id; @@ -1147,7 +1147,7 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, } static gint -_dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, guint8 * buf, +_dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, const guint8 * buf, gint buf_size) { int dds_version, info_byte; @@ -1386,7 +1386,8 @@ dvb_sub_free (DvbSub * sub) * 0 or positive if data was handled. If positive, then amount of data consumed on success. FIXME: List the positive return values. */ gint -dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) +dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, const guint8 * data, + gint len) { unsigned int pos = 0; guint8 segment_type; --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -129,7 +129,7 @@ typedef struct { DvbSub *dvb_sub_new (void); void dvb_sub_free (DvbSub * sub); -gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len); +gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, const guint8 *data, gint len); void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data); void dvb_subtitles_free (DVBSubtitles *sub); -- GitLab From 3b8253f447bcc9831dbf643d2c69b205fedbe086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 11 Feb 2026 20:45:12 +0200 Subject: [PATCH 2/3] dvbsuboverlay: Add missing bounds checks to the parser everywhere Fixes SA-2026-0007, ZDI-CAN-28838, CVE-2026-2923. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/4897 Part-of: --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -585,6 +585,9 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, GST_MEMDUMP ("DVB clut packet", buf, buf_size); + if (buf_size < 1) + return; + clut_id = *buf++; buf += 1; @@ -601,7 +604,7 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, dvb_sub->clut_list = clut; } - while (buf + 4 < buf_end) { + while (buf + 2 < buf_end) { entry_id = *buf++; depth = (*buf) & 0xe0; @@ -614,11 +617,15 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, full_range = (*buf++) & 1; if (full_range) { + if (buf + 4 > buf_end) + break; y = *buf++; cr = *buf++; cb = *buf++; alpha = *buf++; } else { + if (buf + 2 > buf_end) + break; y = buf[0] & 0xfc; cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; cb = (buf[1] << 2) & 0xf0; @@ -633,11 +640,11 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, y, cb, cr, alpha); - if (depth & 0x80) + if ((depth & 0x80) && entry_id < 4) clut->clut4[entry_id] = AYUV (y, cb, cr, 255 - alpha); - if (depth & 0x40) + if ((depth & 0x40) && entry_id < 16) clut->clut16[entry_id] = AYUV (y, cb, cr, 255 - alpha); - if (depth & 0x20) + if ((depth & 0x20) && entry_id < 256) clut->clut256[entry_id] = AYUV (y, cb, cr, 255 - alpha); } } @@ -649,8 +656,6 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table) { GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size); - /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */ - gboolean stop_parsing = FALSE; guint32 bits = 0; guint32 pixels_read = 0; @@ -661,23 +666,29 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 1)) { guint run_length = 0, clut_index = 0; - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 2)) + goto not_enough_data; if (bits) { /* 2-bit_pixel-code */ run_length = 1; clut_index = bits; } else { /* 2-bit_zero */ - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1)) + goto not_enough_data; if (bits == 1) { /* switch_1 == '1' */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 3); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3)) + goto not_enough_data; run_length += 3; - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2)) + goto not_enough_data; } else { /* switch_1 == '0' */ - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1)) + goto not_enough_data; if (bits == 1) { /* switch_2 == '1' */ run_length = 1; /* 1x pseudo-colour '00' */ } else { /* switch_2 == '0' */ - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 2)) + goto not_enough_data; switch (bits) { /* switch_3 */ case 0x0: /* end of 2-bit/pixel_code_string */ stop_parsing = TRUE; @@ -686,14 +697,18 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, run_length = 2; break; case 0x2: /* the following 6 bits contain run length coded pixel data */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4)) + goto not_enough_data; run_length += 12; - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2)) + goto not_enough_data; break; case 0x3: /* the following 10 bits contain run length coded pixel data */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8)) + goto not_enough_data; run_length += 29; - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2)) + goto not_enough_data; break; } } @@ -727,13 +742,18 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, pixels_read += run_length; } - // FIXME: Test skip_to_byte instead of adding 7 bits, once everything else is working good - //gst_bit_reader_skip_to_byte (&gb); - *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; + gst_bit_reader_skip_to_byte (&gb); + *srcbuf = gb.data + gb.byte; GST_TRACE ("PIXEL: returning, read %u pixels", pixels_read); // FIXME: Shouldn't need this variable if tracking things in the loop better return pixels_read; + +not_enough_data: + GST_WARNING ("Not enough data"); + // Go to the end of the buffer so the caller stops parsing + *srcbuf += buf_size; + return 0; } // FFMPEG-FIXME: The same code in ffmpeg is much more complex, it could use the same @@ -743,7 +763,6 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table) { GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size); - /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */ gboolean stop_parsing = FALSE; guint32 bits = 0; guint32 pixels_read = 0; @@ -755,28 +774,35 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 3)) { guint run_length = 0, clut_index = 0; - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 4)) + goto not_enough_data; if (bits) { run_length = 1; clut_index = bits; } else { - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1)) + goto not_enough_data; if (bits == 0) { /* switch_1 == '0' */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 3); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3)) + goto not_enough_data; if (!run_length) { stop_parsing = TRUE; } else { run_length += 2; } } else { /* switch_1 == '1' */ - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1)) + goto not_enough_data; if (bits == 0) { /* switch_2 == '0' */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 2)) + goto not_enough_data; run_length += 4; - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4); + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4)) + goto not_enough_data; } else { /* switch_2 == '1' */ - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 2)) + goto not_enough_data; switch (bits) { case 0x0: /* switch_3 == '00' */ run_length = 1; /* 1 pixel of pseudo-color 0 */ @@ -785,14 +811,18 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, run_length = 2; /* 2 pixels of pseudo-color 0 */ break; case 0x2: /* switch_3 == '10' */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4)) + goto not_enough_data; run_length += 9; - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4); + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4)) + goto not_enough_data; break; case 0x3: /* switch_3 == '11' */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8)) + goto not_enough_data; run_length += 25; - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4); + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4)) + goto not_enough_data; break; } } @@ -826,14 +856,19 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, pixels_read += run_length; } - // FIXME: Test skip_to_byte instead of adding 7 bits, once everything else is working good - //gst_bit_reader_skip_to_byte (&gb); - *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; + gst_bit_reader_skip_to_byte (&gb); + *srcbuf = gb.data + gb.byte; GST_LOG ("Returning with %u pixels read", pixels_read); // FIXME: Shouldn't need this variable if tracking things in the loop better return pixels_read; + +not_enough_data: + GST_WARNING ("Not enough data"); + // Go to the end of the buffer so the caller stops parsing + *srcbuf += buf_size; + return 0; } static int @@ -841,8 +876,6 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table) { GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size); - /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */ - gboolean stop_parsing = FALSE; guint32 bits = 0; guint32 pixels_read = 0; @@ -858,23 +891,29 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, /* Rephrased - it's better to work with bytes with default value '0' instead of reading from memory we don't own. */ while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 7)) { guint run_length = 0, clut_index = 0; - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8); + + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 8)) + goto not_enough_data; if (bits) { /* 8-bit_pixel-code */ run_length = 1; clut_index = bits; } else { /* 8-bit_zero */ - bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1); + if (!gst_bit_reader_get_bits_uint32 (&gb, &bits, 1)) + goto not_enough_data; if (bits == 0) { /* switch_1 == '0' */ /* run_length_1-127 for pseudo-colour _entry) '0x00' */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 7); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7)) + goto not_enough_data; if (run_length == 0) { /* end_of_string_signal */ stop_parsing = TRUE; } } else { /* switch_1 == '1' */ /* run_length_3-127 */ - run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 7); - clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8); + if (!gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7)) + goto not_enough_data; + if (!gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 8)) + goto not_enough_data; if (run_length < 3) { GST_WARNING ("runlength value was %u, but the spec requires it " @@ -912,10 +951,17 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, GST_LOG ("Returning with %u pixels read", pixels_read); - *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; + gst_bit_reader_skip_to_byte (&gb); + *srcbuf = gb.data + gb.byte; // FIXME: Shouldn't need this variable if tracking things in the loop better return pixels_read; + +not_enough_data: + GST_WARNING ("Not enough data"); + // Go to the end of the buffer so the caller stops parsing + *srcbuf += buf_size; + return 0; } static void @@ -928,7 +974,6 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, guint8 *pbuf; int x_pos, y_pos; int i; - gboolean dest_buf_filled = FALSE; guint8 map2to4[] = { 0x0, 0x7, 0x8, 0xf }; guint8 map2to8[] = { 0x00, 0x77, 0x88, 0xff }; @@ -963,24 +1008,13 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, // FFMPEG-FIXME: ffmpeg doesn't check for equality and so can overflow destination buffer later on with bad input data // FFMPEG-FIXME: However that makes it warn on end_of_object_line and map tables as well, so we add the dest_buf_filled tracking - // FIXME: Removed x_pos checking here, because we don't want to turn dest_buf_filled to TRUE permanently in that case - // FIXME: We assume that region->width - x_pos as dbuf_len to read_nbit_string will take care of that case nicely; - // FIXME: That is, that read_nbit_string never scribbles anything if dbuf_len passed to it is zero due to this. - if (y_pos >= region->height) { - dest_buf_filled = TRUE; + if (x_pos >= region->width || y_pos >= region->height) { + GST_WARNING ("Invalid object location for data_type 0x%x!", *buf); + return; } switch (*buf++) { case 0x10: - if (dest_buf_filled) { - /* FIXME: Be more verbose */ - GST_WARNING ("Invalid object location for data_type 0x%x!", - *(buf - 1)); - GST_MEMDUMP ("Remaining data after invalid object location:", buf, - (guint) (buf_end - buf)); - return; - } - if (region->depth == 8) map_table = map2to8; else if (region->depth == 4) @@ -995,15 +1029,6 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, region->width - x_pos, &buf, buf_end - buf, non_mod, map_table); break; case 0x11: - if (dest_buf_filled) { - /* FIXME: Be more verbose */ - GST_WARNING ("Invalid object location for data_type 0x%x!", - *(buf - 1)); - GST_MEMDUMP ("Remaining data after invalid object location:", buf, - buf_end - buf); - return; // FIXME: Perhaps tell read_nbit_string that dbuf_len is zero and let it walk the bytes regardless? (Same FIXME for 2bit and 8bit) - } - if (region->depth < 4) { GST_WARNING ("4-bit pixel string in %d-bit region!", region->depth); return; @@ -1024,15 +1049,6 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, GST_DEBUG ("READ_4BIT_STRING finished: buf pointer now %p", buf); break; case 0x12: - if (dest_buf_filled) { - /* FIXME: Be more verbose */ - GST_WARNING ("Invalid object location for data_type 0x%x!", - *(buf - 1)); - GST_MEMDUMP ("Remaining data after invalid object location:", - buf, (guint) (buf_end - buf)); - return; - } - if (region->depth < 8) { GST_WARNING ("8-bit pixel string in %d-bit region!", region->depth); return; @@ -1046,19 +1062,29 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, case 0x20: GST_DEBUG ("handling map2to4 table data"); - /* FIXME: I don't see any guards about buffer size here - buf++ happens with the switch, but - * FIXME: buffer is walked without length checks? Same deal in other map table cases */ + if (buf + 2 > buf_end) { + GST_WARNING ("map2to4 table too short"); + return; + } map2to4[0] = (*buf) >> 4; map2to4[1] = (*buf++) & 0xf; map2to4[2] = (*buf) >> 4; map2to4[3] = (*buf++) & 0xf; break; case 0x21: + if (buf + 4 > buf_end) { + GST_WARNING ("map2to8 table too short"); + return; + } GST_DEBUG ("handling map2to8 table data"); for (i = 0; i < 4; i++) map2to8[i] = *buf++; break; case 0x22: + if (buf + 16 > buf_end) { + GST_WARNING ("map4to8 table too short"); + return; + } GST_DEBUG ("handling map4to8 table data"); for (i = 0; i < 16; i++) map4to8[i] = *buf++; @@ -1085,6 +1111,9 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 coding_method, non_modifying_color; + if (buf_size < 3) + return; + object_id = GST_READ_UINT16_BE (buf); buf += 2; @@ -1107,6 +1136,9 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, DVBSubObjectDisplay *display; guint16 top_field_len, bottom_field_len; + if (buf + 4 > buf_end) + return; + top_field_len = GST_READ_UINT16_BE (buf); buf += 2; bottom_field_len = GST_READ_UINT16_BE (buf); -- GitLab From f0a84752aaa09457fcf736c93cecdff34ec0bfb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 12 Feb 2026 09:50:23 +0200 Subject: [PATCH 3/3] dvbsuboverlay: Avoid integer overflows and unreasonably large displays/regions Part-of: --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -483,6 +483,17 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, region->height = GST_READ_UINT16_BE (buf); buf += 2; + /* Avoid integer overflows and also clamp to a reasonable size of 8kx8k for + * the region size. We allow 16kx16k display sizes. */ + if (region->width > 8192 || region->height > 8192) { + GST_WARNING ("too large region of %ux%x", region->width, region->height); + g_free (region->pbuf); + region->pbuf = NULL; + region->buf_size = 0; + region->width = region->height = 0; + return; + } + if (region->width * region->height != region->buf_size) { /* FIXME: Read closer from spec what happens when dimensions change */ g_free (region->pbuf); @@ -1196,6 +1207,18 @@ _dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, const guint8 * buf, display_height = GST_READ_UINT16_BE (buf) + 1; buf += 2; + /* Avoid integer overflows and also clamp to a reasonable size of 16kx16k */ + if (display_width > 16384 || display_height > 16384) { + GST_WARNING ("too large display size of %ux%x", display_width, + display_height); + /* Reset to the initial values */ + dvb_sub->display_def.version = -1; + dvb_sub->display_def.window_flag = 0; + dvb_sub->display_def.display_width = 720; + dvb_sub->display_def.display_height = 576; + return -1; + } + if ((display_width != dvb_sub->display_def.display_width) || (display_height != dvb_sub->display_def.display_height)) { dvb_sub->display_def.display_width = display_width; -- GitLab