[FFmpeg-devel] [PATCH] movtextdec: MPEG4 Part 17 Timed Text Decoder.

Clément Bœsch ubitux at gmail.com
Thu Jul 5 00:01:01 CEST 2012


On Wed, Jul 04, 2012 at 11:10:32AM -0700, Philip Langdale wrote:
> 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.
> 
> Signed-off-by: Philip Langdale <philipl at overt.org>
> ---
>  Changelog                  |    1 +
>  doc/general.texi           |   21 ++++----
>  libavcodec/Makefile        |    1 +
>  libavcodec/allcodecs.c     |    1 +
>  libavcodec/movtextdec.c    |  114 ++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/version.h       |    2 +-
>  tests/fate/subtitles.mak   |    3 ++
>  tests/ref/fate/sub-movtext |    1 +
>  8 files changed, 133 insertions(+), 11 deletions(-)
>  create mode 100644 libavcodec/movtextdec.c
>  create mode 100644 tests/ref/fate/sub-movtext
> 

Doesn't apply on HEAD and your tree looks not up to date.

> diff --git a/Changelog b/Changelog
> index a899023..530bd60 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -18,6 +18,7 @@ version next:
>  - LucasArts SMUSH playback support
>  - SAMI demuxer and decoder
>  - RealText demuxer and decoder
> +- MPEG4 Part 17 Timed Text decoder
>  
>  
>  version 0.11:
> diff --git a/doc/general.texi b/doc/general.texi
> index 2ca10cd..9bde6aa 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -858,16 +858,17 @@ performance on systems without hardware floating point support).
>  
>  @multitable @columnfractions .4 .1 .1 .1 .1
>  @item Name @tab Muxing @tab Demuxing @tab Encoding @tab Decoding
> - at item SSA/ASS      @tab X @tab X @tab X @tab X
> - at item DVB          @tab X @tab X @tab X @tab X
> - at item DVD          @tab X @tab X @tab X @tab X
> - at item JACOsub      @tab X @tab X @tab   @tab X
> - at item MicroDVD     @tab X @tab X @tab   @tab X
> - at item PGS          @tab   @tab   @tab   @tab X
> - at item RealText     @tab   @tab X @tab   @tab X
> - at item SAMI         @tab   @tab X @tab   @tab X
> - at item SubRip (SRT) @tab X @tab X @tab X @tab X
> - at item XSUB         @tab   @tab   @tab X @tab X
> + at item SSA/ASS          @tab X @tab X @tab X @tab X
> + at item DVB              @tab X @tab X @tab X @tab X
> + at item DVD              @tab X @tab X @tab X @tab X
> + at item JACOsub          @tab X @tab X @tab   @tab X
> + at item MicroDVD         @tab X @tab X @tab   @tab X
> + at item MPEG4 Timed Text @tab   @tab   @tab   @tab X
> + at item PGS              @tab   @tab   @tab   @tab X
> + at item RealText         @tab   @tab X @tab   @tab X
> + at item SAMI             @tab   @tab X @tab   @tab X
> + at item SubRip (SRT)     @tab X @tab X @tab X @tab X
> + at item XSUB             @tab   @tab   @tab X @tab X
>  @end multitable
>  
>  @code{X} means that the feature is supported.
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index e8fac7e..b613530 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 51e603e..c6216ce 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_DECODER (REALTEXT, realtext);
>      REGISTER_DECODER (SAMI, sami);
> 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

All that naming looks quite inconsistent: you use "mov text" (sometimes
"MPEG4 Timed Text"), but the specs are the MPEG-4 ones, and are talking
about "3GPP Timed Text" (and sometimes called "tx3g" right?) so wouldn't
it make sense to actually call that decoder tx3gdec.c?

AFAICT all of this is the same thing. Eventually you could add a @file
doxy to briefly give the good references, but I don't want to block this
patch.

> + * 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,
> +};
> diff --git a/libavcodec/version.h b/libavcodec/version.h
> index 5bfb7f4..275200f 100644
> --- a/libavcodec/version.h
> +++ b/libavcodec/version.h
> @@ -27,7 +27,7 @@
>   */
>  
>  #define LIBAVCODEC_VERSION_MAJOR 54
> -#define LIBAVCODEC_VERSION_MINOR  31
> +#define LIBAVCODEC_VERSION_MINOR  32

Don't bother with this, it's often a pain when rebasing or reviewing on a
more recent HEAD. Just add a "FIXME: bump lavc" or something in the commit
description, the commiter can fix that.

>  #define LIBAVCODEC_VERSION_MICRO 100
>  
>  #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
> diff --git a/tests/fate/subtitles.mak b/tests/fate/subtitles.mak
> index f2a68e1..92322da 100644
> --- a/tests/fate/subtitles.mak
> +++ b/tests/fate/subtitles.mak
> @@ -13,5 +13,8 @@ fate-sub-srt: CMD = md5 -i $(SAMPLES)/sub/SubRip_capability_tester.srt -f ass
>  FATE_SUBTITLES += fate-sub-realtext
>  fate-sub-realtext: CMD = md5 -i $(SAMPLES)/sub/RealText_capability_tester.rt -f ass
>  
> +FATE_SUBTITLES += fate-sub-movtext
> +fate-sub-movtext: CMD = md5 -i $(SAMPLES)/sub/MovText_capability_tester.mp4 -f ass
> +

Thank you very much for this.

Except the naming confusion, the patch LGTM. (I don't think it matters if
the samples is still called MovText_*)

Are you working on an encoder so we can mux subtitles in MOV/MP4?

[...]

-- 
Clément B.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120705/211f900b/attachment.asc>


More information about the ffmpeg-devel mailing list