add MicroDVD muxer and demuxer
authorAurelien Jacobs <aurel@gnuage.org>
Fri, 10 Sep 2010 21:10:53 +0000 (23:10 +0200)
committerAurelien Jacobs <aurel@gnuage.org>
Sun, 3 Apr 2011 23:29:40 +0000 (01:29 +0200)
Signed-off-by: Aurelien Jacobs <aurel@gnuage.org>
Changelog
MAINTAINERS
doc/general.texi
libavcodec/avcodec.h
libavformat/Makefile
libavformat/allformats.c
libavformat/microdvddec.c [new file with mode: 0644]
libavformat/microdvdenc.c [new file with mode: 0644]
libavformat/version.h

index 4833315..e60c278 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -88,6 +88,7 @@ version <next>:
 - Linux framebuffer input device added
 - Chronomaster DFA decoder
 - DPX image encoder
+- MicroDVD subtitle file muxer and demuxer
 
 
 version 0.6:
index 977df20..8588ba7 100644 (file)
@@ -294,6 +294,7 @@ Muxers/Demuxers:
   matroskadec.c                         Aurelien Jacobs
   matroskaenc.c                         David Conrad
   metadata*                             Aurelien Jacobs
+  microdvd*                             Aurelien Jacobs
   mm.c                                  Peter Ross
   mov.c                                 Michael Niedermayer, Baptiste Coudurier
   movenc.c                              Michael Niedermayer, Baptiste Coudurier
index 696db58..3e4dbd2 100644 (file)
@@ -703,6 +703,7 @@ performance on systems without hardware floating point support).
 @item SSA/ASS      @tab X @tab X @tab X @tab X
 @item DVB          @tab X @tab X @tab X @tab X
 @item DVD          @tab X @tab X @tab X @tab X
+@item MicroDVD     @tab X @tab X @tab   @tab
 @item PGS          @tab   @tab   @tab   @tab X
 @item SubRip (SRT) @tab X @tab X @tab X @tab X
 @item XSUB         @tab   @tab   @tab X @tab X
