From 3c4b5275b6dd76ef0be2f77ea13b03968d66ed1b Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Thu, 24 Oct 2013 00:04:05 +0200 Subject: [PATCH] libzvbi-teletextdec: output ass subtitles instead of plain text Signed-off-by: Marton Balint --- libavcodec/libzvbi-teletextdec.c | 52 +++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/libavcodec/libzvbi-teletextdec.c b/libavcodec/libzvbi-teletextdec.c index c65268d016..b22a87e860 100644 --- a/libavcodec/libzvbi-teletextdec.c +++ b/libavcodec/libzvbi-teletextdec.c @@ -19,6 +19,7 @@ */ #include "avcodec.h" +#include "libavcodec/ass.h" #include "libavutil/opt.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" @@ -49,7 +50,7 @@ typedef struct TeletextContext char *pgno; int x_offset; int y_offset; - int format_id; /* 0 = bitmap, 1 = text */ + int format_id; /* 0 = bitmap, 1 = text/ass */ int chop_top; int sub_duration; /* in msec */ int transparent_bg; @@ -88,10 +89,43 @@ subtitle_rect_free(AVSubtitleRect **sub_rect) { av_freep(&(*sub_rect)->pict.data[0]); av_freep(&(*sub_rect)->pict.data[1]); - av_freep(&(*sub_rect)->text); + av_freep(&(*sub_rect)->ass); av_freep(sub_rect); } +static int +create_ass_text(TeletextContext *ctx, const char *text, char **ass) +{ + int ret; + AVBPrint buf, buf2; + const int ts_start = av_rescale_q(ctx->pts, AV_TIME_BASE_Q, (AVRational){1, 100}); + const int ts_duration = av_rescale_q(ctx->sub_duration, (AVRational){1, 1000}, (AVRational){1, 100}); + + /* First we escape the plain text into buf. */ + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + ff_ass_bprint_text_event(&buf, text, strlen(text), "", 0); + + if (!av_bprint_is_complete(&buf)) { + av_bprint_finalize(&buf, NULL); + return AVERROR(ENOMEM); + } + + /* Then we create the ass dialog line in buf2 from the escaped text in buf. */ + av_bprint_init(&buf2, 0, AV_BPRINT_SIZE_UNLIMITED); + ff_ass_bprint_dialog(&buf2, buf.str, ts_start, ts_duration, 0); + av_bprint_finalize(&buf, NULL); + + if (!av_bprint_is_complete(&buf2)) { + av_bprint_finalize(&buf2, NULL); + return AVERROR(ENOMEM); + } + + if ((ret = av_bprint_finalize(&buf2, ass)) < 0) + return ret; + + return 0; +} + // draw a page as text static int gen_sub_text(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page *page, int chop_top) @@ -147,14 +181,16 @@ gen_sub_text(TeletextContext *ctx, AVSubtitleRect *sub_rect, vbi_page *page, int if (buf.len) { int ret; - sub_rect->type = SUBTITLE_TEXT; - if ((ret = av_bprint_finalize(&buf, &sub_rect->text)) < 0) + sub_rect->type = SUBTITLE_ASS; + if ((ret = create_ass_text(ctx, buf.str, &sub_rect->ass)) < 0) { + av_bprint_finalize(&buf, NULL); return ret; - av_log(ctx, AV_LOG_DEBUG, "subtext:%s:txetbus\n", sub_rect->text); + } + av_log(ctx, AV_LOG_DEBUG, "subtext:%s:txetbus\n", sub_rect->ass); } else { sub_rect->type = SUBTITLE_NONE; - av_bprint_finalize(&buf, NULL); } + av_bprint_finalize(&buf, NULL); return 0; } @@ -393,7 +429,7 @@ teletext_decode_frame(AVCodecContext *avctx, // is there a subtitle to pass? if (ctx->nb_pages) { int i; - sub->format = (ctx->pages->sub_rect->type == SUBTITLE_TEXT ? 1: 0); + sub->format = ctx->format_id; sub->start_display_time = 0; sub->end_display_time = ctx->sub_duration; sub->num_rects = 0; @@ -445,7 +481,7 @@ static int teletext_init_decoder(AVCodecContext *avctx) } #endif av_log(avctx, AV_LOG_VERBOSE, "page filter: %s\n", ctx->pgno); - return 0; + return (ctx->format_id == 1) ? ff_ass_subtitle_header_default(avctx) : 0; } static int teletext_close_decoder(AVCodecContext *avctx)