Browse code

add MicroDVD muxer and demuxer

Signed-off-by: Aurelien Jacobs <aurel@gnuage.org>

Aurelien Jacobs authored on 2010/09/11 06:10:53
Showing 9 changed files
... ...
@@ -88,6 +88,7 @@ version <next>:
88 88
 - Linux framebuffer input device added
89 89
 - Chronomaster DFA decoder
90 90
 - DPX image encoder
91
+- MicroDVD subtitle file muxer and demuxer
91 92
 
92 93
 
93 94
 version 0.6:
... ...
@@ -294,6 +294,7 @@ Muxers/Demuxers:
294 294
   matroskadec.c                         Aurelien Jacobs
295 295
   matroskaenc.c                         David Conrad
296 296
   metadata*                             Aurelien Jacobs
297
+  microdvd*                             Aurelien Jacobs
297 298
   mm.c                                  Peter Ross
298 299
   mov.c                                 Michael Niedermayer, Baptiste Coudurier
299 300
   movenc.c                              Michael Niedermayer, Baptiste Coudurier
... ...
@@ -703,6 +703,7 @@ performance on systems without hardware floating point support).
703 703
 @item SSA/ASS      @tab X @tab X @tab X @tab X
704 704
 @item DVB          @tab X @tab X @tab X @tab X
705 705
 @item DVD          @tab X @tab X @tab X @tab X
706
+@item MicroDVD     @tab X @tab X @tab   @tab
706 707
 @item PGS          @tab   @tab   @tab   @tab X
707 708
 @item SubRip (SRT) @tab X @tab X @tab X @tab X
708 709
 @item XSUB         @tab   @tab   @tab X @tab X