index 6c7ec0e..4659719 100644 (file)
@@ -353,6 +353,7 @@ enum CodecID {
     CODEC_ID_HDMV_PGS_SUBTITLE,
     CODEC_ID_DVB_TELETEXT,
     CODEC_ID_SRT,
+    CODEC_ID_MICRODVD,
 
     /* other specific kind of codecs (generally used for attachments) */
     CODEC_ID_TTF= 0x18000,
index 719783c..5a2a5f4 100644 (file)
@@ -122,6 +122,8 @@ OBJS-$(CONFIG_MATROSKA_MUXER)            += matroskaenc.o matroska.o \
                                             riff.o isom.o avc.o \
                                             flacenc_header.o avlanguage.o
 OBJS-$(CONFIG_MD5_MUXER)                 += md5enc.o
+OBJS-$(CONFIG_MICRODVD_DEMUXER)          += microdvddec.o
+OBJS-$(CONFIG_MICRODVD_MUXER)            += microdvdenc.o rawenc.o
 OBJS-$(CONFIG_MJPEG_DEMUXER)             += rawdec.o
 OBJS-$(CONFIG_MJPEG_MUXER)               += rawenc.o
 OBJS-$(CONFIG_MLP_DEMUXER)               += rawdec.o
index 3acaed9..7a8874f 100644 (file)
@@ -118,6 +118,7 @@ void av_register_all(void)
     REGISTER_MUXER    (MD5, md5);
     REGISTER_MUXDEMUX (MATROSKA, matroska);
     REGISTER_MUXER    (MATROSKA_AUDIO, matroska_audio);
+    REGISTER_MUXDEMUX (MICRODVD, microdvd);
     REGISTER_MUXDEMUX (MJPEG, mjpeg);
     REGISTER_MUXDEMUX (MLP, mlp);
     REGISTER_DEMUXER  (MM, mm);
diff --git a/libavformat/microdvddec.c b/libavformat/microdvddec.c
new file mode 100644 (file)
index 0000000..95c76af
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * MicroDVD subtitle demuxer
+ * Copyright (c) 2010  Aurelien Jacobs <aurel@gnuage.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "internal.h"
+#include "libavutil/intreadwrite.h"
+
+#define MAX_LINESIZE 2048
+
+
+typedef struct {
+    uint8_t lines[3][MAX_LINESIZE];
+    int64_t pos[3];
+} MicroDVDContext;
+
+
+static int microdvd_probe(AVProbeData *p)
+{
+    unsigned char c, *ptr = p->buf;
+    int i;
+
+    if (AV_RB24(ptr) == 0xEFBBBF)
+        ptr += 3;  /* skip UTF-8 BOM */
+
+    for (i=0; i<3; i++) {
+        if (sscanf(ptr, "{%*d}{}%c",     &c) != 1 &&
+            sscanf(ptr, "{%*d}{%*d}%c",  &c) != 1 &&
+            sscanf(ptr, "{DEFAULT}{}%c", &c) != 1)
+            return 0;
+        ptr += strcspn(ptr, "\n") + 1;
+    }
+    return AVPROBE_SCORE_MAX;
+}
+
+static int microdvd_read_header(AVFormatContext *s, AVFormatParameters *ap)
+{
+    AVRational pts_info = (AVRational){ 2997, 125 };  /* default: 23.976 fps */
+    MicroDVDContext *microdvd = s->priv_data;
+    AVStream *st = av_new_stream(s, 0);
+    int i, frame;
+    double fps;
+    char c;
+
+    if (!st)
+        return -1;
+    for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) {
+        microdvd->pos[i] = avio_tell(s->pb);
+        ff_get_line(s->pb, microdvd->lines[i], sizeof(microdvd->lines[i]));
+        if ((sscanf(microdvd->lines[i], "{%d}{}%6lf",    &frame, &fps) == 2 ||
+             sscanf(microdvd->lines[i], "{%d}{%*d}%6lf", &frame, &fps) == 2)
+            && frame <= 1 && fps > 3 && fps < 100)
+            pts_info = av_d2q(fps, 100000);
+        if (sscanf(microdvd->lines[i], "{DEFAULT}{}%c", &c) == 1) {
+            st->codec->extradata = av_strdup(microdvd->lines[i] + 11);
+            st->codec->extradata_size = strlen(st->codec->extradata);
+            i--;
+        }
+    }
+    av_set_pts_info(st, 64, pts_info.den, pts_info.num);
+    st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
+    st->codec->codec_id   = CODEC_ID_MICRODVD;
+    return 0;
+}
+
+static int64_t get_pts(const char *buf)
+{
+    int frame;
+    char c;
+
+    if (sscanf(buf, "{%d}{%c", &frame, &c) == 2)
+        return frame;
+    return AV_NOPTS_VALUE;
+}
+
+static int microdvd_read_packet(AVFormatContext *s, AVPacket *pkt)
+{
+    MicroDVDContext *microdvd = s->priv_data;
+    char buffer[MAX_LINESIZE];
+    int64_t pos = avio_tell(s->pb);
+    int i, len = 0, res = AVERROR_EOF;
+
+    for (i=0; i<FF_ARRAY_ELEMS(microdvd->lines); i++) {
+        if (microdvd->lines[i][0]) {
+            strcpy(buffer, microdvd->lines[i]);
+            pos = microdvd->pos[i];
+            len = strlen(buffer);
+            microdvd->lines[i][0] = 0;
+            break;
+        }
+    }
+    if (!len)
+        len = ff_get_line(s->pb, buffer, sizeof(buffer));
+
+    if (buffer[0] && !(res = av_new_packet(pkt, len))) {
+        memcpy(pkt->data, buffer, len);
+        pkt->flags |= AV_PKT_FLAG_KEY;
+        pkt->pos = pos;
+        pkt->pts = pkt->dts = get_pts(buffer);
+    }
+    return res;
+}
+
+AVInputFormat ff_microdvd_demuxer = {
+    .name           = "microdvd",
+    .long_name      = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
+    .priv_data_size = sizeof(MicroDVDContext),
+    .read_probe     = microdvd_probe,
+    .read_header    = microdvd_read_header,
+    .read_packet    = microdvd_read_packet,
+    .flags          = AVFMT_GENERIC_INDEX,
+};
diff --git a/libavformat/microdvdenc.c b/libavformat/microdvdenc.c
new file mode 100644 (file)
index 0000000..b2abc54
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * MicroDVD subtitle muxer
+ * Copyright (c) 2010  Aurelien Jacobs <aurel@gnuage.org>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "avformat.h"
+#include "rawenc.h"
+
+static int microdvd_write_header(struct AVFormatContext *s)
+{
+    AVCodecContext *avctx = s->streams[0]->codec;
+
+    if (s->nb_streams != 1 || avctx->codec_id != CODEC_ID_MICRODVD) {
+        av_log(s, AV_LOG_ERROR, "Exactly one MicroDVD stream is needed.\n");
+        return -1;
+    }
+
+    if (avctx->extradata && avctx->extradata_size > 0) {
+        avio_write(s->pb, "{DEFAULT}{}", 11);
+        avio_write(s->pb, avctx->extradata, avctx->extradata_size);
+        avio_flush(s->pb);
+    }
+    return 0;
+}
+
+AVOutputFormat ff_microdvd_muxer = {
+    .name           = "microdvd",
+    .long_name      = NULL_IF_CONFIG_SMALL("MicroDVD subtitle format"),
+    .mime_type      = "text/x-microdvd",
+    .extensions     = "sub",
+    .write_header   = microdvd_write_header,
+    .write_packet   = ff_raw_write_packet,
+    .flags          = AVFMT_NOTIMESTAMPS,
+    .subtitle_codec = CODEC_ID_MICRODVD,
+};
index 497779d..84b6c11 100644 (file)
@@ -24,7 +24,7 @@
 #include "libavutil/avutil.h"
 
 #define LIBAVFORMAT_VERSION_MAJOR 52
-#define LIBAVFORMAT_VERSION_MINOR 104
+#define LIBAVFORMAT_VERSION_MINOR 105
 #define LIBAVFORMAT_VERSION_MICRO  0
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \