#include <stdarg.h>
#include "avcodec.h"
+#include "libavutil/opt.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/intreadwrite.h"
#define DEFAULT_STYLE_FLAG 0x00
#define BGR_TO_RGB(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff))
+#define FONTSIZE_SCALE(s,fs) ((fs) * (s)->font_scale_factor + 0.5)
#define av_bprint_append_any(buf, data, size) av_bprint_append_data(buf, ((const char*)data), size)
typedef struct {
} HilightcolorBox;
typedef struct {
+ AVClass *class;
AVCodecContext *avctx;
ASSSplitContext *ass_ctx;
uint16_t byte_count;
char ** fonts;
int font_count;
+ double font_scale_factor;
+ int frame_height;
} MovTextContext;
typedef struct {
// Populate sample description from ASS header
ass = (ASS*)s->ass_ctx;
+ // Compute font scaling factor based on (optionally) provided
+ // output video height and ASS script play_res_y
+ if (s->frame_height && ass->script_info.play_res_y)
+ s->font_scale_factor = (double)s->frame_height / ass->script_info.play_res_y;
+ else
+ s->font_scale_factor = 1;
+
style = ff_ass_style_get(s->ass_ctx, "Default");
if (!style && ass->styles_count) {
style = &ass->styles[0];
s->d.style_color = DEFAULT_STYLE_COLOR;
s->d.style_flag = DEFAULT_STYLE_FLAG;
if (style) {
- s->d.style_fontsize = style->font_size;
+ s->d.style_fontsize = FONTSIZE_SCALE(s, style->font_size);
s->d.style_color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8 |
255 - ((uint32_t)style->primary_color >> 24);
s->d.style_flag = (!!style->bold * STYLE_FLAG_BOLD) |
if (color_id == 1) { //primary color changes
mov_text_color_set(s, color);
} else if (color_id == 2) { //secondary color changes
- if (s->box_flags & HLIT_BOX) { //close tag
- s->hlit.end = s->text_pos;
- } else {
+ if (!(s->box_flags & HCLR_BOX))
+ // Highlight alpha not set yet, use current primary alpha
+ s->hclr.color = s->style_attributes_temp->style_color;
+ if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) {
s->box_flags |= HCLR_BOX;
s->box_flags |= HLIT_BOX;
s->hlit.start = s->text_pos;
- s->hclr.color = color | 0xFF; //set alpha value to FF
+ s->hclr.color = color | (s->hclr.color & 0xFF);
}
+ else //close tag
+ s->hlit.end = s->text_pos;
+ /* If there are more than one secondary color changes in ASS,
+ take start of first section and end of last section. Movtext
+ allows only one highlight box per sample.
+ */
}
- /* If there are more than one secondary color changes in ASS, take start of
- first section and end of last section. Movtext allows only one
- highlight box per sample.
- */
+ // Movtext does not support changes to other color_id (outline, background)
}
static void mov_text_alpha_set(MovTextContext *s, uint8_t alpha)
{
MovTextContext *s = priv;
+ alpha = 255 - alpha;
if (alpha_id == 1) // primary alpha changes
- mov_text_alpha_set(s, 255 - alpha);
+ mov_text_alpha_set(s, alpha);
+ else if (alpha_id == 2) { //secondary alpha changes
+ if (!(s->box_flags & HCLR_BOX))
+ // Highlight color not set yet, use current primary color
+ s->hclr.color = s->style_attributes_temp->style_color;
+ if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) {
+ s->box_flags |= HCLR_BOX;
+ s->box_flags |= HLIT_BOX;
+ s->hlit.start = s->text_pos;
+ s->hclr.color = (s->hclr.color & 0xffffff00) | alpha;
+ }
+ else //close tag
+ s->hlit.end = s->text_pos;
+ }
+ // Movtext does not support changes to other alpha_id (outline, background)
}
static uint16_t find_font_id(MovTextContext * s, const char * name)
static void mov_text_font_size_set(MovTextContext *s, int size)
{
+ size = FONTSIZE_SCALE(s, size);
if (!s->style_attributes_temp ||
s->style_attributes_temp->style_fontsize == size) {
// color hasn't changed
if (sub->rects[i]->type != SUBTITLE_ASS) {
av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
- return AVERROR(ENOSYS);
+ return AVERROR(EINVAL);
}
#if FF_API_ASS_TIMING
if (s->buffer.len > bufsize - 3) {
av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
- length = AVERROR(EINVAL);
+ length = AVERROR_BUFFER_TOO_SMALL;
goto exit;
}
return length;
}
+#define OFFSET(x) offsetof(MovTextContext, x)
+#define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM
+static const AVOption options[] = {
+ { "height", "Frame height, usually video height", OFFSET(frame_height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
+ { NULL },
+};
+
+static const AVClass mov_text_encoder_class = {
+ .class_name = "MOV text enoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_movtext_encoder = {
.name = "mov_text",
.long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
.type = AVMEDIA_TYPE_SUBTITLE,
.id = AV_CODEC_ID_MOV_TEXT,
.priv_data_size = sizeof(MovTextContext),
+ .priv_class = &mov_text_encoder_class,
.init = mov_text_encode_init,
.encode_sub = mov_text_encode_frame,
.close = mov_text_encode_close,