Skip to content

Commit bb11798

Browse files
committed
avcodec/dvbsubdec: Fix conditions for fallback to default resolution
The previous code expected a segment of type CLUT definition to exist in order to accept a set of segments to be complete. This was an incorrect assumption as the presence of a CLUT segment is not mandatory. (version 1.6.1 of the spec is probably a bit more clear about this than earlier versions: https://www.etsi.org/deliver/etsi_en/ 300700_300799/300743/01.06.01_20/en_300743v010601a.pdf) The flawed condition prevented proper fallback to using the default resolution for the decoding context. Signed-off-by: softworkz <[email protected]>
1 parent 6046dde commit bb11798

File tree

1 file changed

+30
-21
lines changed

1 file changed

+30
-21
lines changed

libavcodec/dvbsubdec.c

+30-21
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#define DVBSUB_CLUT_SEGMENT 0x12
3535
#define DVBSUB_OBJECT_SEGMENT 0x13
3636
#define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
37-
#define DVBSUB_DISPLAY_SEGMENT 0x80
37+
#define DVBSUB_END_DISPLAY_SEGMENT 0x80
3838

3939
#define cm (ff_crop_tab + MAX_NEG_CROP)
4040

@@ -1450,8 +1450,12 @@ static int dvbsub_decode(AVCodecContext *avctx, AVSubtitle *sub,
14501450
int segment_length;
14511451
int i;
14521452
int ret = 0;
1453-
int got_segment = 0;
1454-
int got_dds = 0;
1453+
//int got_segment = 0;
1454+
int got_page = 0;
1455+
int got_region = 0;
1456+
int got_object = 0;
1457+
int got_end_display = 0;
1458+
int got_displaydef = 0;
14551459

14561460
ff_dlog(avctx, "DVB sub packet:\n");
14571461

@@ -1496,34 +1500,28 @@ static int dvbsub_decode(AVCodecContext *avctx, AVSubtitle *sub,
14961500
switch (segment_type) {
14971501
case DVBSUB_PAGE_SEGMENT:
14981502
ret = dvbsub_parse_page_segment(avctx, p, segment_length, sub, got_sub_ptr);
1499-
got_segment |= 1;
1503+
got_page = 1;
15001504
break;
15011505
case DVBSUB_REGION_SEGMENT:
15021506
ret = dvbsub_parse_region_segment(avctx, p, segment_length);
1503-
got_segment |= 2;
1507+
got_region = 1;
15041508
break;
15051509
case DVBSUB_CLUT_SEGMENT:
15061510
ret = dvbsub_parse_clut_segment(avctx, p, segment_length);
15071511
if (ret < 0) goto end;
1508-
got_segment |= 4;
15091512
break;
15101513
case DVBSUB_OBJECT_SEGMENT:
15111514
ret = dvbsub_parse_object_segment(avctx, p, segment_length);
1512-
got_segment |= 8;
1515+
got_object = 1;
15131516
break;
15141517
case DVBSUB_DISPLAYDEFINITION_SEGMENT:
15151518
ret = dvbsub_parse_display_definition_segment(avctx, p,
15161519
segment_length);
1517-
got_dds = 1;
1520+
got_displaydef = 1;
15181521
break;
1519-
case DVBSUB_DISPLAY_SEGMENT:
1522+
case DVBSUB_END_DISPLAY_SEGMENT:
15201523
ret = dvbsub_display_end_segment(avctx, p, segment_length, sub, got_sub_ptr);
1521-
if (got_segment == 15 && !got_dds && !avctx->width && !avctx->height) {
1522-
// Default from ETSI EN 300 743 V1.3.1 (7.2.1)
1523-
avctx->width = 720;
1524-
avctx->height = 576;
1525-
}
1526-
got_segment |= 16;
1524+
got_end_display = 1;
15271525
break;
15281526
default:
15291527
ff_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n",
@@ -1536,13 +1534,24 @@ static int dvbsub_decode(AVCodecContext *avctx, AVSubtitle *sub,
15361534

15371535
p += segment_length;
15381536
}
1539-
// Some streams do not send a display segment but if we have all the other
1540-
// segments then we need no further data.
1541-
if (got_segment == 15) {
1542-
av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n");
1543-
dvbsub_display_end_segment(avctx, p, 0, sub, got_sub_ptr);
1544-
}
15451537

1538+
// Even though not mandated by the spec, we're imposing a minimum requirement
1539+
// for a useful packet to have at least one page, region and object segment.
1540+
if (got_page && got_region && got_object && got_end_display) {
1541+
1542+
if (!got_displaydef && !avctx->width && !avctx->height) {
1543+
// Default from ETSI EN 300 743 V1.3.1 (7.2.1)
1544+
avctx->width = 720;
1545+
avctx->height = 576;
1546+
}
1547+
1548+
// Some streams do not send an end-of-display segment but if we have all the other
1549+
// segments then we need no further data.
1550+
if (!got_end_display) {
1551+
av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n");
1552+
dvbsub_display_end_segment(avctx, p, 0, sub, got_sub_ptr);
1553+
}
1554+
}
15461555
end:
15471556
if (ret < 0) {
15481557
return ret;

0 commit comments

Comments
 (0)