[FFmpeg-devel] [PATCH] avcodec/srtdec: Keep exact end times

Eelco Lempsink eml at tupil.com
Thu Dec 3 10:30:44 CET 2015


When converting SRT to SRT (to normalize) or WebVTT the end timestamps were
modified compared to the original.

Fixes trac 4783.

NOTE: The FATE test 'sub-srt' fails after this patch, because the end times of
the Dialogue lines change from X:XX:XX.50 to X:XX:XX.49. I can argue that this
is semantically correct, because in the original SRT the begin and end times
are such that there is no (unintended) overlap between cues, but since the
semantics of SRT are poorly defined, I’m not sure it’s correct.
---
 libavcodec/srtdec.c          | 15 ++++++----
 tests/ref/fate/sub-webvttenc | 66 ++++++++++++++++++++++----------------------
 2 files changed, 43 insertions(+), 38 deletions(-)

diff --git a/libavcodec/srtdec.c b/libavcodec/srtdec.c
index 542dd35..54568ca 100644
--- a/libavcodec/srtdec.c
+++ b/libavcodec/srtdec.c
@@ -57,7 +57,7 @@ static int srt_decode_frame(AVCodecContext *avctx,
 {
     AVSubtitle *sub = data;
     AVBPrint buffer;
-    int ts_start, ts_end, x1 = -1, y1 = -1, x2 = -1, y2 = -1;
+    int ts_start, ts_duration, x1 = -1, y1 = -1, x2 = -1, y2 = -1;
     int size, ret;
     const uint8_t *p = av_packet_get_side_data(avpkt, AV_PKT_DATA_SUBTITLE_POSITION, &size);
 
@@ -77,12 +77,17 @@ static int srt_decode_frame(AVCodecContext *avctx,
     ts_start = av_rescale_q(avpkt->pts,
                             avctx->time_base,
                             (AVRational){1,100});
-    ts_end   = av_rescale_q(avpkt->pts + avpkt->duration,
-                            avctx->time_base,
-                            (AVRational){1,100});
+
+    // Floor the duration (for ASS output)
+    ts_duration = avpkt->duration / 10;
+
+    // Set an exact end display time to prevent the rounding for ASS messing it up
+    sub->end_display_time = av_rescale_q(avpkt->duration,
+                                         avctx->pkt_timebase,
+                                         (AVRational){1,1000});
 
     srt_to_ass(avctx, &buffer, avpkt->data, x1, y1, x2, y2);
-    ret = ff_ass_add_rect_bprint(sub, &buffer, ts_start, ts_end-ts_start);
+    ret = ff_ass_add_rect_bprint(sub, &buffer, ts_start, ts_duration);
     av_bprint_finalize(&buffer, NULL);
     if (ret < 0)
         return ret;
diff --git a/tests/ref/fate/sub-webvttenc b/tests/ref/fate/sub-webvttenc
index dbeadb0..ba567c3 100644
--- a/tests/ref/fate/sub-webvttenc
+++ b/tests/ref/fate/sub-webvttenc
@@ -14,12 +14,12 @@ If you see this with the normal font, the player don't (fully) support font face
 00:04.500 --> 00:04.500
 Hidden
 
-00:04.501 --> 00:07.501
+00:04.501 --> 00:07.500
 This text should be small
 This text should be normal
 This text should be big
 
-00:07.501 --> 00:11.501
+00:07.501 --> 00:11.500
 This should be an E with an accent: È
 日本語
 <b><i><u>This text should be bold, italics and underline</u></i></b>
@@ -27,7 +27,7 @@ This text should be small and green
 This text should be small and red
 This text should be big and brown
 
-00:11.501 --> 00:14.501
+00:11.501 --> 00:14.500
 <b>This line should be bold</b>
 <i>This line should be italics</i>
 <u>This line should be underline</u>
@@ -35,7 +35,7 @@ This line should be strikethrough
 <u>Both lines
 should be underline</u>
 
-00:14.501 --> 00:17.501
+00:14.501 --> 00:17.500
 >
 It would be a good thing to
 hide invalid html tags that are closed and show the text in them
@@ -43,110 +43,110 @@ hide invalid html tags that are closed and show the text in them
 Show not opened tags</invalid_tag_not_opened>
 <
 
-00:17.501 --> 00:20.501
+00:17.501 --> 00:20.500
 and also
 hide invalid html tags with parameters that are closed and show the text in them
 <invalid_tag_uc par=5>but show un-closed invalid html tags
 <u>This text should be showed underlined without problems also: 2<3,5>1,4<6</u>
 This shouldn't be underlined
 
-00:20.501 --> 00:21.501
+00:20.501 --> 00:21.500
 This text should be in the normal position...
 
-00:21.501 --> 00:22.501
+00:21.501 --> 00:22.500
 This text should NOT be in the normal position
 
-00:22.501 --> 00:24.501
+00:22.501 --> 00:24.500
 Implementation is the same of the ASS tag
 This text should be at the
 top and horizontally centered
 
-00:22.501 --> 00:24.501
+00:22.501 --> 00:24.500
 This text should be at the
 middle and horizontally centered
 
-00:22.501 --> 00:24.501
+00:22.501 --> 00:24.500
 This text should be at the
 bottom and horizontally centered
 
-00:24.501 --> 00:26.501
+00:24.501 --> 00:26.500
 This text should be at the
 top and horizontally at the left
 
-00:24.501 --> 00:26.501
+00:24.501 --> 00:26.500
 This text should be at the
 middle and horizontally at the left
 (The second position must be ignored)
 
-00:24.501 --> 00:26.501
+00:24.501 --> 00:26.500
 This text should be at the
 bottom and horizontally at the left
 
-00:26.501 --> 00:28.501
+00:26.501 --> 00:28.500
 This text should be at the
 top and horizontally at the right
 
-00:26.501 --> 00:28.501
+00:26.501 --> 00:28.500
 This text should be at the
 middle and horizontally at the right
 
-00:26.501 --> 00:28.501
+00:26.501 --> 00:28.500
 This text should be at the
 bottom and horizontally at the right
 
-00:28.501 --> 00:31.501
+00:28.501 --> 00:31.500
 This could be the most difficult thing to implement
 
-00:31.501 --> 00:50.501
+00:31.501 --> 00:50.500
 First text
 
 00:33.500 --> 00:35.500
 Second, it shouldn't overlap first
 
-00:35.501 --> 00:37.501
+00:35.501 --> 00:37.500
 Third, it should replace second
 
-00:36.501 --> 00:50.501
+00:36.501 --> 00:50.500
 Fourth, it shouldn't overlap first and third
 
-00:40.501 --> 00:45.501
+00:40.501 --> 00:45.500
 Fifth, it should replace third
 
-00:45.501 --> 00:50.501
+00:45.501 --> 00:50.500
 Sixth, it shouldn't be
 showed overlapped
 
-00:50.501 --> 00:52.501
+00:50.501 --> 00:52.500
 TEXT 1 (bottom)
 
-00:50.501 --> 00:52.501
+00:50.501 --> 00:52.500
 text 2
 
-00:52.501 --> 00:54.501
+00:52.501 --> 00:54.500
 Hide these tags:
 also hide these tags:
 but show this: {normal text}
 
-00:54.501 --> 01:00.501
+00:54.501 --> 01:00.500
 
 \ N is a forced line break
 \ h is a hard space
 Normal spaces at the start and at the end of the line are trimmed while hard spaces are not trimmed.
 The\hline\hwill\hnever\hbreak\hautomatically\hright\hbefore\hor\hafter\ha\hhard\hspace.\h:-D
 
-00:54.501 --> 00:56.501
+00:54.501 --> 00:56.500
 
 \h\h\h\h\hA (05 hard spaces followed by a letter)
 A (Normal  spaces followed by a letter)
 A (No hard spaces followed by a letter)
 
-00:56.501 --> 00:58.501
+00:56.501 --> 00:58.500
 \h\h\h\h\hA (05 hard spaces followed by a letter)
 A (Normal  spaces followed by a letter)
 A (No hard spaces followed by a letter)
 Show this: \TEST and this: \-)
 
-00:58.501 --> 01:00.501
+00:58.501 --> 01:00.500
 
 A letter followed by 05 hard spaces: A\h\h\h\h\h
 A letter followed by normal  spaces: A
@@ -156,22 +156,22 @@ A letter followed by no hard spaces: A
 
 ^--Forced line break
 
-01:00.501 --> 01:02.501
+01:00.501 --> 01:02.500
 Both line should be strikethrough,
 yes.
 Correctly closed tags
 should be hidden.
 
-01:02.501 --> 01:04.501
+01:02.501 --> 01:04.500
 It shouldn't be strikethrough,
 not opened tag showed as text.</s>
 Not opened tag showed as text.</xxxxx>
 
-01:04.501 --> 01:06.501
+01:04.501 --> 01:06.500
 Three lines should be strikethrough,
 yes.
 <yyyy>Not closed tags showed as text
 
-01:06.501 --> 01:08.501
+01:06.501 --> 01:08.500
 Both line should be strikethrough but
 the wrong closing tag should be showed</b>
-- 
2.4.9 (Apple Git-60)



More information about the ffmpeg-devel mailing list