]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/movtextdec.c
avformat/argo_asf: fix enforcement of chunk count
[ffmpeg] / libavcodec / movtextdec.c
index eb9c7f57557aeccebaf84a804c9f9adf35f8069e..4a21dbf36d4fd86b52d0fb7cd8fd4736ec16a385 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "avcodec.h"
 #include "ass.h"
+#include "libavutil/opt.h"
 #include "libavutil/avstring.h"
 #include "libavutil/common.h"
 #include "libavutil/bprint.h"
@@ -76,6 +77,8 @@ typedef struct {
     uint8_t bold;
     uint8_t italic;
     uint8_t underline;
+    int color;
+    uint8_t alpha;
     uint8_t fontsize;
     uint16_t style_fontID;
 } StyleBox;
@@ -94,6 +97,7 @@ typedef struct {
 } TextWrapBox;
 
 typedef struct {
+    AVClass *class;
     StyleBox **s;
     StyleBox *s_temp;
     HighlightBox h;
@@ -108,6 +112,8 @@ typedef struct {
     int size_var;
     int count_s, count_f;
     int readorder;
+    int frame_width;
+    int frame_height;
 } MovTextContext;
 
 typedef struct {
@@ -329,14 +335,16 @@ static int decode_styl(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt)
         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;
 }
@@ -372,6 +380,7 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
     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) {
@@ -400,11 +409,18 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
                         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++;
             }
@@ -426,9 +442,10 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
             }
             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));
                 }
             }
         }
@@ -468,9 +485,17 @@ static int mov_text_init(AVCodecContext *avctx) {
     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
@@ -588,12 +613,28 @@ static void mov_text_flush(AVCodecContext *avctx)
         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,