summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Bœsch <ubitux@gmail.com>2012-12-29 23:26:36 +0100
committerClément Bœsch <ubitux@gmail.com>2012-12-31 00:41:35 +0100
commit1f265f52050e967d78e29d8e115c7dc849b14c4e (patch)
treec35814a7a10c70da45ef5700bd6b401a59558ba0
parentfaa94061dd7236cbaabd483e7b2df148cdbefb7f (diff)
microdvd: sanitize AVPackets.
Current MicroDVD AVPackets contain timing information and trailing line breaks. The data is now only composed of the markup data. Doing this consistently between text subtitles decoders allows to use different codec for various formats. For instance, MicroDVD markup is sometimes found in some VPlayer files. Also, generally speaking, the subtitles text decoders have no use of these timings (and they must not use them since it would break any user timing adjustment). Technically, this is a major ABI break. In practice, a mismatching lavf/lavc will now error out for MicroDVD decoding. Supporting both formats requires unnecessary complex and fragile code. FATE needs update because line breaks in the ASS file were "\n" (because that's what is used in the original file). ASS format expect "\r\n" line breaks; this commit fixes this issue. Also note that this "\r\n" trailing need to be moved at some point from the decoders to the ASS muxer.
-rw-r--r--libavcodec/microdvddec.c18
-rw-r--r--libavcodec/version.h2
-rw-r--r--libavformat/microdvddec.c23
-rw-r--r--libavformat/version.h2
-rw-r--r--tests/ref/fate/sub-microdvd2
5 files changed, 34 insertions, 13 deletions
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(&microdvd->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(&microdvd->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(&microdvd->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