#include "avcodec.h"
#include "ass.h"
+#include "libavutil/opt.h"
#include "libavutil/avstring.h"
#include "libavutil/common.h"
#include "libavutil/bprint.h"
uint8_t bold;
uint8_t italic;
uint8_t underline;
+ int color;
+ uint8_t alpha;
uint8_t fontsize;
uint16_t style_fontID;
} StyleBox;
} TextWrapBox;
typedef struct {
+ AVClass *class;
StyleBox **s;
StyleBox *s_temp;
HighlightBox h;
int size_var;
int count_s, count_f;
int readorder;
+ int frame_width;
+ int frame_height;
} MovTextContext;
typedef struct {
m->s_temp->underline = !!(m->s_temp->style_flag & STYLE_FLAG_UNDERLINE);
tsmb++;
m->s_temp->fontsize = AV_RB8(tsmb);
+ tsmb++;
+ m->s_temp->color = AV_RB24(tsmb);
+ tsmb += 3;
+ m->s_temp->alpha = AV_RB8(tsmb);
+ tsmb++;
av_dynarray_add(&m->s, &m->count_s, m->s_temp);
if(!m->s) {
mov_text_cleanup(m);
return AVERROR(ENOMEM);
}
- tsmb++;
- // text-color-rgba
- tsmb += 4;
}
return 0;
}
int text_pos = 0;
int style_active = 0;
int entry = 0;
+ int color = m->d.color;
if (text < text_end && m->box_flags & TWRP_BOX) {
if (m->w.wrap_flag == 1) {
if (m->s[entry]->style_fontID == m->ftab[i]->fontID)
av_bprintf(buf, "{\\fn%s}", m->ftab[i]->font);
}
+ if (m->d.color != m->s[entry]->color) {
+ color = m->s[entry]->color;
+ av_bprintf(buf, "{\\1c&H%X&}", RGB_TO_BGR(color));
+ }
+ if (m->d.alpha != m->s[entry]->alpha)
+ av_bprintf(buf, "{\\1a&H%02X&}", 255 - m->s[entry]->alpha);
}
if (text_pos == m->s[entry]->style_end) {
if (style_active) {
av_bprintf(buf, "{\\r}");
style_active = 0;
+ color = m->d.color;
}
entry++;
}
}
if (text_pos == m->h.hlit_end) {
if (m->box_flags & HCLR_BOX) {
- av_bprintf(buf, "{\\2c&H000000&}");
+ av_bprintf(buf, "{\\2c&H%X&}", RGB_TO_BGR(m->d.color));
} else {
- av_bprintf(buf, "{\\1c&HFFFFFF&}{\\2c&H000000&}");
+ av_bprintf(buf, "{\\1c&H%X&}{\\2c&H%X&}",
+ RGB_TO_BGR(color), RGB_TO_BGR(m->d.color));
}
}
}
MovTextContext *m = avctx->priv_data;
ret = mov_text_tx3g(avctx, m);
if (ret == 0) {
- return ff_ass_subtitle_header(avctx, m->d.font, m->d.fontsize,
- (255 - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color),
- (255 - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color),
+ if (!m->frame_width || !m->frame_height) {
+ m->frame_width = ASS_DEFAULT_PLAYRESX;
+ m->frame_height = ASS_DEFAULT_PLAYRESY;
+ }
+ return ff_ass_subtitle_header_full(avctx,
+ m->frame_width, m->frame_height,
+ m->d.font, m->d.fontsize,
+ (255U - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color),
+ (255U - m->d.alpha) << 24 | RGB_TO_BGR(m->d.color),
+ (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color),
+ (255U - m->d.back_alpha) << 24 | RGB_TO_BGR(m->d.back_color),
m->d.bold, m->d.italic, m->d.underline,
ASS_DEFAULT_BORDERSTYLE, m->d.alignment);
} else
m->readorder = 0;
}
+#define OFFSET(x) offsetof(MovTextContext, x)
+#define FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM
+static const AVOption options[] = {
+ { "width", "Frame width, usually video width", OFFSET(frame_width), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
+ { "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_decoder_class = {
+ .class_name = "MOV text decoder",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
AVCodec ff_movtext_decoder = {
.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_decoder_class,
.init = mov_text_init,
.decode = mov_text_decode_frame,
.close = mov_text_decode_close,