Browse code

Add SubViewer v1 subtitles demuxer and decoder.

Clément Bœsch authored on 2012/12/29 08:04:44
Showing 14 changed files
... ...
@@ -51,7 +51,7 @@ version <next>:
51 51
 - pp (postproc) filter ported from MPlayer
52 52
 - NIST Sphere demuxer
53 53
 - av_basename and av_dirname
54
-- MPL2, VPlayer, MPlayer, AQTitle and PJS subtitles demuxers and decoders
54
+- MPL2, VPlayer, MPlayer, AQTitle, PJS and SubViewer v1 subtitles demuxers and decoders
55 55
 
56 56
 
57 57
 version 1.0:
... ...
@@ -933,6 +933,7 @@ performance on systems without hardware floating point support).
933 933
 @item SAMI             @tab   @tab X @tab   @tab X
934 934
 @item SSA/ASS          @tab X @tab X @tab X @tab X
935 935
 @item SubRip (SRT)     @tab X @tab X @tab X @tab X
936
+@item SubViewer v1     @tab   @tab X @tab   @tab X
936 937
 @item SubViewer        @tab   @tab X @tab   @tab X
937 938
 @item TED Talks captions @tab @tab X @tab   @tab X
938 939
 @item VobSub (IDX+SUB) @tab   @tab X @tab   @tab X
... ...
@@ -402,6 +402,7 @@ OBJS-$(CONFIG_SRT_DECODER)             += srtdec.o ass.o
402 402
 OBJS-$(CONFIG_SRT_ENCODER)             += srtenc.o ass_split.o
403 403
 OBJS-$(CONFIG_SUBRIP_DECODER)          += srtdec.o ass.o
404 404
 OBJS-$(CONFIG_SUBRIP_ENCODER)          += srtenc.o ass_split.o
405
+OBJS-$(CONFIG_SUBVIEWER1_DECODER)      += textdec.o ass.o
405 406
 OBJS-$(CONFIG_SUBVIEWER_DECODER)       += subviewerdec.o ass.o
406 407
 OBJS-$(CONFIG_SUNRAST_DECODER)         += sunrast.o
407 408
 OBJS-$(CONFIG_SUNRAST_ENCODER)         += sunrastenc.o
... ...
@@ -456,6 +456,7 @@ void avcodec_register_all(void)
456 456
     REGISTER_ENCDEC (SRT,               srt);
457 457
     REGISTER_ENCDEC (SUBRIP,            subrip);
458 458
     REGISTER_DECODER(SUBVIEWER,         subviewer);
459
+    REGISTER_DECODER(SUBVIEWER1,        subviewer1);
459 460
     REGISTER_DECODER(TEXT,              text);
460 461
     REGISTER_DECODER(VPLAYER,           vplayer);
461 462
     REGISTER_DECODER(WEBVTT,            webvtt);