... ...
@@ -353,6 +353,7 @@ enum CodecID {
353 353
     CODEC_ID_HDMV_PGS_SUBTITLE,
354 354
     CODEC_ID_DVB_TELETEXT,
355 355
     CODEC_ID_SRT,
356
+    CODEC_ID_MICRODVD,
356 357
 
357 358
     /* other specific kind of codecs (generally used for attachments) */
358 359
     CODEC_ID_TTF= 0x18000,
... ...
@@ -122,6 +122,8 @@ OBJS-$(CONFIG_MATROSKA_MUXER)            += matroskaenc.o matroska.o \
122 122
                                             riff.o isom.o avc.o \
123 123
                                             flacenc_header.o avlanguage.o
124 124
 OBJS-$(CONFIG_MD5_MUXER)                 += md5enc.o
125
+OBJS-$(CONFIG_MICRODVD_DEMUXER)          += microdvddec.o
126
+OBJS-$(CONFIG_MICRODVD_MUXER)            += microdvdenc.o rawenc.o
125 127
 OBJS-$(CONFIG_MJPEG_DEMUXER)             += rawdec.o
126 128
 OBJS-$(CONFIG_MJPEG_MUXER)               += rawenc.o
127 129
 OBJS-$(CONFIG_MLP_DEMUXER)               += rawdec.o
... ...
@@ -118,6 +118,7 @@ void av_register_all(void)
118 118
     REGISTER_MUXER    (MD5, md5);
119 119
     REGISTER_MUXDEMUX (MATROSKA, matroska);
120 120
     REGISTER_MUXER    (MATROSKA_AUDIO, matroska_audio);
121
+    REGISTER_MUXDEMUX (MICRODVD, microdvd);
121 122
     REGISTER_MUXDEMUX (MJPEG, mjpeg);
122 123
     REGISTER_MUXDEMUX (MLP, mlp);
123 124
     REGISTER_DEMUXER  (MM, mm);
124 125
new file mode 100644
... ...
@@ -0,0 +1,129 @@
0
+/*
1
+ * MicroDVD subtitle demuxer
2
+ * Copyright (c) 2010  Aurelien Jacobs <aurel@gnuage.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 "avformat.h"
22
+#include "internal.h"
23
+#include "libavutil/intreadwrite.h"
24
+
25
+#define MAX_LINESIZE 2048
26
+
27
+
28
+typedef struct {
29
+    uint8_t lines[3][MAX_LINESIZE];
30
+    int64_t pos[3];
31
+} MicroDVDContext;
32
+
33
+
34
+static int microdvd_probe(AVProbeData *p)
35
+{
36
+    unsigned char c, *ptr = p->buf;
37
+    int i;
38
+
39
+    if (AV_RB24(ptr) == 0xEFBBBF)
40
+        ptr += 3;  /* skip UTF-8 BOM */
41
+
42
+    for (i=0; i<3; i++) {
43
+        if (sscanf(ptr, "{%*d}{}%c",     &c) != 1 &&
44
+            sscanf(ptr, "{%*d}{%*d}%c",  &c) != 1 &&
45
+            sscanf(ptr, "{DEFAULT}{}%c", &c) != 1)
46
+            return 0;
47
+        ptr += strcspn(ptr, "\n") + 1;
48
+    }
49
+    return AVPROBE_SCORE_MAX;
50
+}
51
+
52
+static int microdvd_read_header(AVFormatContext *s, AVFormatParameters *ap)
53
+{
54
+    AVRational pts_info = (AVRational){ 2997, 125 };  /* default: 23.976 fps */
55
+    MicroDVDContext *microdvd = s->priv_data;
56
+    AVStream *st = av_new_stream(s, 0);
57
+    int i, frame;
58
+    double fps;
59
+    char c;
60
+
61
+    if (!st)
62
+        return -1;
63
+    for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) {
64
+        microdvd->pos[i] = avio_tell(s->pb);
65
+        ff_get_line(s->pb, microdvd->lines[i], sizeof(microdvd->lines[i]));
66
+        if ((sscanf(microdvd->lines[i], "{%d}{}%6lf",    &frame, &fps) == 2 ||
67
+             sscanf(microdvd->lines[i], "{%d}{%*d}%6lf", &frame, &fps) == 2)
68
+            && frame <= 1 && fps > 3 && fps < 100)
69
+            pts_info = av_d2q(fps, 100000);
70
+        if (sscanf(microdvd->lines[i], "{DEFAULT}{}%c", &c) == 1) {
71
+            st->codec->extradata = av_strdup(microdvd->lines[i] + 11);
72
+            st->codec->extradata_size = strlen(st->codec->extradata);
73
+            i--;
74
+        }
75
+    }
76
+    av_set_pts_info(st, 64, pts_info.den, pts_info.num);
77
+    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
78
+    st->codec->codec_id   = CODEC_ID_MICRODVD;
79
+    return 0;
80
+}
81
+
82
+static int64_t get_pts(const char *buf)
83
+{
84
+    int frame;
85
+    char c;
86
+
87
+    if (sscanf(buf, "{%d}{%c", &frame, &c) == 2)
88
+        return frame;
89
+    return AV_NOPTS_VALUE;
90
+}
91
+
92
+static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt)
93
+{
94
+    MicroDVDContext *microdvd = s->priv_data;
95
+    char buffer[MAX_LINESIZE];
96
+    int64_t pos = avio_tell(s->pb);
97
+    int i, len = 0, res = AVERROR_EOF;
98
+
99
+    for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) {
100
+        if (microdvd->lines[i][0]) {
101
+            strcpy(buffer, microdvd->lines[i]);
102
+            pos = microdvd->pos[i];
103
+            len = strlen(buffer);
104
+            microdvd->lines[i][0] = 0;
105
+            break;
106
+        }
107
+    }
108
+    if (!len)
109
+        len = ff_get_line(s->pb, buffer, sizeof(buffer));
110
+
111
+    if (buffer[0] && !(res = av_new_packet(pkt, len))) {
112
+        memcpy(pkt->data, buffer, len);
113
+        pkt->flags |= AV_PKT_FLAG_KEY;
114
+        pkt->pos = pos;
115
+        pkt->pts = pkt->dts = get_pts(buffer);
116
+    }
117
+    return res;
118
+}
119
+
120
+AVInputFormat ff_microdvd_demuxer = {
121
+    .name           = "microdvd",
122
+    .long_name      = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
123
+    .priv_data_size = sizeof(MicroDVDContext),
124
+    .read_probe     = microdvd_probe,
125
+    .read_header    = microdvd_read_header,
126
+    .read_packet    = microdvd_read_packet,
127
+    .flags          = AVFMT_GENERIC_INDEX,
128
+};
0 129
new file mode 100644
... ...
@@ -0,0 +1,51 @@
0
+/*
1
+ * MicroDVD subtitle muxer
2
+ * Copyright (c) 2010  Aurelien Jacobs <aurel@gnuage.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 "avformat.h"
22
+#include "rawenc.h"
23
+
24
+static int microdvd_write_header(struct AVFormatContext *s)
25
+{
26
+    AVCodecContext *avctx = s->streams[0]->codec;
27
+
28
+    if (s->nb_streams != 1 || avctx->codec_id != CODEC_ID_MICRODVD) {
29
+        av_log(s, AV_LOG_ERROR, "Exactly one MicroDVD stream is needed.\n");
30
+        return -1;
31
+    }
32
+
33
+    if (avctx->extradata && avctx->extradata_size > 0) {
34
+        avio_write(s->pb, "{DEFAULT}{}", 11);
35
+        avio_write(s->pb, avctx->extradata, avctx->extradata_size);
36
+        avio_flush(s->pb);
37
+    }
38
+    return 0;
39
+}
40
+
41
+AVOutputFormat ff_microdvd_muxer = {
42
+    .name           = "microdvd",
43
+    .long_name      = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
44
+    .mime_type      = "text/x-microdvd",
45
+    .extensions     = "sub",
46
+    .write_header   = microdvd_write_header,
47
+    .write_packet   = ff_raw_write_packet,
48
+    .flags          = AVFMT_NOTIMESTAMPS,
49
+    .subtitle_codec = CODEC_ID_MICRODVD,
50
+};
... ...
@@ -24,7 +24,7 @@
24 24
 #include "libavutil/avutil.h"
25 25
 
26 26
 #define LIBAVFORMAT_VERSION_MAJOR 52
27
-#define LIBAVFORMAT_VERSION_MINOR 104
27
+#define LIBAVFORMAT_VERSION_MINOR 105
28 28
 #define LIBAVFORMAT_VERSION_MICRO  0
29 29
 
30 30
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \