[FFmpeg-devel] [PATCH 1/2] movtextenc: 3GPP TS 26.245 Timed Text Encoder.

Clément Bœsch ubitux at gmail.com
Thu Jul 26 22:05:37 CEST 2012


On Sat, Jul 21, 2012 at 03:19:52PM -0700, Philip Langdale wrote:
> This change introduces a basic encoder for 3GPP Timed Text subtitles,
> also known as TX3G, Quicktime subtitles, or "movtext" in the existing
> code.
> 
> This initial change doesn't attempt to write styling information,
> and just writes the plain text of the subtitles. I intend to add
> support for styles eventually, but it's challenging due to a lack
> of existing players that support them.
> 
> Note that an additional change is required to the mov/mp4 muxer to
> write empty subtitle packets to indicate subtitle duration.
> 
> Signed-off-by: Philip Langdale <philipl at overt.org>
> ---
>  Changelog               |    2 +-
>  doc/general.texi        |    2 +-
>  libavcodec/Makefile     |    1 +
>  libavcodec/allcodecs.c  |    2 +-
>  libavcodec/movtextenc.c |  164 +++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/version.h    |    2 +-
>  6 files changed, 169 insertions(+), 4 deletions(-)
>  create mode 100644 libavcodec/movtextenc.c
> 
> diff --git a/Changelog b/Changelog
> index ab8e704..b02580c 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -29,7 +29,7 @@ version next:
>  - iec61883 device
>  - asettb filter
>  - new option: -progress
> -- 3GPP Timed Text decoder
> +- 3GPP Timed Text encoder/decoder
>  - GeoTIFF decoder support
>  - ffmpeg -(no)stdin option
>  - Opus decoder using libopus
> diff --git a/doc/general.texi b/doc/general.texi
> index 370765e..adbb260 100644
> --- a/doc/general.texi
> +++ b/doc/general.texi
> @@ -885,7 +885,7 @@ performance on systems without hardware floating point support).
>  @item RealText         @tab   @tab X @tab   @tab X
>  @item SAMI             @tab   @tab X @tab   @tab X
>  @item SubRip (SRT)     @tab X @tab X @tab X @tab X
> - at item 3GPP Timed Text  @tab   @tab   @tab   @tab X
> + at item 3GPP Timed Text  @tab   @tab   @tab X @tab X
>  @item XSUB             @tab   @tab   @tab X @tab X
>  @end multitable
>  
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 52fd714..e6f61b8 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -267,6 +267,7 @@ 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_MOVTEXT_ENCODER)         += movtextenc.o ass_split.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 1db3800..f48f774 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -409,7 +409,7 @@ void avcodec_register_all(void)
>      REGISTER_ENCDEC  (DVDSUB, dvdsub);
>      REGISTER_DECODER (JACOSUB, jacosub);
>      REGISTER_DECODER (MICRODVD, microdvd);
> -    REGISTER_DECODER (MOVTEXT, movtext);
> +    REGISTER_ENCDEC  (MOVTEXT, movtext);
>      REGISTER_DECODER (PGSSUB, pgssub);
>      REGISTER_DECODER (REALTEXT, realtext);
>      REGISTER_DECODER (SAMI, sami);
> diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c
> new file mode 100644
> index 0000000..b2ff8b7
> --- /dev/null
> +++ b/libavcodec/movtextenc.c
> @@ -0,0 +1,164 @@
> +/*
> + * 3GPP TS 26.245 Timed Text encoder
> + * 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 <stdarg.h>
> +#include "avcodec.h"
> +#include "movtext.h"

The patch is missing that file so I can't really test the patch.

> +#include "libavutil/avstring.h"
> +#include "ass_split.h"
> +#include "ass.h"
> +
> +typedef struct {
> +    AVCodecContext *avctx;
> +    ASSSplitContext *ass_ctx;
> +    char buffer[2048];
> +    char *ptr;
> +    char *end;
> +} MovTextContext;
> +
> +
> +static av_cold int mov_text_encode_init(AVCodecContext *avctx)
> +{
> +    /*
> +     * For now, we'll use a fixed default style. When we add styling
> +     * support, this will be generated from the ASS style.
> +     */
> +    static uint8_t text_sample_entry[] = {
> +        0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags
> +        0x01,                   // int8_t horizontal-justification
> +        0xFF,                   // int8_t vertical-justification
> +        0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4]
> +        // BoxRecord {
> +        0x00, 0x00,             // int16_t top
> +        0x00, 0x00,             // int16_t left
> +        0x00, 0x00,             // int16_t bottom
> +        0x00, 0x00,             // int16_t right
> +        // };
> +        // StyleRecord {
> +        0x00, 0x00,             // uint16_t startChar
> +        0x00, 0x00,             // uint16_t endChar
> +        0x00, 0x01,             // uint16_t font-ID
> +        0x00,                   // uint8_t face-style-flags
> +        0x12,                   // uint8_t font-size
> +        0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4]
> +        // };
> +        // FontTableBox {
> +        0x00, 0x00, 0x00, 0x12, // uint32_t size
> +        'f', 't', 'a', 'b',     // uint8_t name[4]
> +        0x00, 0x01,             // uint16_t entry-count
> +        // FontRecord {
> +        0x00, 0x01,             // uint16_t font-ID
> +        0x05,                   // uint8_t font-name-length
> +        'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length]

