diff options
Diffstat (limited to 'ffmpeg1/libavcodec/microdvddec.c')
| -rw-r--r-- | ffmpeg1/libavcodec/microdvddec.c | 377 |
1 files changed, 0 insertions, 377 deletions
diff --git a/ffmpeg1/libavcodec/microdvddec.c b/ffmpeg1/libavcodec/microdvddec.c deleted file mode 100644 index f3c640f..0000000 --- a/ffmpeg1/libavcodec/microdvddec.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (c) 2012 Clément Bœsch - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file - * MicroDVD subtitle decoder - * - * Based on the specifications found here: - * https://trac.videolan.org/vlc/ticket/1825#comment:6 - */ - -#include "libavutil/avstring.h" -#include "libavutil/parseutils.h" -#include "libavutil/bprint.h" -#include "avcodec.h" -#include "ass.h" - -static int indexof(const char *s, int c) -{ - char *f = strchr(s, c); - return f ? (f - s) : -1; -} - -struct microdvd_tag { - char key; - int persistent; - uint32_t data1; - uint32_t data2; - char *data_string; - int data_string_len; -}; - -#define MICRODVD_PERSISTENT_OFF 0 -#define MICRODVD_PERSISTENT_ON 1 -#define MICRODVD_PERSISTENT_OPENED 2 - -// Color, Font, Size, cHarset, stYle, Position, cOordinate -#define MICRODVD_TAGS "cfshyYpo" - -static void microdvd_set_tag(struct microdvd_tag *tags, struct microdvd_tag tag) -{ - int tag_index = indexof(MICRODVD_TAGS, tag.key); - - if (tag_index < 0) - return; - memcpy(&tags[tag_index], &tag, sizeof(tag)); -} - -// italic, bold, underline, strike-through -#define MICRODVD_STYLES "ibus" - -static char *microdvd_load_tags(struct microdvd_tag *tags, char *s) -{ - while (*s == '{') { - char *start = s; - char tag_char = *(s + 1); - struct microdvd_tag tag = {0}; - - if (!tag_char || *(s + 2) != ':') - break; - s += 3; - - switch (tag_char) { - - /* Style */ - case 'Y': - tag.persistent = MICRODVD_PERSISTENT_ON; - case 'y': - while (*s && *s != '}') { - int style_index = indexof(MICRODVD_STYLES, *s); - - if (style_index >= 0) - tag.data1 |= (1 << style_index); - s++; - } - if (*s != '}') - break; - /* We must distinguish persistent and non-persistent styles - * to handle this kind of style tags: {y:ib}{Y:us} */ - tag.key = tag_char; - break; - - /* Color */ - case 'C': - tag.persistent = MICRODVD_PERSISTENT_ON; - case 'c': - if (*s == '$') - s++; - tag.data1 = strtol(s, &s, 16) & 0x00ffffff; - if (*s != '}') - break; - tag.key = 'c'; - break; - - /* Font name */ - case 'F': - tag.persistent = MICRODVD_PERSISTENT_ON; - case 'f': { - int len = indexof(s, '}'); - if (len < 0) - break; - tag.data_string = s; - tag.data_string_len = len; - s += len; - tag.key = 'f'; - break; - } - - /* Font size */ - case 'S': - tag.persistent = MICRODVD_PERSISTENT_ON; - case 's': - tag.data1 = strtol(s, &s, 10); - if (*s != '}') - break; - tag.key = 's'; - break; - - /* Charset */ - case 'H': { - //TODO: not yet handled, just parsed. - int len = indexof(s, '}'); - if (len < 0) - break; - tag.data_string = s; - tag.data_string_len = len; - s += len; - tag.key = 'h'; - break; - } - - /* Position */ - case 'P': - tag.persistent = MICRODVD_PERSISTENT_ON; - tag.data1 = (*s++ == '1'); - if (*s != '}') - break; - tag.key = 'p'; - break; - - /* Coordinates */ - case 'o': - tag.persistent = MICRODVD_PERSISTENT_ON; - tag.data1 = strtol(s, &s, 10); - if (*s != ',') - break; - s++; - tag.data2 = strtol(s, &s, 10); - if (*s != '}') - break; - tag.key = 'o'; - break; - - default: /* Unknown tag, we consider it's text */ - break; - } - - if (tag.key == 0) - return start; - - microdvd_set_tag(tags, tag); - s++; - } - return s; -} - -static void microdvd_open_tags(AVBPrint *new_line, struct microdvd_tag *tags) -{ - int i, sidx; - for (i = 0; i < sizeof(MICRODVD_TAGS) - 1; i++) { - if (tags[i].persistent == MICRODVD_PERSISTENT_OPENED) - continue; - switch (tags[i].key) { - case 'Y': - case 'y': - for (sidx = 0; sidx < sizeof(MICRODVD_STYLES) - 1; sidx++) - if (tags[i].data1 & (1 << sidx)) - av_bprintf(new_line, "{\\%c1}", MICRODVD_STYLES[sidx]); - break; - - case 'c': - av_bprintf(new_line, "{\\c&H%06X&}", tags[i].data1); - break; - - case 'f': - av_bprintf(new_line, "{\\fn%.*s}", - tags[i].data_string_len, tags[i].data_string); - break; - - case 's': - av_bprintf(new_line, "{\\fs%d}", tags[i].data1); - break; - - case 'p': - if (tags[i].data1 == 0) - av_bprintf(new_line, "{\\an8}"); - break; - - case 'o': - av_bprintf(new_line, "{\\pos(%d,%d)}", - tags[i].data1, tags[i].data2); - break; - } - if (tags[i].persistent == MICRODVD_PERSISTENT_ON) - tags[i].persistent = MICRODVD_PERSISTENT_OPENED; - } -} - -static void microdvd_close_no_persistent_tags(AVBPrint *new_line, - struct microdvd_tag *tags) -{ - int i, sidx; - - for (i = sizeof(MICRODVD_TAGS) - 2; i >= 0; i--) { - if (tags[i].persistent != MICRODVD_PERSISTENT_OFF) - continue; - switch (tags[i].key) { - - case 'y': - for (sidx = sizeof(MICRODVD_STYLES) - 2; sidx >= 0; sidx--) - if (tags[i].data1 & (1 << sidx)) - av_bprintf(new_line, "{\\%c0}", MICRODVD_STYLES[sidx]); - break; - - case 'c': - av_bprintf(new_line, "{\\c}"); - break; - - case 'f': - av_bprintf(new_line, "{\\fn}"); - break; - - case 's': - av_bprintf(new_line, "{\\fs}"); - break; - } - tags[i].key = 0; - } -} - -static int microdvd_decode_frame(AVCodecContext *avctx, - void *data, int *got_sub_ptr, AVPacket *avpkt) -{ - AVSubtitle *sub = data; - AVBPrint new_line; - char c; - char *decoded_sub; - char *line = avpkt->data; - char *end = avpkt->data + avpkt->size; - struct microdvd_tag tags[sizeof(MICRODVD_TAGS) - 1] = {{0}}; - - if (avpkt->size <= 0) - return avpkt->size; - - /* To be removed later */ - if (sscanf(line, "{%*d}{%*[0123456789]}%c", &c) == 1 && - line[avpkt->size - 1] == '\n') { - av_log(avctx, AV_LOG_ERROR, "AVPacket is not clean (contains timing " - "information and a trailing line break). You need to upgrade " - "your libavformat or sanitize your packet.\n"); - return AVERROR_INVALIDDATA; - } - - av_bprint_init(&new_line, 0, 2048); - - // subtitle content - while (line < end && *line) { - - // parse MicroDVD tags, and open them in ASS - line = microdvd_load_tags(tags, line); - microdvd_open_tags(&new_line, tags); - - // simple copy until EOL or forced carriage return - while (line < end && *line && *line != '|') { - av_bprint_chars(&new_line, *line, 1); - line++; - } - - // line split - if (line < end && *line == '|') { - microdvd_close_no_persistent_tags(&new_line, tags); - av_bprintf(&new_line, "\\N"); - line++; - } - } - if (new_line.len) { - av_bprintf(&new_line, "\r\n"); - - av_bprint_finalize(&new_line, &decoded_sub); - 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 = AV_CODEC_ID_MICRODVD, - .init = microdvd_init, - .decode = microdvd_decode_frame, -}; |