... ...
@@ -463,6 +463,7 @@ enum AVCodecID {
463 463
     AV_CODEC_ID_JACOSUB    = MKBETAG('J','S','U','B'),
464 464
     AV_CODEC_ID_SAMI       = MKBETAG('S','A','M','I'),
465 465
     AV_CODEC_ID_REALTEXT   = MKBETAG('R','T','X','T'),
466
+    AV_CODEC_ID_SUBVIEWER1 = MKBETAG('S','b','V','1'),
466 467
     AV_CODEC_ID_SUBVIEWER  = MKBETAG('S','u','b','V'),
467 468
     AV_CODEC_ID_SUBRIP     = MKBETAG('S','R','i','p'),
468 469
     AV_CODEC_ID_WEBVTT     = MKBETAG('W','V','T','T'),
... ...
@@ -2441,6 +2441,12 @@ static const AVCodecDescriptor codec_descriptors[] = {
2441 2441
         .long_name = NULL_IF_CONFIG_SMALL("RealText subtitle"),
2442 2442
     },
2443 2443
     {
2444
+        .id        = AV_CODEC_ID_SUBVIEWER1,
2445
+        .type      = AVMEDIA_TYPE_SUBTITLE,
2446
+        .name      = "subviewer1",
2447
+        .long_name = NULL_IF_CONFIG_SMALL("SubViewer v1 subtitle"),
2448
+    },
2449
+    {
2444 2450
         .id        = AV_CODEC_ID_SUBVIEWER,
2445 2451
         .type      = AVMEDIA_TYPE_SUBTITLE,
2446 2452
         .name      = "subviewer",
... ...
@@ -128,7 +128,7 @@ AVCodec ff_text_decoder = {
128 128
 };
129 129
 #endif
130 130
 
131
-#if CONFIG_VPLAYER_DECODER || CONFIG_PJS_DECODER
131
+#if CONFIG_VPLAYER_DECODER || CONFIG_PJS_DECODER || CONFIG_TEXT_DECODER
132 132
 
133 133
 static int linebreak_init(AVCodecContext *avctx)
134 134
 {
... ...
@@ -169,4 +169,20 @@ AVCodec ff_pjs_decoder = {
169 169
 };
170 170
 #endif
171 171
 
172
+#if CONFIG_SUBVIEWER1_DECODER
173
+#define subviewer1_options options
174
+DECLARE_CLASS(subviewer1);
175
+
176
+AVCodec ff_subviewer1_decoder = {
177
+    .name           = "subviewer1",
178
+    .priv_data_size = sizeof(TextContext),
179
+    .long_name      = NULL_IF_CONFIG_SMALL("SubViewer1 subtitle"),
180
+    .type           = AVMEDIA_TYPE_SUBTITLE,
181
+    .id             = AV_CODEC_ID_SUBVIEWER1,
182
+    .decode         = text_decode_frame,
183
+    .init           = linebreak_init,
184
+    .priv_class     = &subviewer1_decoder_class,
185
+};
186
+#endif
187
+
172 188
 #endif /* text subtitles with '|' line break */
... ...
@@ -29,7 +29,7 @@
29 29
 #include "libavutil/avutil.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR 54
32
-#define LIBAVCODEC_VERSION_MINOR 83
32
+#define LIBAVCODEC_VERSION_MINOR 84
33 33
 #define LIBAVCODEC_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -348,6 +348,7 @@ OBJS-$(CONFIG_SPDIF_MUXER)               += spdif.o spdifenc.o
348 348
 OBJS-$(CONFIG_SRT_DEMUXER)               += srtdec.o
349 349
 OBJS-$(CONFIG_SRT_MUXER)                 += srtenc.o
350 350
 OBJS-$(CONFIG_STR_DEMUXER)               += psxstr.o
351
+OBJS-$(CONFIG_SUBVIEWER1_DEMUXER)        += subviewer1dec.o
351 352
 OBJS-$(CONFIG_SUBVIEWER_DEMUXER)         += subviewerdec.o
352 353
 OBJS-$(CONFIG_SWF_DEMUXER)               += swfdec.o swf.o
353 354
 OBJS-$(CONFIG_SWF_MUXER)                 += swfenc.o swf.o
... ...
@@ -259,6 +259,7 @@ void av_register_all(void)
259 259
     REGISTER_MUXDEMUX(SPDIF,            spdif);
260 260
     REGISTER_MUXDEMUX(SRT,              srt);
261 261
     REGISTER_DEMUXER (STR,              str);
262
+    REGISTER_DEMUXER (SUBVIEWER1,       subviewer1);
262 263
     REGISTER_DEMUXER (SUBVIEWER,        subviewer);
263 264
     REGISTER_MUXDEMUX(SWF,              swf);
264 265
     REGISTER_DEMUXER (TAK,              tak);
265 266
new file mode 100644
... ...
@@ -0,0 +1,124 @@
0
+/*
1
+ * Copyright (c) 2012 Clément Bœsch
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+/**
21
+ * @file
22
+ * SubViewer v1 subtitle demuxer
23
+ */
24
+
25
+#include "avformat.h"
26
+#include "internal.h"
27
+#include "subtitles.h"
28
+
29
+typedef struct {
30
+    FFDemuxSubtitlesQueue q;
31
+} SubViewer1Context;
32
+
33
+static int subviewer1_probe(AVProbeData *p)
34
+{
35
+    const unsigned char *ptr = p->buf;
36
+
37
+    if (strstr(ptr, "******** START SCRIPT ********"))
38
+        return AVPROBE_SCORE_MAX / 2;
39
+    return 0;
40
+}
41
+
42
+static int subviewer1_read_header(AVFormatContext *s)
43
+{
44
+    int delay = 0;
45
+    AVPacket *sub = NULL;
46
+    SubViewer1Context *subviewer1 = s->priv_data;
47
+    AVStream *st = avformat_new_stream(s, NULL);
48
+
49
+    if (!st)
50
+        return AVERROR(ENOMEM);
51
+    avpriv_set_pts_info(st, 64, 1, 1);
52
+    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
53
+    st->codec->codec_id   = AV_CODEC_ID_SUBVIEWER1;
54
+
55
+    while (!url_feof(s->pb)) {
56
+        char line[4096];
57
+        int len = ff_get_line(s->pb, line, sizeof(line));
58
+        int hh, mm, ss;
59
+
60
+        if (!len)
61
+            break;
62
+
63
+        if (!strncmp(line, "[DELAY]", 7)) {
64
+            ff_get_line(s->pb, line, sizeof(line));
65
+            sscanf(line, "%d", &delay);
66
+        }
67
+
68
+        if (sscanf(line, "[%d:%d:%d]", &hh, &mm, &ss) == 3) {
69
+            const int64_t pos = avio_tell(s->pb);
70
+            int64_t pts_start = hh*3600LL + mm*60LL + ss + delay;
71
+
72
+            len = ff_get_line(s->pb, line, sizeof(line));
73
+            line[strcspn(line, "\r\n")] = 0;
74
+            if (!*line) {
75
+                if (sub)
76
+                    sub->duration = pts_start - sub->pts;
77
+            } else {
78
+                sub = ff_subtitles_queue_insert(&subviewer1->q, line, len, 0);
79
+                if (!sub)
80
+                    return AVERROR(ENOMEM);
81
+                sub->pos = pos;
82
+                sub->pts = pts_start;
83
+                sub->duration = -1;
84
+            }
85
+        }
86
+    }
87
+
88
+    ff_subtitles_queue_finalize(&subviewer1->q);
89
+    return 0;
90
+}
91
+
92
+static int subviewer1_read_packet(AVFormatContext *s, AVPacket *pkt)
93
+{
94
+    SubViewer1Context *subviewer1 = s->priv_data;
95
+    return ff_subtitles_queue_read_packet(&subviewer1->q, pkt);
96
+}
97
+
98
+static int subviewer1_read_seek(AVFormatContext *s, int stream_index,
99
+                               int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
100
+{
101
+    SubViewer1Context *subviewer1 = s->priv_data;
102
+    return ff_subtitles_queue_seek(&subviewer1->q, s, stream_index,
103
+                                   min_ts, ts, max_ts, flags);
104
+}
105
+
106
+static int subviewer1_read_close(AVFormatContext *s)
107
+{
108
+    SubViewer1Context *subviewer1 = s->priv_data;
109
+    ff_subtitles_queue_clean(&subviewer1->q);
110
+    return 0;
111
+}
112
+
113
+AVInputFormat ff_subviewer1_demuxer = {
114
+    .name           = "subviewer1",
115
+    .long_name      = NULL_IF_CONFIG_SMALL("SubViewer v1 subtitle format"),
116
+    .priv_data_size = sizeof(SubViewer1Context),
117
+    .read_probe     = subviewer1_probe,
118
+    .read_header    = subviewer1_read_header,
119
+    .read_packet    = subviewer1_read_packet,
120
+    .read_seek2     = subviewer1_read_seek,
121
+    .read_close     = subviewer1_read_close,
122
+    .extensions     = "sub",
123
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/avutil.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 54
33
-#define LIBAVFORMAT_VERSION_MINOR 55
33
+#define LIBAVFORMAT_VERSION_MINOR 56
34 34
 #define LIBAVFORMAT_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -37,6 +37,9 @@ fate-sub-srt: CMD = md5 -i $(SAMPLES)/sub/SubRip_capability_tester.srt -f ass
37 37
 FATE_SUBTITLES-$(call ALLYES, MOV_DEMUXER MOVTEXT_DECODER SUBRIP_ENCODER) += fate-sub-subripenc
38 38
 fate-sub-subripenc: CMD = md5 -i $(SAMPLES)/sub/MovText_capability_tester.mp4 -scodec subrip -f srt
39 39
 
40
+FATE_SUBTITLES_ASS-$(call DEMDEC, SUBVIEWER1, SUBVIEWER1) += fate-sub-subviewer1
41
+fate-sub-subviewer1: CMD = md5 -i $(SAMPLES)/sub/SubViewer1_capability_tester.sub -f ass
42
+
40 43
 FATE_SUBTITLES_ASS-$(call DEMDEC, SUBVIEWER, SUBVIEWER) += fate-sub-subviewer
41 44
 fate-sub-subviewer: CMD = md5 -i $(SAMPLES)/sub/SubViewer_capability_tester.sub -f ass
42 45
 
43 46
new file mode 100644
... ...
@@ -0,0 +1 @@
0
+0c2096fedf7c971742b2e879bb303ce9