nit: doesn't Serif look weird for subtitles?

> +        // };
> +        // };
> +    };
> +
> +    MovTextContext *s = avctx->priv_data;
> +
> +    avctx->extradata_size = sizeof text_sample_entry;

I don't think it has any impact in this particular case, but no need for
an extra padding size?

note: I don't mind the missing () after sizeof but we tend to prefer with
them.

> +    avctx->extradata = av_mallocz(avctx->extradata_size);
> +    if (!avctx->extradata)
> +    	return AVERROR(ENOMEM);

You have a tab here

> +
> +    memcpy(avctx->extradata, text_sample_entry, avctx->extradata_size);
> +
> +    s->avctx = avctx;

I maybe be missing something but are you really using this saved pointer
somewhere?

> +    s->ass_ctx = ff_ass_split(avctx->subtitle_header);
> +    return s->ass_ctx ? 0 : AVERROR_INVALIDDATA;
> +}
> +
> +static void mov_text_text_cb(void *priv, const char *text, int len)
> +{
> +    MovTextContext *s = priv;
> +    av_strlcpy(s->ptr, text, FFMIN(s->end - s->ptr, len + 1));
> +    s->ptr += len;
> +}
> +
> +static void mov_text_new_line_cb(void *priv, int forced)
> +{
> +    MovTextContext *s = priv;
> +    av_strlcpy(s->ptr, "\n", FFMIN(s->end - s->ptr, 2));
> +    s->ptr++;
> +}
> +
> +static const ASSCodesCallbacks mov_text_callbacks = {
> +    .text     = mov_text_text_cb,
> +    .new_line = mov_text_new_line_cb,
> +};
> +
> +static int mov_text_encode_frame(AVCodecContext *avctx,
> +                            unsigned char *buf, int bufsize, void *data)

nit: align

> +{
> +    MovTextContext *s = avctx->priv_data;
> +    AVSubtitle *sub = data;
> +    ASSDialog *dialog;
> +    int i, len, num;
> +
> +    s->ptr = s->buffer;
> +    s->end = s->ptr + sizeof(s->buffer);
> +
> +    for (i=0; i<sub->num_rects; i++) {

nit: some spacing around operators

> +
> +        if (sub->rects[i]->type != SUBTITLE_ASS) {
> +            av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
> +            return AVERROR(ENOSYS);
> +        }
> +
> +        dialog = ff_ass_split_dialog(s->ass_ctx, sub->rects[i]->ass, 0, &num);
> +        for (; dialog && num--; dialog++) {
> +            ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
> +        }
> +    }
> +
> +    if (s->ptr == s->buffer)
> +        return 0;
> +
> +    AV_WB16(buf, strlen(s->buffer));
> +    buf += 2;
> +
> +    len = av_strlcpy(buf, s->buffer, bufsize - 2);
> +
> +    if (len > bufsize-3) {
> +        av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
> +        return -1;

AVERROR(EINVAL) or something maybe.

[...]

-- 
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/20120726/a134e9cd/attachment.asc>


More information about the ffmpeg-devel mailing list