diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 53de4ac997..4eb8c4f155 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -1512,31 +1512,69 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type } break; case 0x59: /* subtitling descriptor */ - language[0] = get8(pp, desc_end); - language[1] = get8(pp, desc_end); - language[2] = get8(pp, desc_end); - language[3] = 0; - /* hearing impaired subtitles detection */ - switch(get8(pp, desc_end)) { - case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */ - case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */ - case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */ - case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */ - case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */ - case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */ - st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; - break; - } - if (st->codec->extradata) { - if (st->codec->extradata_size == 4 && memcmp(st->codec->extradata, *pp, 4)) - avpriv_request_sample(fc, "DVB sub with multiple IDs"); - } else { - if (!ff_alloc_extradata(st->codec, 4)) { - memcpy(st->codec->extradata, *pp, 4); + { + /* 8 bytes per DVB subtitle substream data: + * ISO_639_language_code (3 bytes), + * subtitling_type (1 byte), + * composition_page_id (2 bytes), + * ancillary_page_id (2 bytes) */ + int language_count = desc_len / 8; + + if (desc_len > 0 && desc_len % 8 != 0) + return AVERROR_INVALIDDATA; + + if (language_count > 1) { + avpriv_request_sample(fc, "DVB subtitles with multiple languages"); + } + + if (language_count > 0) { + uint8_t *extradata; + + /* 4 bytes per language code (3 bytes) with comma or NUL byte should fit language buffer */ + if (language_count > sizeof(language) / 4) { + language_count = sizeof(language) / 4; + } + + if (st->codec->extradata == NULL) { + if (ff_alloc_extradata(st->codec, language_count * 5)) { + return AVERROR(ENOMEM); + } + } + + if (st->codec->extradata_size < language_count * 5) + return AVERROR_INVALIDDATA; + + extradata = st->codec->extradata; + + for (i = 0; i < language_count; i++) { + language[i * 4 + 0] = get8(pp, desc_end); + language[i * 4 + 1] = get8(pp, desc_end); + language[i * 4 + 2] = get8(pp, desc_end); + language[i * 4 + 3] = ','; + + /* hearing impaired subtitles detection using subtitling_type */ + switch(*pp[0]) { + case 0x20: /* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */ + case 0x21: /* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */ + case 0x22: /* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */ + case 0x23: /* DVB subtitles (for the hard of hearing) for display on 2.21:1 aspect ratio monitor */ + case 0x24: /* DVB subtitles (for the hard of hearing) for display on a high definition monitor */ + case 0x25: /* DVB subtitles (for the hard of hearing) with plano-stereoscopic disparity for display on a high definition monitor */ + st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; + break; + } + + extradata[4] = get8(pp, desc_end); /* subtitling_type */ + memcpy(extradata, *pp, 4); /* composition_page_id and ancillary_page_id */ + extradata += 5; + + *pp += 4; + } + + language[i * 4 - 1] = 0; + av_dict_set(&st->metadata, "language", language, 0); } } - *pp += 4; - av_dict_set(&st->metadata, "language", language, 0); break; case 0x0a: /* ISO 639 language descriptor */ for (i = 0; i + 4 <= desc_len; i += 4) { diff --git a/libavformat/version.h b/libavformat/version.h index e2d097cc47..9e7bcf798f 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 55 #define LIBAVFORMAT_VERSION_MINOR 32 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MICRO 101 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \