Browse code

avformat: add SUP/PGS subtitle demuxer

Signed-off-by: Clément Bœsch <u@pkh.me>

wm4 authored on 2014/09/25 00:38:58
Showing 6 changed files
... ...
@@ -3,6 +3,7 @@ releases are sorted from youngest to oldest.
3 3
 
4 4
 version <next>:
5 5
 - HEVC/H.265 RTP payload format (draft v6) packetizer
6
+- SUP/PGS subtitle demuxer
6 7
 
7 8
 version 2.4:
8 9
 - Icecast protocol
... ...
@@ -454,6 +454,7 @@ library:
454 454
 @item Sony Wave64 (W64)         @tab X @tab X
455 455
 @item SoX native format         @tab X @tab X
456 456
 @item SUN AU format             @tab X @tab X
457
+@item SUP raw PGS subtitles     @tab   @tab X
457 458
 @item Text files                @tab   @tab X
458 459
 @item THP                       @tab   @tab X
459 460
     @tab Used on the Nintendo GameCube.
... ...
@@ -407,6 +407,7 @@ OBJS-$(CONFIG_SRT_MUXER)                 += srtenc.o
407 407
 OBJS-$(CONFIG_STR_DEMUXER)               += psxstr.o
408 408
 OBJS-$(CONFIG_SUBVIEWER1_DEMUXER)        += subviewer1dec.o subtitles.o
409 409
 OBJS-$(CONFIG_SUBVIEWER_DEMUXER)         += subviewerdec.o subtitles.o
410
+OBJS-$(CONFIG_SUP_DEMUXER)               += supdec.o
410 411
 OBJS-$(CONFIG_SWF_DEMUXER)               += swfdec.o swf.o
411 412
 OBJS-$(CONFIG_SWF_MUXER)                 += swfenc.o swf.o
412 413
 OBJS-$(CONFIG_TAK_DEMUXER)               += takdec.o apetag.o img2.o rawdec.o
... ...
@@ -280,6 +280,7 @@ void av_register_all(void)
280 280
     REGISTER_DEMUXER (STR,              str);
281 281
     REGISTER_DEMUXER (SUBVIEWER1,       subviewer1);
282 282
     REGISTER_DEMUXER (SUBVIEWER,        subviewer);
283
+    REGISTER_DEMUXER (SUP,              sup);
283 284
     REGISTER_MUXDEMUX(SWF,              swf);
284 285
     REGISTER_DEMUXER (TAK,              tak);
285 286
     REGISTER_MUXER   (TEE,              tee);
286 287
new file mode 100644
... ...
@@ -0,0 +1,109 @@
0
+/*
1
+ * This file is part of FFmpeg.
2
+ *
3
+ * FFmpeg is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * FFmpeg is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with FFmpeg; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#include "avformat.h"
19
+#include "internal.h"
20
+#include "libavutil/intreadwrite.h"
21
+
22
+#define SUP_PGS_MAGIC 0x5047 /* "PG", big endian */
23
+
24
+static int sup_read_header(AVFormatContext *s)
25
+{
26
+    AVStream *st = avformat_new_stream(s, NULL);
27
+    if (!st)
28
+        return AVERROR(ENOMEM);
29
+    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
30
+    st->codec->codec_id = AV_CODEC_ID_HDMV_PGS_SUBTITLE;
31
+    avpriv_set_pts_info(st, 32, 1, 90000);
32
+
33
+    return 0;
34
+}
35
+
36
+static int sup_read_packet(AVFormatContext *s, AVPacket *pkt)
37
+{
38
+    int64_t pts, dts, pos;
39
+    int ret;
40
+
41
+    pos = avio_tell(s->pb);
42
+
43
+    if (avio_rb16(s->pb) != SUP_PGS_MAGIC)
44
+        return avio_feof(s->pb) ? AVERROR_EOF : AVERROR_INVALIDDATA;
45
+
46
+    pts = avio_rb32(s->pb);
47
+    dts = avio_rb32(s->pb);
48
+
49
+    if ((ret = av_get_packet(s->pb, pkt, 3)) < 0)
50
+        return ret;
51
+
52
+    pkt->stream_index = 0;
53
+    pkt->flags |= AV_PKT_FLAG_KEY;
54
+    pkt->pos = pos;
55
+    pkt->pts = pts;
56
+    // Many files have DTS set to 0 for all packets, so assume 0 means unset.
57
+    pkt->dts = dts ? dts : AV_NOPTS_VALUE;
58
+
59
+    if (pkt->size >= 3) {
60
+        // The full packet size is stored as part of the packet.
61
+        size_t len = AV_RB16(pkt->data + 1);
62
+
63
+        if ((ret = av_append_packet(s->pb, pkt, len)) < 0)
64
+            return ret;
65
+    }
66
+
67
+    return 0;
68
+}
69
+
70
+static int sup_probe(AVProbeData *p)
71
+{
72
+    unsigned char *buf = p->buf;
73
+    size_t buf_size = p->buf_size;
74
+    int nb_packets;
75
+
76
+    for (nb_packets = 0; nb_packets < 10; nb_packets++) {
77
+        size_t full_packet_size;
78
+        if (buf_size < 10 + 3)
79
+            break;
80
+        if (AV_RB16(buf) != SUP_PGS_MAGIC)
81
+            return 0;
82
+        full_packet_size = AV_RB16(buf + 10 + 1) + 10 + 3;
83
+        if (buf_size < full_packet_size)
84
+            break;
85
+        buf += full_packet_size;
86
+        buf_size -= full_packet_size;
87
+    }
88
+    if (!nb_packets)
89
+        return 0;
90
+    if (nb_packets < 2)
91
+        return AVPROBE_SCORE_RETRY / 2;
92
+    if (nb_packets < 4)
93
+        return AVPROBE_SCORE_RETRY;
94
+    if (nb_packets < 10)
95
+        return AVPROBE_SCORE_EXTENSION;
96
+    return AVPROBE_SCORE_MAX;
97
+}
98
+
99
+AVInputFormat ff_sup_demuxer = {
100
+    .name           = "sup",
101
+    .long_name      = NULL_IF_CONFIG_SMALL("raw HDMV Presentation Graphic Stream subtitles"),
102
+    .extensions     = "sup",
103
+    .mime_type      = "application/x-pgs",
104
+    .read_probe     = sup_probe,
105
+    .read_header    = sup_read_header,
106
+    .read_packet    = sup_read_packet,
107
+    .flags          = AVFMT_GENERIC_INDEX,
108
+};
... ...
@@ -30,7 +30,7 @@
30 30
 #include "libavutil/version.h"
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 56
33
-#define LIBAVFORMAT_VERSION_MINOR  6
33
+#define LIBAVFORMAT_VERSION_MINOR  7
34 34
 #define LIBAVFORMAT_VERSION_MICRO 100
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \