[MPlayer-dev-eng] [PATCH] Style tag support for srt and microdvd subtitles
ubitux
ubitux at gmail.com
Sat May 15 15:36:03 CEST 2010
Hi,
Here is a more complete patch which now also supports MicroDVD subtitles.
So now, with -ass you can get basic tags working for MicroDVD and SubRip
subtitles (bold/italic/underline/strike-through).
Since last time, I've a bit modified the SubRip conversion support:
- Function name
- Overflow check (again)
- Let the old filter html tags if there is ones left
About the MicroDVD support, I've commented it a bit since the code is a
bit larger. As I say it supports basic tagging, but also tag persistence.
Next step is colors/size support, but I think this is a first patch that
can be safetly applied.
Can you make a review of this stuff?
Regards,
--
ubitux
-------------- next part --------------
Index: subreader.c
===================================================================
--- subreader.c (revision 31179)
+++ subreader.c (working copy)
@@ -36,6 +36,8 @@
#include "libavutil/common.h"
#include "libavutil/avstring.h"
+#include "libass/ass_mp.h"
+
#ifdef CONFIG_ENCA
#include <enca.h>
#endif
@@ -251,7 +253,96 @@
return current;
}
+static int indexof(const char *s, int c)
+{
+ char *f = strchr(s, c);
+ return (f) ? (f - s) : -1;
+}
+
+#define MICRODVD_ALLOWED_STYLES "ibus" /* italic, bold, underline, strike-through */
+#define MICRODVD_DEFAULT_STYLES "...." /* no styles */
+#define MICRODVD_TAG_DISABLED '.'
+
+static void subconvert_microdvd_to_ass(char *line)
+{
+ char new_line[LINE_LEN + 1];
+ int i = 0, j = 0;
+ char ass_otag[] = "{\\.1}"; /* ASS/SSA opening tag */
+ char ass_ctag[] = "{\\.0}"; /* ASS/SSA closing tag */
+ char tags_to_close[] = MICRODVD_DEFAULT_STYLES;
+
+ while (line[i] && j < sizeof(new_line) - 1) {
+
+ /* End of line */
+ if (line[i] == '|') {
+ int n;
+
+ /* close non-persistent style tags */
+ for (n = sizeof(tags_to_close) - 2; n >= 0; n--) {
+ if (tags_to_close[n] != MICRODVD_TAG_DISABLED) {
+ if (j + sizeof(ass_ctag) < sizeof(new_line) - 1) {
+ ass_ctag[2] = tags_to_close[n];
+ strcpy(&new_line[j], ass_ctag);
+ j += sizeof(ass_ctag) - 1;
+ }
+ tags_to_close[n] = MICRODVD_TAG_DISABLED;
+ }
+ }
+
+ /* ASS/SSA end of line */
+ if (j + 2 < sizeof(new_line) - 1) {
+ strcpy(&new_line[j], "\\N");
+ j += 2;
+ }
+
+ i++;
+ continue;
+ }
+
+ /* Opening style tags */
+ if (strncasecmp(&line[i], "{y:", 3) == 0) {
+ int n, persistent = (line[i + 1] == 'Y');
+ char tags_to_open[] = MICRODVD_DEFAULT_STYLES;
+
+ i += 3;
+
+ /* Reference style tags to open */
+ while (line[i] && line[i] != '}') {
+ int tag_index = indexof(MICRODVD_ALLOWED_STYLES, line[i]);
+
+ if (tag_index >= 0)
+ tags_to_open[tag_index] = line[i];
+ i++;
+ }
+
+ if (!line[i])
+ break;
+
+ /* Open them in order to close them the exact opposite way they are opened */
+ for (n = 0; tags_to_open[n]; n++) {
+ if (tags_to_open[n] != MICRODVD_TAG_DISABLED &&
+ j + sizeof(ass_otag) < sizeof(new_line) - 1) {
+ ass_otag[2] = tags_to_open[n];
+ strcpy(&new_line[j], ass_otag);
+ j += sizeof(ass_otag) - 1;
+ if (!persistent)
+ tags_to_close[n] = tags_to_open[n];
+ }
+ }
+
+ i++;
+ continue;
+ }
+
+ /* Part of the text */
+ new_line[j++] = line[i++];
+ }
+
+ new_line[j] = 0;
+ strcpy(line, new_line);
+}
+
static char *sub_readtext(char *source, char **dest) {
int len=0;
char *p=source;
@@ -291,6 +382,9 @@
p=line2;
+ if (ass_enabled)
+ subconvert_microdvd_to_ass(p);
+
next=p, i=0;
while ((next =sub_readtext (next, &(current->text[i])))) {
if (current->text[i]==ERR) {return ERR;}
@@ -358,6 +452,42 @@
return current;
}
+static const struct {
+ char *from;
+ char *to;
+} subviewer_to_ass[] = {
+ {"<i>", "{\\i1}"}, {"</i>", "{\\i0}"},
+ {"<b>", "{\\b1}"}, {"</b>", "{\\b0}"},
+ {"<u>", "{\\u1}"}, {"</u>", "{\\u0}"},
+ {"<s>", "{\\s1}"}, {"</s>", "{\\s0}"}
+};
+
+static void subconvert_subviewer_to_ass(char *line)
+{
+ char new_line[LINE_LEN + 1];
+ int i = 0, j = 0;
+
+ while (line[i] && j < sizeof(new_line) - 1) {
+ int n, match = 0;
+
+ for (n = 0; n < (int)(sizeof(subviewer_to_ass) / sizeof(*subviewer_to_ass)); n++) {
+ int from_len = strlen(subviewer_to_ass[n].from);
+
+ if (strncmp(&line[i], subviewer_to_ass[n].from, from_len) == 0) {
+ strcpy(&new_line[j], subviewer_to_ass[n].to);
+ i += from_len;
+ j += strlen(subviewer_to_ass[n].to);
+ match = 1;
+ break;
+ }
+ }
+ if (!match)
+ new_line[j++] = line[i++];
+ }
+ new_line[j] = 0;
+ strcpy(line, new_line);
+}
+
static subtitle *sub_read_line_subviewer(stream_t *st,subtitle *current, int utf16) {
char line[LINE_LEN+1];
int a1,a2,a3,a4,b1,b2,b3,b4;
@@ -373,6 +503,10 @@
for (i=0; i<SUB_MAX_TEXT;) {
int blank = 1;
if (!stream_read_line (st, line, LINE_LEN, utf16)) break;
+
+ if (ass_enabled)
+ subconvert_subviewer_to_ass(line);
+
len=0;
for (p=line; *p!='\n' && *p!='\r' && *p; p++,len++)
if (*p != ' ' && *p != '\t')
More information about the MPlayer-dev-eng
mailing list