diff --git a/libavcodec/microdvddec.c b/libavcodec/microdvddec.c index e08cc312c0..f3c640f932 100644 --- a/libavcodec/microdvddec.c +++ b/libavcodec/microdvddec.c @@ -260,6 +260,7 @@ static int microdvd_decode_frame(AVCodecContext *avctx, { AVSubtitle *sub = data; AVBPrint new_line; + char c; char *decoded_sub; char *line = avpkt->data; char *end = avpkt->data + avpkt->size; @@ -268,11 +269,16 @@ static int microdvd_decode_frame(AVCodecContext *avctx, if (avpkt->size <= 0) return avpkt->size; - av_bprint_init(&new_line, 0, 2048); + /* To be removed later */ + if (sscanf(line, "{%*d}{%*[0123456789]}%c", &c) == 1 && + line[avpkt->size - 1] == '\n') { + av_log(avctx, AV_LOG_ERROR, "AVPacket is not clean (contains timing " + "information and a trailing line break). You need to upgrade " + "your libavformat or sanitize your packet.\n"); + return AVERROR_INVALIDDATA; + } - // skip {frame_start}{frame_end} - line = strchr(line, '}'); if (!line) goto end; line++; - line = strchr(line, '}'); if (!line) goto end; line++; + av_bprint_init(&new_line, 0, 2048); // subtitle content while (line < end && *line) { @@ -294,8 +300,9 @@ static int microdvd_decode_frame(AVCodecContext *avctx, line++; } } + if (new_line.len) { + av_bprintf(&new_line, "\r\n"); -end: av_bprint_finalize(&new_line, &decoded_sub); if (*decoded_sub) { int64_t start = avpkt->pts; @@ -306,6 +313,7 @@ end: ff_ass_add_rect(sub, decoded_sub, ts_start, ts_duration, 0); } av_free(decoded_sub); + } *got_sub_ptr = sub->num_rects > 0; return avpkt->size; diff --git a/libavcodec/version.h b/libavcodec/version.h index af58490975..b4608a2cb0 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -29,7 +29,7 @@ #include "libavutil/avutil.h" #define LIBAVCODEC_VERSION_MAJOR 54 -#define LIBAVCODEC_VERSION_MINOR 84 +#define LIBAVCODEC_VERSION_MINOR 85 #define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/microdvddec.c b/libavformat/microdvddec.c index 5d5b83fea8..96ffa3da07 100644 --- a/libavformat/microdvddec.c +++ b/libavformat/microdvddec.c @@ -83,18 +83,19 @@ static int microdvd_read_header(AVFormatContext *s) return AVERROR(ENOMEM); while (!url_feof(s->pb)) { + char *p = line; AVPacket *sub; int64_t pos = avio_tell(s->pb); int len = ff_get_line(s->pb, line, sizeof(line)); if (!len) break; - if (i < 3) { + line[strcspn(line, "\r\n")] = 0; + if (i++ < 3) { int frame; double fps; char c; - i++; if ((sscanf(line, "{%d}{}%6lf", &frame, &fps) == 2 || sscanf(line, "{%d}{%*d}%6lf", &frame, &fps) == 2) && frame <= 1 && fps > 3 && fps < 100) @@ -107,12 +108,24 @@ static int microdvd_read_header(AVFormatContext *s) continue; } } - sub = ff_subtitles_queue_insert(µdvd->q, line, len, 0); +#define SKIP_FRAME_ID \ + p = strchr(p, '}'); \ + if (!p) { \ + av_log(s, AV_LOG_WARNING, "Invalid event \"%s\"" \ + " at line %d\n", line, i); \ + continue; \ + } \ + p++ + SKIP_FRAME_ID; + SKIP_FRAME_ID; + if (!*p) + continue; + sub = ff_subtitles_queue_insert(µdvd->q, p, strlen(p), 0); if (!sub) return AVERROR(ENOMEM); sub->pos = pos; - sub->pts = get_pts(sub->data); - sub->duration = get_duration(sub->data); + sub->pts = get_pts(line); + sub->duration = get_duration(line); } ff_subtitles_queue_finalize(µdvd->q); avpriv_set_pts_info(st, 64, pts_info.den, pts_info.num); diff --git a/libavformat/version.h b/libavformat/version.h index 90d47d02d1..6fb42d84ed 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -30,7 +30,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 54 -#define LIBAVFORMAT_VERSION_MINOR 56 +#define LIBAVFORMAT_VERSION_MINOR 57 #define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/tests/ref/fate/sub-microdvd b/tests/ref/fate/sub-microdvd index 9fc10fbc57..2059989172 100644 --- a/tests/ref/fate/sub-microdvd +++ b/tests/ref/fate/sub-microdvd @@ -1 +1 @@ -6356b8c53169aae6a20bce34d0f7be87 +35e133576aa3881d2de8dbf39a8d6df7