yading@10: /* yading@10: * SSA/ASS common functions yading@10: * Copyright (c) 2010 Aurelien Jacobs yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: #include "avcodec.h" yading@10: #include "ass.h" yading@10: #include "libavutil/avassert.h" yading@10: #include "libavutil/avstring.h" yading@10: #include "libavutil/bprint.h" yading@10: #include "libavutil/common.h" yading@10: yading@10: int ff_ass_subtitle_header(AVCodecContext *avctx, yading@10: const char *font, int font_size, yading@10: int color, int back_color, yading@10: int bold, int italic, int underline, yading@10: int alignment) yading@10: { yading@10: avctx->subtitle_header = av_asprintf( yading@10: "[Script Info]\r\n" yading@10: "ScriptType: v4.00+\r\n" yading@10: "\r\n" yading@10: "[V4+ Styles]\r\n" yading@10: "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding\r\n" yading@10: "Style: Default,%s,%d,&H%x,&H%x,&H%x,&H%x,%d,%d,%d,1,1,0,%d,10,10,10,0,0\r\n" yading@10: "\r\n" yading@10: "[Events]\r\n" yading@10: "Format: Layer, Start, End, Style, Text\r\n", yading@10: font, font_size, color, color, back_color, back_color, yading@10: -bold, -italic, -underline, alignment); yading@10: yading@10: if (!avctx->subtitle_header) yading@10: return AVERROR(ENOMEM); yading@10: avctx->subtitle_header_size = strlen(avctx->subtitle_header); yading@10: return 0; yading@10: } yading@10: yading@10: int ff_ass_subtitle_header_default(AVCodecContext *avctx) yading@10: { yading@10: return ff_ass_subtitle_header(avctx, ASS_DEFAULT_FONT, yading@10: ASS_DEFAULT_FONT_SIZE, yading@10: ASS_DEFAULT_COLOR, yading@10: ASS_DEFAULT_BACK_COLOR, yading@10: ASS_DEFAULT_BOLD, yading@10: ASS_DEFAULT_ITALIC, yading@10: ASS_DEFAULT_UNDERLINE, yading@10: ASS_DEFAULT_ALIGNMENT); yading@10: } yading@10: yading@10: static void insert_ts(AVBPrint *buf, int ts) yading@10: { yading@10: if (ts == -1) { yading@10: av_bprintf(buf, "9:59:59.99,"); yading@10: } else { yading@10: int h, m, s; yading@10: yading@10: h = ts/360000; ts -= 360000*h; yading@10: m = ts/ 6000; ts -= 6000*m; yading@10: s = ts/ 100; ts -= 100*s; yading@10: av_bprintf(buf, "%d:%02d:%02d.%02d,", h, m, s, ts); yading@10: } yading@10: } yading@10: yading@10: int ff_ass_add_rect(AVSubtitle *sub, const char *dialog, yading@10: int ts_start, int duration, int raw) yading@10: { yading@10: AVBPrint buf; yading@10: int ret, dlen; yading@10: AVSubtitleRect **rects; yading@10: yading@10: av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); yading@10: if (!raw || raw == 2) { yading@10: long int layer = 0; yading@10: yading@10: if (raw == 2) { yading@10: /* skip ReadOrder */ yading@10: dialog = strchr(dialog, ','); yading@10: if (!dialog) yading@10: return AVERROR_INVALIDDATA; yading@10: dialog++; yading@10: yading@10: /* extract Layer or Marked */ yading@10: layer = strtol(dialog, (char**)&dialog, 10); yading@10: if (*dialog != ',') yading@10: return AVERROR_INVALIDDATA; yading@10: dialog++; yading@10: } yading@10: av_bprintf(&buf, "Dialogue: %ld,", layer); yading@10: insert_ts(&buf, ts_start); yading@10: insert_ts(&buf, duration == -1 ? -1 : ts_start + duration); yading@10: if (raw != 2) yading@10: av_bprintf(&buf, "Default,"); yading@10: } yading@10: yading@10: dlen = strcspn(dialog, "\n"); yading@10: dlen += dialog[dlen] == '\n'; yading@10: yading@10: av_bprintf(&buf, "%.*s", dlen, dialog); yading@10: if (raw == 2) yading@10: av_bprintf(&buf, "\r\n"); yading@10: if (!av_bprint_is_complete(&buf)) yading@10: return AVERROR(ENOMEM); yading@10: yading@10: rects = av_realloc(sub->rects, (sub->num_rects+1) * sizeof(*sub->rects)); yading@10: if (!rects) yading@10: return AVERROR(ENOMEM); yading@10: sub->rects = rects; yading@10: sub->end_display_time = FFMAX(sub->end_display_time, 10 * duration); yading@10: rects[sub->num_rects] = av_mallocz(sizeof(*rects[0])); yading@10: rects[sub->num_rects]->type = SUBTITLE_ASS; yading@10: ret = av_bprint_finalize(&buf, &rects[sub->num_rects]->ass); yading@10: if (ret < 0) yading@10: return ret; yading@10: sub->num_rects++; yading@10: return dlen; yading@10: }