avcodec/dump_extradata_bsf: don't allocate a new AVPacket per filtered packet
[ffmpeg.git] / libavcodec / movtextenc.c
index 791132a..c19ef38 100644 (file)
@@ -57,6 +57,8 @@ typedef struct {
 } HilightcolorBox;
 
 typedef struct {
+    AVCodecContext *avctx;
+
     ASSSplitContext *ass_ctx;
     AVBPrint buffer;
     StyleBox **style_attributes;
@@ -70,6 +72,7 @@ typedef struct {
     uint8_t style_fontsize;
     uint32_t style_color;
     uint16_t text_pos;
+    uint16_t byte_count;
 } MovTextContext;
 
 typedef struct {
@@ -187,6 +190,7 @@ static av_cold int mov_text_encode_init(AVCodecContext *avctx)
     };
 
     MovTextContext *s = avctx->priv_data;
+    s->avctx = avctx;
 
     avctx->extradata_size = sizeof text_sample_entry;
     avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
@@ -247,6 +251,9 @@ static void mov_text_style_cb(void *priv, const char style, int close)
             s->style_attributes_temp->style_flag |= STYLE_FLAG_UNDERLINE;
             break;
         }
+    } else if (!s->style_attributes_temp) {
+        av_log(s->avctx, AV_LOG_WARNING, "Ignoring unmatched close tag\n");
+        return;
     } else {
         s->style_attributes_temp->style_end = AV_RB16(&s->text_pos);
         av_dynarray_add(&s->style_attributes, &s->count, s->style_attributes_temp);
@@ -298,11 +305,34 @@ static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color
      */
 }
 
+static uint16_t utf8_strlen(const char *text, int len)
+{
+    uint16_t i = 0, ret = 0;
+    while (i < len) {
+        char c = text[i];
+        if ((c & 0x80) == 0)
+            i += 1;
+        else if ((c & 0xE0) == 0xC0)
+            i += 2;
+        else if ((c & 0xF0) == 0xE0)
+            i += 3;
+        else if ((c & 0xF8) == 0xF0)
+            i += 4;
+        else
+            return 0;
+        ret++;
+    }
+    return ret;
+}
+
 static void mov_text_text_cb(void *priv, const char *text, int len)
 {
+    uint16_t utf8_len = utf8_strlen(text, len);
     MovTextContext *s = priv;
     av_bprint_append_data(&s->buffer, text, len);
-    s->text_pos += len;
+    // If it's not utf-8, just use the byte length
+    s->text_pos += utf8_len ? utf8_len : len;
+    s->byte_count += len;
 }
 
 static void mov_text_new_line_cb(void *priv, int forced)
@@ -310,6 +340,7 @@ static void mov_text_new_line_cb(void *priv, int forced)
     MovTextContext *s = priv;
     av_bprint_append_data(&s->buffer, "\n", 1);
     s->text_pos += 1;
+    s->byte_count += 1;
 }
 
 static const ASSCodesCallbacks mov_text_callbacks = {
@@ -327,6 +358,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
     int i, length;
     size_t j;
 
+    s->byte_count = 0;
     s->text_pos = 0;
     s->count = 0;
     s->box_flags = 0;
@@ -343,10 +375,9 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
         if (!strncmp(ass, "Dialogue: ", 10)) {
             int num;
             dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
-            // TODO reindent
-        for (; dialog && num--; dialog++) {
-            ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
-        }
+            for (; dialog && num--; dialog++) {
+                ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
+            }
         } else {
 #endif
             dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
@@ -363,7 +394,7 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
         }
     }
 
-    AV_WB16(buf, s->text_pos);
+    AV_WB16(buf, s->byte_count);
     buf += 2;
 
     if (!av_bprint_is_complete(&s->buffer)) {