Browse code

movtextdec: 3GPP TS 26.245 Timed Text Decoder.

This change introduces a basic decoder for 3GPP Timed Text subtitles,
also known as TX3G, Quicktime subtitles, or "movtext" in the existing
code.

This initial change doesn't attempt to parse styling information,
and just reads the plain text of the subtitles. I intend to add
support for styles eventually, but it's challenging due to a lack
of existing players that support them.

Signed-off-by: Philip Langdale <philipl@overt.org>

Philip Langdale authored on 2012/06/24 06:11:19
Showing 8 changed files
... ...
@@ -27,6 +27,7 @@ version next:
27 27
 - iec61883 device
28 28
 - asettb filter
29 29
 - new option: -progress
30
+- 3GPP Timed Text decoder
30 31
 
31 32
 
32 33
 version 0.11:
... ...
@@ -876,16 +876,17 @@ performance on systems without hardware floating point support).
876 876
 
877 877
 @multitable @columnfractions .4 .1 .1 .1 .1
878 878
 @item Name @tab Muxing @tab Demuxing @tab Encoding @tab Decoding
879
-@item SSA/ASS      @tab X @tab X @tab X @tab X
880
-@item DVB          @tab X @tab X @tab X @tab X
881
-@item DVD          @tab X @tab X @tab X @tab X
882
-@item JACOsub      @tab X @tab X @tab   @tab X
883
-@item MicroDVD     @tab X @tab X @tab   @tab X
884
-@item PGS          @tab   @tab   @tab   @tab X
885
-@item RealText     @tab   @tab X @tab   @tab X
886
-@item SAMI         @tab   @tab X @tab   @tab X
887
-@item SubRip (SRT) @tab X @tab X @tab X @tab X
888
-@item XSUB         @tab   @tab   @tab X @tab X
879
+@item SSA/ASS          @tab X @tab X @tab X @tab X
880
+@item DVB              @tab X @tab X @tab X @tab X
881
+@item DVD              @tab X @tab X @tab X @tab X
882
+@item JACOsub          @tab X @tab X @tab   @tab X
883
+@item MicroDVD         @tab X @tab X @tab   @tab X
884
+@item PGS              @tab   @tab   @tab   @tab X
885
+@item RealText         @tab   @tab X @tab   @tab X
886
+@item SAMI             @tab   @tab X @tab   @tab X
887
+@item SubRip (SRT)     @tab X @tab X @tab X @tab X
888
+@item 3GPP Timed Text  @tab   @tab   @tab   @tab X
889
+@item XSUB             @tab   @tab   @tab X @tab X
889 890
 @end multitable
890 891
 
891 892
 @code{X} means that the feature is supported.
... ...
@@ -265,6 +265,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER)          += mjpegbdec.o mjpegdec.o mjpeg.o
265 265
 OBJS-$(CONFIG_MLP_DECODER)             += mlpdec.o mlpdsp.o
266 266
 OBJS-$(CONFIG_MMVIDEO_DECODER)         += mmvideo.o
267 267
 OBJS-$(CONFIG_MOTIONPIXELS_DECODER)    += motionpixels.o
268
+OBJS-$(CONFIG_MOVTEXT_DECODER)         += movtextdec.o ass.o
268 269
 OBJS-$(CONFIG_MP1_DECODER)             += mpegaudiodec.o mpegaudiodecheader.o \
269 270
                                           mpegaudio.o mpegaudiodata.o
270 271
 OBJS-$(CONFIG_MP1FLOAT_DECODER)        += mpegaudiodec_float.o mpegaudiodecheader.o \
... ...
@@ -409,6 +409,7 @@ void avcodec_register_all(void)
409 409
     REGISTER_ENCDEC  (DVDSUB, dvdsub);
410 410
     REGISTER_DECODER (JACOSUB, jacosub);
411 411
     REGISTER_DECODER (MICRODVD, microdvd);
412
+    REGISTER_DECODER (MOVTEXT, movtext);
412 413
     REGISTER_DECODER (PGSSUB, pgssub);
413 414
     REGISTER_DECODER (REALTEXT, realtext);
414 415
     REGISTER_DECODER (SAMI, sami);
