[FFmpeg-trac] #6021(avcodec:new): tx3g / mov_text subtitles are not encoded correctly in some specific cases

FFmpeg trac at avcodec.org
Thu Dec 15 05:56:33 EET 2016


#6021: tx3g / mov_text subtitles are not encoded correctly in some specific cases
-------------------------------------+-------------------------------------
             Reporter:  erikbs       |                    Owner:
                 Type:  defect       |                   Status:  new
             Priority:  normal       |                Component:  avcodec
              Version:  git-master   |               Resolution:
             Keywords:  utf8         |               Blocked By:
  mov_text ttxt tx3g subtitles mp4   |  Reproduced by developer:  0
             Blocking:               |
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------

Comment (by erikbs):

 Okay, so I took a closer look at the [https://gpac.wp.mines-
 telecom.fr/mp4box/ttxt-format-documentation/ TTXT format documenation],
 and it clearly states that text lengths are counted in characters (not
 bytes). (Note that this document only touches the XML form. In binary
 form, the length of the different blocks (text, style etc.) appear to be
 counted in bytes.)

 I also played around with the code, and think I have found a solution:
 1. In the MovTextContext struct, introduce a new member variable for the
 text position as characters (without replacing the existing text_pos,
 which is measured in bytes and needed for storing the length of the
 blocks)
 2. Increase the new variable by counting UTF8 characters instead of bytes
 (according to the format documentation, only UTF8 is supported anyway). A
 simple for+if will do (loop through all bytes and only count those where
 the two most significant bits are not 10)
 3. Replace all instances of text_pos with the new variable in code
 regarding style.

 My modified code produces files that play correctly in QuickTime and
 contain subtitle streams equivalent to what MP4Box produces (MP4Box also
 sets height/width, ffmpeg does not, but this does not seem to matter). I
 have tested it on subtitles with nested styles too. My modifications may
 not be the prettiest, but the code works as far as I can see. I have not
 touched movtextdec.c, so when extracting TTXT subtitles from an MP4,
 ffmpeg generates SRT files with misplaced style tags.

 For movtextenc.c I have created a patch. Any help with submitting it is
 highly appreciated. Me + git = disaster, and I do not even know if it is
 in the correct format (I used {{{diff -u file1 file2}}}):

 {{{
 --- movtextenc.c        2016-02-26 21:15:02.000000000 +0000
 +++ movtextenc.c        2016-12-15 02:29:03.000000000 +0000
 @@ -70,6 +70,7 @@
      uint8_t style_fontsize;
      uint32_t style_color;
      uint16_t text_pos;
 +    uint16_t text_pos_char;
  } MovTextContext;

  typedef struct {
 @@ -216,10 +217,10 @@
              }

              s->style_attributes_temp->style_flag = 0;
 -            s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos);
 +            s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos_char);
          } else {
              if (s->style_attributes_temp->style_flag) { //break the style
 record here and start a new one
 -                s->style_attributes_temp->style_end =
 AV_RB16(&s->text_pos);
 +                s->style_attributes_temp->style_end =
 AV_RB16(&s->text_pos_char);
                  av_dynarray_add(&s->style_attributes, &s->count,
 s->style_attributes_temp);
                  s->style_attributes_temp =
 av_malloc(sizeof(*s->style_attributes_temp));
                  if (!s->style_attributes_temp) {
 @@ -230,10 +231,10 @@
                  }

                  s->style_attributes_temp->style_flag =
 s->style_attributes[s->count - 1]->style_flag;
 -                s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos);
 +                s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos_char);
              } else {
                  s->style_attributes_temp->style_flag = 0;
 -                s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos);
 +                s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos_char);
              }
          }
          switch (style){
 @@ -248,7 +249,7 @@
              break;
          }
      } else {
 -        s->style_attributes_temp->style_end = AV_RB16(&s->text_pos);
 +        s->style_attributes_temp->style_end = AV_RB16(&s->text_pos_char);
          av_dynarray_add(&s->style_attributes, &s->count,
 s->style_attributes_temp);

          s->style_attributes_temp =
 av_malloc(sizeof(*s->style_attributes_temp));
 @@ -273,7 +274,7 @@
              break;
          }
          if (s->style_attributes_temp->style_flag) { //start of new style
 record
 -            s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos);
 +            s->style_attributes_temp->style_start =
 AV_RB16(&s->text_pos_char);
          }
      }
      s->box_flags |= STYL_BOX;
 @@ -284,11 +285,11 @@
      MovTextContext *s = priv;
      if (color_id == 2) {    //secondary color changes
          if (s->box_flags & HLIT_BOX) {  //close tag
 -            s->hlit.end = AV_RB16(&s->text_pos);
 +            s->hlit.end = AV_RB16(&s->text_pos_char);
          } else {
              s->box_flags |= HCLR_BOX;
              s->box_flags |= HLIT_BOX;
 -            s->hlit.start = AV_RB16(&s->text_pos);
 +            s->hlit.start = AV_RB16(&s->text_pos_char);
              s->hclr.color = color | (0xFF << 24);  //set alpha value to
 FF
          }
      }
 @@ -302,7 +303,10 @@
  {
      MovTextContext *s = priv;
      av_bprint_append_data(&s->buffer, text, len);
 -    s->text_pos += len;
 +    s->text_pos += len; // length of text in bytes
 +    for (int i = 0; i < len; i++) // length of text in characters
 +        if ((text[i] & 0xC0) != 0x80)
 +            s->text_pos_char ++;
  }

  static void mov_text_new_line_cb(void *priv, int forced)
 @@ -310,6 +314,7 @@
      MovTextContext *s = priv;
      av_bprint_append_data(&s->buffer, "\n", 1);
      s->text_pos += 1;
 +    s->text_pos_char += 1;
  }

  static const ASSCodesCallbacks mov_text_callbacks = {
 @@ -328,6 +333,7 @@
      size_t j;

      s->text_pos = 0;
 +    s->text_pos_char = 0;
      s->count = 0;
      s->box_flags = 0;
      s->style_entries = 0;

 }}}

--
Ticket URL: <https://trac.ffmpeg.org/ticket/6021#comment:2>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list