]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/microdvddec.c
Fix typo in v410 decoder.
[ffmpeg] / libavcodec / microdvddec.c
index 083efdb94f896395a53d36bd90a340d27ba87a1f..27645cccb1977e1b5b6fb465b005da4bd9d2f489 100644 (file)
@@ -101,6 +101,8 @@ static char *microdvd_load_tags(struct microdvd_tag *tags, char *s)
         case 'C':
             tag.persistent = MICRODVD_PERSISTENT_ON;
         case 'c':
+            if (*s == '$')
+                s++;
             tag.data1 = strtol(s, &s, 16) & 0x00ffffff;
             if (*s != '}')
                 break;
@@ -226,7 +228,7 @@ static void microdvd_close_no_persistent_tags(AVBPrint *new_line,
 {
     int i, sidx;
 
-    for (i = sizeof(MICRODVD_TAGS) - 2; i; i--) {
+    for (i = sizeof(MICRODVD_TAGS) - 2; i >= 0; i--) {
         if (tags[i].persistent != MICRODVD_PERSISTENT_OFF)
             continue;
         switch (tags[i].key) {
@@ -261,10 +263,6 @@ static int microdvd_decode_frame(AVCodecContext *avctx,
     char *decoded_sub;
     char *line = avpkt->data;
     char *end = avpkt->data + avpkt->size;
-    int64_t frame_start = avpkt->pts;
-    int64_t frame_end   = avpkt->pts + avpkt->duration;
-    int ts_start = av_rescale_q(frame_start, avctx->time_base, (AVRational){1,100});
-    int ts_end   = av_rescale_q(frame_end,   avctx->time_base, (AVRational){1,100});
     struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}};
 
     if (avpkt->size <= 0)
@@ -299,19 +297,73 @@ static int microdvd_decode_frame(AVCodecContext *avctx,
 
 end:
     av_bprint_finalize(&new_line, &decoded_sub);
-    if (*decoded_sub)
-        ff_ass_add_rect(sub, decoded_sub, ts_start, ts_end, 0);
+    if (*decoded_sub) {
+        int64_t start    = avpkt->pts;
+        int64_t duration = avpkt->duration;
+        int ts_start     = av_rescale_q(start,    avctx->time_base, (AVRational){1,100});
+        int ts_duration  = duration != -1 ?
+                           av_rescale_q(duration, avctx->time_base, (AVRational){1,100}) : -1;
+        ff_ass_add_rect(sub, decoded_sub, ts_start, ts_duration, 0);
+    }
     av_free(decoded_sub);
 
     *got_sub_ptr = sub->num_rects > 0;
     return avpkt->size;
 }
 
+static int microdvd_init(AVCodecContext *avctx)
+{
+    int i, sidx;
+    AVBPrint font_buf;
+    int font_size    = ASS_DEFAULT_FONT_SIZE;
+    int color        = ASS_DEFAULT_COLOR;
+    int bold         = ASS_DEFAULT_BOLD;
+    int italic       = ASS_DEFAULT_ITALIC;
+    int underline    = ASS_DEFAULT_UNDERLINE;
+    int alignment    = ASS_DEFAULT_ALIGNMENT;
+    struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}};
+
+    av_bprint_init(&font_buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
+    av_bprintf(&font_buf, "%s", ASS_DEFAULT_FONT);
+
+    if (avctx->extradata) {
+        microdvd_load_tags(tags, avctx->extradata);
+        for (i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) {
+            switch (av_tolower(tags[i].key)) {
+            case 'y':
+                for (sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++) {
+                    if (tags[i].data1 & (1 << sidx)) {
+                        switch (MICRODVD_STYLES[sidx]) {
+                        case 'i': italic    = 1; break;
+                        case 'b': bold      = 1; break;
+                        case 'u': underline = 1; break;
+                        }
+                    }
+                }
+                break;
+
+            case 'c': color     = tags[i].data1; break;
+            case 's': font_size = tags[i].data1; break;
+            case 'p': alignment =             8; break;
+
+            case 'f':
+                av_bprint_clear(&font_buf);
+                av_bprintf(&font_buf, "%.*s",
+                           tags[i].data_string_len, tags[i].data_string);
+                break;
+            }
+        }
+    }
+    return ff_ass_subtitle_header(avctx, font_buf.str, font_size, color,
+                                  ASS_DEFAULT_BACK_COLOR, bold, italic,
+                                  underline, alignment);
+}
+
 AVCodec ff_microdvd_decoder = {
     .name         = "microdvd",
     .long_name    = NULL_IF_CONFIG_SMALL("MicroDVD subtitle"),
     .type         = AVMEDIA_TYPE_SUBTITLE,
     .id           = CODEC_ID_MICRODVD,
-    .init         = ff_ass_subtitle_header_default,
+    .init         = microdvd_init,
     .decode       = microdvd_decode_frame,
 };