[FFmpeg-devel] [PATCH] movtextdec: MPEG4 Part 17 Timed Text Decoder.
Philip Langdale
philipl at overt.org
Sun Jul 1 19:29:15 CEST 2012
This change introduces a basic decoder for MPEG4 Part 17 subtitles,
also known as Timed Text and TX3G.
This initial change doesn't attempt to parse styling information,
and just reads the plain text of the subtitles. I intend to add
support for styles eventually, but it's challenging due to a lack
of reliable samples and existing players that support them.
---
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/movtextdec.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+)
create mode 100644 libavcodec/movtextdec.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 95bcb17..ec7ddca 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -265,6 +265,7 @@ OBJS-$(CONFIG_MJPEGB_DECODER) += mjpegbdec.o mjpegdec.o mjpeg.o
OBJS-$(CONFIG_MLP_DECODER) += mlpdec.o mlpdsp.o
OBJS-$(CONFIG_MMVIDEO_DECODER) += mmvideo.o
OBJS-$(CONFIG_MOTIONPIXELS_DECODER) += motionpixels.o
+OBJS-$(CONFIG_MOVTEXT_DECODER) += movtextdec.o ass.o
OBJS-$(CONFIG_MP1_DECODER) += mpegaudiodec.o mpegaudiodecheader.o \
mpegaudio.o mpegaudiodata.o
OBJS-$(CONFIG_MP1FLOAT_DECODER) += mpegaudiodec_float.o mpegaudiodecheader.o \
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 8c2bd2b..0674a7c 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -404,6 +404,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (DVDSUB, dvdsub);
REGISTER_DECODER (JACOSUB, jacosub);
REGISTER_DECODER (MICRODVD, microdvd);
+ REGISTER_DECODER (MOVTEXT, movtext);
REGISTER_DECODER (PGSSUB, pgssub);
REGISTER_ENCDEC (SRT, srt);
REGISTER_ENCDEC (XSUB, xsub);
diff --git a/libavcodec/movtextdec.c b/libavcodec/movtextdec.c
new file mode 100644
index 0000000..63b869d
--- /dev/null
+++ b/libavcodec/movtextdec.c
@@ -0,0 +1,114 @@
+/*
+ * 3GPP TS 26.245/MPEG4 Part 17 Timed Text decoder
+ * Copyright (c) 2012 Philip Langdale <philipl at overt.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 "avcodec.h"
+#include "ass.h"
+#include "libavutil/avstring.h"
+#include "libavutil/bprint.h"
+#include "libavutil/intreadwrite.h"
+
+static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end)
+{
+ int line_start = 1;
+
+ while (text < text_end) {
+ switch (*text) {
+ case '\r':
+ line_start = 1;
+ break;
+ case '\n':
+ av_bprintf(buf, "\\N");
+ line_start = 1;
+ break;
+ case ' ':
+ // 1) Don't transfer leading whitespace
+ // 2) Don't transfer multiple spaces
+ // 3) Don't transfer trailing whitespace
+ if (!line_start && text + 1 != text_end &&
+ text[1] != ' ' &&
+ text[1] != '\r' && text[1] != '\n')
+ av_bprint_chars(buf, *text, 1);
+ break;
+ default:
+ av_bprint_chars(buf, *text, 1);
+ line_start = 0;
+ break;
+ }
+ text++;
+ }
+
+ av_bprintf(buf, "\r\n");
+ return 0;
+}
+
+static int mov_text_init(AVCodecContext *avctx) {
+ /*
+ * TODO: Handle the default text style.
+ * NB: Most players ignore styles completely, with the result that
+ * it's very common to find files where the default style is broken
+ * and respecting it results in a worse experience than ignoring it.
+ */
+ return ff_ass_subtitle_header_default(avctx);
+}
+
+static int mov_text_decode_frame(AVCodecContext *avctx,
+ void *data, int *got_sub_ptr, AVPacket *avpkt)
+{
+ AVSubtitle *sub = data;
+ int ts_start, ts_end;
+ AVBPrint buf;
+ const char *ptr = avpkt->data;
+ const char *end;
+
+ if (!ptr || avpkt->size <= 2)
+ return 0;
+
+ /*
+ * The first two bytes of the packet are the length of the text string
+ * In complex cases, there are style descriptors appended to the string
+ * so we can't just assume the packet size is the string size.
+ */
+ end = ptr + 2 + AV_RB16(ptr);
+ ptr += 2;
+
+ ts_start = av_rescale_q(avpkt->pts,
+ avctx->time_base,
+ (AVRational){1,100});
+ ts_end = av_rescale_q(avpkt->pts + avpkt->duration,
+ avctx->time_base,
+ (AVRational){1,100});
+
+ av_bprint_init(&buf, 0, 2048);
+ text_to_ass(&buf, ptr, end);
+ ff_ass_add_rect(sub, buf.str, ts_start, ts_end-ts_start, 0);
+ *got_sub_ptr = sub->num_rects > 0;
+ av_bprint_finalize(&buf, NULL);
+ return avpkt->size;
+}
+
+AVCodec ff_movtext_decoder = {
+ .name = "mov_text",
+ .long_name = NULL_IF_CONFIG_SMALL("MPEG4 Part 17 subtitle"),
+ .type = AVMEDIA_TYPE_SUBTITLE,
+ .id = CODEC_ID_MOV_TEXT,
+ .init = mov_text_init,
+ .decode = mov_text_decode_frame,
+};
--
1.7.9.5
More information about the ffmpeg-devel
mailing list