Browse code

Add SUP/PGS subtitle muxer

Fixes ticket #2208

Petri Hintukainen authored on 2014/09/30 17:01:17
Showing 6 changed files
... ...
@@ -44,6 +44,7 @@ version <next>:
44 44
 - drop deprecated qtkit input device (use avfoundation instead)
45 45
 - despill video filter
46 46
 - haas audio filter
47
+- SUP/PGS subtitle muxer
47 48
 
48 49
 version 3.3:
49 50
 - CrystalHD decoder moved to new decode API
... ...
@@ -530,7 +530,7 @@ library:
530 530
 @item Sony Wave64 (W64)         @tab X @tab X
531 531
 @item SoX native format         @tab X @tab X
532 532
 @item SUN AU format             @tab X @tab X
533
-@item SUP raw PGS subtitles     @tab   @tab X
533
+@item SUP raw PGS subtitles     @tab X @tab X
534 534
 @item SVAG                      @tab   @tab X
535 535
     @tab Audio format used in Konami PS2 games.
536 536
 @item TDSC                      @tab   @tab X
... ...
@@ -474,6 +474,7 @@ OBJS-$(CONFIG_STR_DEMUXER)               += psxstr.o
474 474
 OBJS-$(CONFIG_SUBVIEWER1_DEMUXER)        += subviewer1dec.o subtitles.o
475 475
 OBJS-$(CONFIG_SUBVIEWER_DEMUXER)         += subviewerdec.o subtitles.o
476 476
 OBJS-$(CONFIG_SUP_DEMUXER)               += supdec.o
477
+OBJS-$(CONFIG_SUP_MUXER)                 += supenc.o
477 478
 OBJS-$(CONFIG_SVAG_DEMUXER)              += svag.o
478 479
 OBJS-$(CONFIG_SWF_DEMUXER)               += swfdec.o swf.o
479 480
 OBJS-$(CONFIG_SWF_MUXER)                 += swfenc.o swf.o
... ...
@@ -303,7 +303,7 @@ static void register_all(void)
303 303
     REGISTER_DEMUXER (STL,              stl);
304 304
     REGISTER_DEMUXER (SUBVIEWER1,       subviewer1);
305 305
     REGISTER_DEMUXER (SUBVIEWER,        subviewer);
306
-    REGISTER_DEMUXER (SUP,              sup);
306
+    REGISTER_MUXDEMUX(SUP,              sup);
307 307
     REGISTER_DEMUXER (SVAG,             svag);
308 308
     REGISTER_MUXDEMUX(SWF,              swf);
309 309
     REGISTER_DEMUXER (TAK,              tak);
310 310
new file mode 100644
... ...
@@ -0,0 +1,96 @@
0
+/*
1
+ * SUP muxer
2
+ * Copyright (c) 2014 Petri Hintukainen <phintuka@users.sourceforge.net>
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 "avformat.h"
22
+#include "internal.h"
23
+#include "libavutil/intreadwrite.h"
24
+
25
+#define SUP_PGS_MAGIC 0x5047 /* "PG", big endian */
26
+
27
+static int sup_write_packet(AVFormatContext *s, AVPacket *pkt)
28
+{
29
+    uint8_t *data = pkt->data;
30
+    size_t size = pkt->size;
31
+    uint32_t pts = 0, dts = 0;
32
+
33
+    if (pkt->pts != AV_NOPTS_VALUE) {
34
+        pts = (uint32_t)pkt->pts;
35
+    }
36
+    if (pkt->dts != AV_NOPTS_VALUE) {
37
+        dts = (uint32_t)pkt->dts;
38
+    }
39
+
40
+    /*
41
+      Split frame to segments.
42
+      mkvmerge stores multiple segments in one frame.
43
+    */
44
+    while (size > 2) {
45
+        size_t len = AV_RB16(data + 1) + 3;
46
+
47
+        if (len > size) {
48
+            av_log(s, AV_LOG_ERROR, "Not enough data, skipping %d bytes\n",
49
+                     (int)size);
50
+            return AVERROR_INVALIDDATA;
51
+        }
52
+
53
+        /* header */
54
+        avio_wb16(s->pb, SUP_PGS_MAGIC);
55
+        avio_wb32(s->pb, pts);
56
+        avio_wb32(s->pb, dts);
57
+
58
+        avio_write(s->pb, data, len);
59
+
60
+        data += len;
61
+        size -= len;
62
+    }
63
+
64
+    if (size > 0) {
65
+        av_log(s, AV_LOG_ERROR, "Skipping %d bytes after last segment in frame\n",
66
+                 (int)size);
67
+        return AVERROR_INVALIDDATA;
68
+    }
69
+
70
+    return 0;
71
+}
72
+
73
+static int sup_write_header(AVFormatContext *s)
74
+{
75
+    if (s->nb_streams != 1) {
76
+        av_log(s, AV_LOG_ERROR, "%s files have exactly one stream\n",
77
+               s->oformat->name);
78
+        return AVERROR(EINVAL);
79
+    }
80
+
81
+    avpriv_set_pts_info(s->streams[0], 32, 1, 90000);
82
+
83
+    return 0;
84
+}
85
+
86
+AVOutputFormat ff_sup_muxer = {
87
+    .name           = "sup",
88
+    .long_name      = NULL_IF_CONFIG_SMALL("raw HDMV Presentation Graphic Stream subtitles"),
89
+    .extensions     = "sup",
90
+    .mime_type      = "application/x-pgs",
91
+    .subtitle_codec = AV_CODEC_ID_HDMV_PGS_SUBTITLE,
92
+    .write_header   = sup_write_header,
93
+    .write_packet   = sup_write_packet,
94
+    .flags          = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT,
95
+};
... ...
@@ -32,7 +32,7 @@
32 32
 // Major bumping may affect Ticket5467, 5421, 5451(compatibility with Chromium)
33 33
 // Also please add any ticket numbers that you believe might be affected here
34 34
 #define LIBAVFORMAT_VERSION_MAJOR  57
35
-#define LIBAVFORMAT_VERSION_MINOR  81
35
+#define LIBAVFORMAT_VERSION_MINOR  82
36 36
 #define LIBAVFORMAT_VERSION_MICRO 100
37 37
 
38 38
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \