]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/movtextdec.c
avcodec: Constify AVCodecs
[ffmpeg] / libavcodec / movtextdec.c
index 4a21dbf36d4fd86b52d0fb7cd8fd4736ec16a385..873c1350a4b32f240c35fbe0851935540b54fe0b 100644 (file)
@@ -27,6 +27,7 @@
 #include "libavutil/bprint.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
+#include "bytestream.h"
 
 #define STYLE_FLAG_BOLD         (1<<0)
 #define STYLE_FLAG_ITALIC       (1<<1)
@@ -98,19 +99,16 @@ typedef struct {
 
 typedef struct {
     AVClass *class;
-    StyleBox **s;
-    StyleBox *s_temp;
+    StyleBox *s;
     HighlightBox h;
     HilightcolorBox c;
-    FontRecord **ftab;
-    FontRecord *ftab_temp;
+    FontRecord *ftab;
     TextWrapBox w;
     MovTextDefault d;
     uint8_t box_flags;
     uint16_t style_entries, ftab_entries;
     uint64_t tracksize;
     int size_var;
-    int count_s, count_f;
     int readorder;
     int frame_width;
     int frame_height;
@@ -119,55 +117,42 @@ typedef struct {
 typedef struct {
     uint32_t type;
     size_t base_size;
-    int (*decode)(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt);
+    int (*decode)(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt);
 } Box;
 
 static void mov_text_cleanup(MovTextContext *m)
 {
-    int i;
     if (m->box_flags & STYL_BOX) {
-        for(i = 0; i < m->count_s; i++) {
-            av_freep(&m->s[i]);
-        }
         av_freep(&m->s);
-        m->count_s = 0;
         m->style_entries = 0;
     }
 }
 
 static void mov_text_cleanup_ftab(MovTextContext *m)
 {
-    int i;
-    if (m->ftab_temp)
-        av_freep(&m->ftab_temp->font);
-    av_freep(&m->ftab_temp);
-    if (m->ftab) {
-        for(i = 0; i < m->count_f; i++) {
-            av_freep(&m->ftab[i]->font);
-            av_freep(&m->ftab[i]);
-        }
-    }
+    for (unsigned i = 0; i < m->ftab_entries; i++)
+        av_freep(&m->ftab[i].font);
     av_freep(&m->ftab);
+    m->ftab_entries = 0;
 }
 
 static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m)
 {
-    uint8_t *tx3g_ptr = avctx->extradata;
-    int i, box_size, font_length;
+    const uint8_t *tx3g_ptr = avctx->extradata;
+    int i, j = -1, font_length, remaining = avctx->extradata_size - BOX_SIZE_INITIAL;
     int8_t v_align, h_align;
+    unsigned ftab_entries;
     StyleBox s_default;
 
-    m->count_f = 0;
     m->ftab_entries = 0;
-    box_size = BOX_SIZE_INITIAL; /* Size till ftab_entries */
-    if (avctx->extradata_size < box_size)
+    if (remaining < 0)
         return -1;
 
     // Display Flags
     tx3g_ptr += 4;
     // Alignment
-    h_align = *tx3g_ptr++;
-    v_align = *tx3g_ptr++;
+    h_align = bytestream_get_byte(&tx3g_ptr);
+    v_align = bytestream_get_byte(&tx3g_ptr);
     if (h_align == 0) {
         if (v_align == 0)
             m->d.alignment = TOP_LEFT;
@@ -193,158 +178,133 @@ static int mov_text_tx3g(AVCodecContext *avctx, MovTextContext *m)
             m->d.alignment = BOTTOM_RIGHT;
     }
     // Background Color
-    m->d.back_color = AV_RB24(tx3g_ptr);
-    tx3g_ptr += 3;
-    m->d.back_alpha = AV_RB8(tx3g_ptr);
-    tx3g_ptr += 1;
+    m->d.back_color = bytestream_get_be24(&tx3g_ptr);
+    m->d.back_alpha = bytestream_get_byte(&tx3g_ptr);
     // BoxRecord
     tx3g_ptr += 8;
     // StyleRecord
     tx3g_ptr += 4;
     // fontID
-    m->d.fontID = AV_RB16(tx3g_ptr);
-    tx3g_ptr += 2;
+    m->d.fontID = bytestream_get_be16(&tx3g_ptr);
     // face-style-flags
-    s_default.style_flag = *tx3g_ptr++;
+    s_default.style_flag = bytestream_get_byte(&tx3g_ptr);
     m->d.bold = !!(s_default.style_flag & STYLE_FLAG_BOLD);
     m->d.italic = !!(s_default.style_flag & STYLE_FLAG_ITALIC);
     m->d.underline = !!(s_default.style_flag & STYLE_FLAG_UNDERLINE);
     // fontsize
-    m->d.fontsize = *tx3g_ptr++;
+    m->d.fontsize = bytestream_get_byte(&tx3g_ptr);
     // Primary color
-    m->d.color = AV_RB24(tx3g_ptr);
-    tx3g_ptr += 3;
-    m->d.alpha = AV_RB8(tx3g_ptr);
-    tx3g_ptr += 1;
+    m->d.color = bytestream_get_be24(&tx3g_ptr);
+    m->d.alpha = bytestream_get_byte(&tx3g_ptr);
     // FontRecord
     // FontRecord Size
     tx3g_ptr += 4;
     // ftab
     tx3g_ptr += 4;
 
-    m->ftab_entries = AV_RB16(tx3g_ptr);
-    tx3g_ptr += 2;
+    // In case of broken header, init default font
+    m->d.font = ASS_DEFAULT_FONT;
 
-    for (i = 0; i < m->ftab_entries; i++) {
+    ftab_entries = bytestream_get_be16(&tx3g_ptr);
+    if (!ftab_entries)
+        return 0;
+    remaining   -= 3 * ftab_entries;
+    if (remaining < 0)
+        return AVERROR_INVALIDDATA;
+    m->ftab = av_calloc(ftab_entries, sizeof(*m->ftab));
+    if (!m->ftab)
+        return AVERROR(ENOMEM);
+    m->ftab_entries = ftab_entries;
 
-        box_size += 3;
-        if (avctx->extradata_size < box_size) {
-            mov_text_cleanup_ftab(m);
-            m->ftab_entries = 0;
-            return -1;
-        }
-        m->ftab_temp = av_mallocz(sizeof(*m->ftab_temp));
-        if (!m->ftab_temp) {
-            mov_text_cleanup_ftab(m);
-            return AVERROR(ENOMEM);
-        }
-        m->ftab_temp->fontID = AV_RB16(tx3g_ptr);
-        tx3g_ptr += 2;
-        font_length = *tx3g_ptr++;
+    for (i = 0; i < m->ftab_entries; i++) {
+        m->ftab[i].fontID = bytestream_get_be16(&tx3g_ptr);
+        if (m->ftab[i].fontID == m->d.fontID)
+            j = i;
+        font_length = bytestream_get_byte(&tx3g_ptr);
 
-        box_size = box_size + font_length;
-        if (avctx->extradata_size < box_size) {
+        remaining  -= font_length;
+        if (remaining < 0) {
             mov_text_cleanup_ftab(m);
-            m->ftab_entries = 0;
             return -1;
         }
-        m->ftab_temp->font = av_malloc(font_length + 1);
-        if (!m->ftab_temp->font) {
+        m->ftab[i].font = av_malloc(font_length + 1);
+        if (!m->ftab[i].font) {
             mov_text_cleanup_ftab(m);
             return AVERROR(ENOMEM);
         }
-        memcpy(m->ftab_temp->font, tx3g_ptr, font_length);
-        m->ftab_temp->font[font_length] = '\0';
-        av_dynarray_add(&m->ftab, &m->count_f, m->ftab_temp);
-        if (!m->ftab) {
-            mov_text_cleanup_ftab(m);
-            return AVERROR(ENOMEM);
-        }
-        m->ftab_temp = NULL;
-        tx3g_ptr = tx3g_ptr + font_length;
-    }
-    // In case of broken header, init default font
-    m->d.font = ASS_DEFAULT_FONT;
-    for (i = 0; i < m->ftab_entries; i++) {
-        if (m->d.fontID == m->ftab[i]->fontID)
-            m->d.font = m->ftab[i]->font;
+        bytestream_get_buffer(&tx3g_ptr, m->ftab[i].font, font_length);
+        m->ftab[i].font[font_length] = '\0';
     }
+    if (j >= 0)
+        m->d.font = m->ftab[j].font;
     return 0;
 }
 
-static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt)
+static int decode_twrp(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt)
 {
     m->box_flags |= TWRP_BOX;
-    m->w.wrap_flag = *tsmb++;
+    m->w.wrap_flag = bytestream_get_byte(&tsmb);
     return 0;
 }
 
-static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt)
+static int decode_hlit(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt)
 {
     m->box_flags |= HLIT_BOX;
-    m->h.hlit_start = AV_RB16(tsmb);
-    tsmb += 2;
-    m->h.hlit_end = AV_RB16(tsmb);
-    tsmb += 2;
+    m->h.hlit_start = bytestream_get_be16(&tsmb);
+    m->h.hlit_end   = bytestream_get_be16(&tsmb);
     return 0;
 }
 
-static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt)
+static int decode_hclr(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt)
 {
     m->box_flags |= HCLR_BOX;
-    memcpy(m->c.hlit_color, tsmb, 4);
-    tsmb += 4;
+    bytestream_get_buffer(&tsmb, m->c.hlit_color, 4);
     return 0;
 }
 
-static int decode_styl(const uint8_t *tsmb, MovTextContext *m, AVPacket *avpkt)
+static int decode_styl(const uint8_t *tsmb, MovTextContext *m, const AVPacket *avpkt)
 {
     int i;
-    int style_entries = AV_RB16(tsmb);
-    tsmb += 2;
+    int style_entries = bytestream_get_be16(&tsmb);
+    StyleBox *tmp;
+
     // A single style record is of length 12 bytes.
     if (m->tracksize + m->size_var + 2 + style_entries * 12 > avpkt->size)
         return -1;
 
+    tmp = av_realloc_array(m->s, style_entries, sizeof(*m->s));
+    if (!tmp)
+        return AVERROR(ENOMEM);
+    m->s             = tmp;
     m->style_entries = style_entries;
 
     m->box_flags |= STYL_BOX;
     for(i = 0; i < m->style_entries; i++) {
-        m->s_temp = av_malloc(sizeof(*m->s_temp));
-        if (!m->s_temp) {
-            mov_text_cleanup(m);
-            return AVERROR(ENOMEM);
-        }
-        m->s_temp->style_start = AV_RB16(tsmb);
-        tsmb += 2;
-        m->s_temp->style_end = AV_RB16(tsmb);
+        StyleBox *style = &m->s[i];
 
-        if (   m->s_temp->style_end < m->s_temp->style_start
-            || (m->count_s && m->s_temp->style_start < m->s[m->count_s - 1]->style_end)) {
-            av_freep(&m->s_temp);
+        style->style_start = bytestream_get_be16(&tsmb);
+        style->style_end   = bytestream_get_be16(&tsmb);
+        if (   style->style_end < style->style_start
+            || (i && style->style_start < m->s[i - 1].style_end)) {
             mov_text_cleanup(m);
             return AVERROR(ENOMEM);
         }
-
-        tsmb += 2;
-        m->s_temp->style_fontID = AV_RB16(tsmb);
-        tsmb += 2;
-        m->s_temp->style_flag = AV_RB8(tsmb);
-        m->s_temp->bold = !!(m->s_temp->style_flag & STYLE_FLAG_BOLD);
-        m->s_temp->italic = !!(m->s_temp->style_flag & STYLE_FLAG_ITALIC);
-        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);
+        if (style->style_start == style->style_end) {
+            /* Skip this style as it applies to no character */
+            tsmb += 8;
+            m->style_entries--;
+            i--;
+            continue;
         }
+
+        style->style_fontID = bytestream_get_be16(&tsmb);
+        style->style_flag   = bytestream_get_byte(&tsmb);
+        style->bold      = !!(style->style_flag & STYLE_FLAG_BOLD);
+        style->italic    = !!(style->style_flag & STYLE_FLAG_ITALIC);
+        style->underline = !!(style->style_flag & STYLE_FLAG_UNDERLINE);
+        style->fontsize  = bytestream_get_byte(&tsmb);
+        style->color     = bytestream_get_be24(&tsmb);
+        style->alpha     = bytestream_get_byte(&tsmb);
     }
     return 0;
 }
@@ -378,7 +338,6 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
     MovTextContext *m = avctx->priv_data;
     int i = 0;
     int text_pos = 0;
-    int style_active = 0;
     int entry = 0;
     int color = m->d.color;
 
@@ -394,35 +353,33 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
         int len;
 
         if ((m->box_flags & STYL_BOX) && entry < m->style_entries) {
-            if (text_pos == m->s[entry]->style_start) {
-                style_active = 1;
-                if (m->s[entry]->bold ^ m->d.bold)
-                    av_bprintf(buf, "{\\b%d}", m->s[entry]->bold);
-                if (m->s[entry]->italic ^ m->d.italic)
-                    av_bprintf(buf, "{\\i%d}", m->s[entry]->italic);
-                if (m->s[entry]->underline ^ m->d.underline)
-                    av_bprintf(buf, "{\\u%d}", m->s[entry]->underline);
-                if (m->s[entry]->fontsize != m->d.fontsize)
-                    av_bprintf(buf, "{\\fs%d}", m->s[entry]->fontsize);
-                if (m->s[entry]->style_fontID != m->d.fontID)
+            const StyleBox *style = &m->s[entry];
+            if (text_pos == style->style_end) {
+                av_bprintf(buf, "{\\r}");
+                color = m->d.color;
+                entry++;
+                style++;
+            }
+            if (entry < m->style_entries && text_pos == style->style_start) {
+                if (style->bold ^ m->d.bold)
+                    av_bprintf(buf, "{\\b%d}", style->bold);
+                if (style->italic ^ m->d.italic)
+                    av_bprintf(buf, "{\\i%d}", style->italic);
+                if (style->underline ^ m->d.underline)
+                    av_bprintf(buf, "{\\u%d}", style->underline);
+                if (style->fontsize != m->d.fontsize)
+                    av_bprintf(buf, "{\\fs%d}", style->fontsize);
+                if (style->style_fontID != m->d.fontID)
                     for (i = 0; i < m->ftab_entries; i++) {
-                        if (m->s[entry]->style_fontID == m->ftab[i]->fontID)
-                            av_bprintf(buf, "{\\fn%s}", m->ftab[i]->font);
+                        if (style->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;
+                if (m->d.color != style->color) {
+                    color = style->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 (m->d.alpha != style->alpha)
+                    av_bprintf(buf, "{\\1a&H%02X&}", 255 - style->alpha);
             }
         }
         if (m->box_flags & HLIT_BOX) {
@@ -455,19 +412,17 @@ static int text_to_ass(AVBPrint *buf, const char *text, const char *text_end,
             av_log(avctx, AV_LOG_ERROR, "invalid UTF-8 byte in subtitle\n");
             len = 1;
         }
-        for (i = 0; i < len; i++) {
-            switch (*text) {
-            case '\r':
-                break;
-            case '\n':
-                av_bprintf(buf, "\\N");
-                break;
-            default:
-                av_bprint_chars(buf, *text, 1);
-                break;
-            }
-            text++;
+        switch (*text) {
+        case '\r':
+            break;
+        case '\n':
+            av_bprintf(buf, "\\N");
+            break;
+        default:
+            av_bprint_append_data(buf, text, len);
+            break;
         }
+        text += len;
         text_pos++;
     }
 
@@ -544,7 +499,6 @@ static int mov_text_decode_frame(AVCodecContext *avctx,
     m->tracksize = 2 + text_length;
     m->style_entries = 0;
     m->box_flags = 0;
-    m->count_s = 0;
     // Note that the spec recommends lines be no longer than 2048 characters.
     av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED);
     if (text_length + 2 != avpkt->size) {
@@ -628,7 +582,7 @@ static const AVClass mov_text_decoder_class = {
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
-AVCodec ff_movtext_decoder = {
+const AVCodec ff_movtext_decoder = {
     .name         = "mov_text",
     .long_name    = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
     .type         = AVMEDIA_TYPE_SUBTITLE,