415 416
new file mode 100644
... ...
@@ -0,0 +1,106 @@
0
+/*
1
+ * 3GPP TS 26.245 Timed Text decoder
2
+ * Copyright (c) 2012  Philip Langdale <philipl@overt.org>
3
+ *
4
+ * This file is part of FFmpeg.
5
+ *
6
+ * FFmpeg is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * FFmpeg is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with FFmpeg; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include "avcodec.h"
22
+#include "ass.h"
23
+#include "libavutil/avstring.h"
24
+#include "libavutil/common.h"
25
+#include "libavutil/bprint.h"
26
+#include "libavutil/intreadwrite.h"
27
+
28
+static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end)
29
+{
30
+    while (text < text_end) {
31
+        switch (*text) {
32
+        case '\r':
33
+            break;
34
+        case '\n':
35
+            av_bprintf(buf, "\\N");
36
+            break;
37
+        default:
38
+            av_bprint_chars(buf, *text, 1);
39
+            break;
40
+        }
41
+        text++;
42
+    }
43
+
44
+    av_bprintf(buf, "\r\n");
45
+    return 0;
46
+}
47
+
48
+static int mov_text_init(AVCodecContext *avctx) {
49
+    /*
50
+     * TODO: Handle the default text style.
51
+     * NB: Most players ignore styles completely, with the result that
52
+     * it's very common to find files where the default style is broken
53
+     * and respecting it results in a worse experience than ignoring it.
54
+     */
55
+    return ff_ass_subtitle_header_default(avctx);
56
+}
57
+
58
+static int mov_text_decode_frame(AVCodecContext *avctx,
59
+                            void *data, int *got_sub_ptr, AVPacket *avpkt)
60
+{
61
+    AVSubtitle *sub = data;
62
+    int ts_start, ts_end;
63
+    AVBPrint buf;
64
+    const char *ptr = avpkt->data;
65
+    const char *end;
66
+
67
+    if (!ptr || avpkt->size <= 2)
68
+        return 0;
69
+
70
+    /*
71
+     * The first two bytes of the packet are the length of the text string
72
+     * In complex cases, there are style descriptors appended to the string
73
+     * so we can't just assume the packet size is the string size.
74
+     */
75
+    end = ptr + FFMAX(2 + AV_RB16(ptr), avpkt->size);
76
+    ptr += 2;
77
+
78
+    ts_start = av_rescale_q(avpkt->pts,
79
+                            avctx->time_base,
80
+                            (AVRational){1,100});
81
+    ts_end   = av_rescale_q(avpkt->pts + avpkt->duration,
82
+                            avctx->time_base,
83
+                            (AVRational){1,100});
84
+
85
+    // Note that the spec recommends lines be no longer than 2048 characters.
86
+    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
87
+    text_to_ass(&buf, ptr, end);
88
+
89
+    if (!av_bprint_is_complete(&buf))
90
+        return AVERROR(ENOMEM);
91
+
92
+    ff_ass_add_rect(sub, buf.str, ts_start, ts_end-ts_start, 0);
93
+    *got_sub_ptr = sub->num_rects > 0;
94
+    av_bprint_finalize(&buf, NULL);
95
+    return avpkt->size;
96
+}
97
+
98
+AVCodec ff_movtext_decoder = {
99
+    .name         = "mov_text",
100
+    .long_name    = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
101
+    .type         = AVMEDIA_TYPE_SUBTITLE,
102
+    .id           = CODEC_ID_MOV_TEXT,
103
+    .init         = mov_text_init,
104
+    .decode       = mov_text_decode_frame,
105
+};
... ...
@@ -27,7 +27,7 @@
27 27
  */
28 28
 
29 29
 #define LIBAVCODEC_VERSION_MAJOR 54
30
-#define LIBAVCODEC_VERSION_MINOR  38
30
+#define LIBAVCODEC_VERSION_MINOR  39
31 31
 #define LIBAVCODEC_VERSION_MICRO 101
32 32
 
33 33
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -13,5 +13,8 @@ fate-sub-srt: CMD = md5 -i $(SAMPLES)/sub/SubRip_capability_tester.srt -f ass
13 13
 FATE_SUBTITLES += fate-sub-realtext
14 14
 fate-sub-realtext: CMD = md5 -i $(SAMPLES)/sub/RealText_capability_tester.rt -f ass
15 15
 
16
+FATE_SUBTITLES += fate-sub-movtext
17
+fate-sub-movtext: CMD = md5 -i $(SAMPLES)/sub/MovText_capability_tester.mp4 -f ass
18
+
16 19
 FATE_SAMPLES_FFMPEG += $(FATE_SUBTITLES)
17 20
 fate-subtitles: $(FATE_SUBTITLES)
18 21
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+21453e8ddbbe35d1368a99fe563c969d