]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/movtextenc.c
avformat/mux: factorize interleaved write_packet
[ffmpeg] / libavcodec / movtextenc.c
index a109483a6a19f6f25e504b40c09fbb541adc8b7f..b2368b641bb7751bc3506ca22182ca6094881544 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <stdarg.h>
 #include "avcodec.h"
+#include "libavutil/opt.h"
 #include "libavutil/avassert.h"
 #include "libavutil/avstring.h"
 #include "libavutil/intreadwrite.h"
@@ -45,6 +46,7 @@
 #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 {
@@ -66,6 +68,7 @@ typedef struct {
 } HilightcolorBox;
 
 typedef struct {
+    AVClass *class;
     AVCodecContext *avctx;
 
     ASSSplitContext *ass_ctx;
@@ -82,6 +85,8 @@ typedef struct {
     uint16_t byte_count;
     char ** fonts;
     int font_count;
+    double font_scale_factor;
+    int frame_height;
 } MovTextContext;
 
 typedef struct {
@@ -237,6 +242,13 @@ static int encode_sample_description(AVCodecContext *avctx)
 
     // 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];
@@ -246,7 +258,7 @@ static int encode_sample_description(AVCodecContext *avctx)
     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)   |
@@ -467,19 +479,23 @@ static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color
     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)
@@ -498,8 +514,23 @@ static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id)
 {
     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)
@@ -531,6 +562,7 @@ static void mov_text_font_name_cb(void *priv, 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
@@ -661,7 +693,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
 
         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
@@ -704,7 +736,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
 
     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;
     }
 
@@ -716,12 +748,27 @@ 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,