diff options
Diffstat (limited to 'appl/wm/mpeg/vlc.b')
| -rw-r--r-- | appl/wm/mpeg/vlc.b | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/appl/wm/mpeg/vlc.b b/appl/wm/mpeg/vlc.b new file mode 100644 index 00000000..96e136e9 --- /dev/null +++ b/appl/wm/mpeg/vlc.b @@ -0,0 +1,213 @@ +implement Vlc; + +include "sys.m"; +include "draw.m"; +include "bufio.m"; + +# +# Construct expanded Vlc (variable length code) tables +# from vlc description files. +# + +sys: Sys; +bufio: Bufio; +Iobuf: import bufio; + +stderr: ref Sys->FD; + +sv: adt +{ + s: int; + v: string; +}; + +s2list: type list of (string, string); +bits, size: int; +table: array of sv; +prog: string; +undef: string = "UNDEF"; +xfixed: int = 0; +complete: int = 0; +paren: int = 0; + +Vlc: module +{ + init: fn(nil: ref Draw->Context, args: list of string); +}; + +init(nil: ref Draw->Context, args: list of string) +{ + sys = load Sys Sys->PATH; + stderr = sys->fildes(2); + sargs := makestr(args); + prog = hd args; + args = tl args; + bufio = load Bufio Bufio->PATH; + if (bufio == nil) { + sys->fprint(stderr, "%s: could not load %s: %r\n", prog, Bufio->PATH); + return; + } + inf := bufio->fopen(sys->fildes(0), Bufio->OREAD); + if (inf == nil) { + sys->fprint(stderr, "%s: fopen stdin failed: %r\n", prog); + return; + } + while (args != nil && len hd args && (a := hd args)[0] == '-') { + flag: + for (x := 1; x < len a; x++) { + case a[x] { + 'c' => + complete = 1; + 'f' => + xfixed = 1; + 'p' => + paren = 1; + 'u' => + if (++x == len a) { + args = tl args; + if (args == nil) + usage(); + undef = hd args; + } else + undef = a[x:]; + break flag; + * => + usage(); + return; + } + } + args = tl args; + } + vlc := "vlc"; + if (args != nil) { + if (tl args != nil) { + usage(); + return; + } + vlc = hd args; + } + il: s2list; + while ((l := inf.gets('\n')) != nil) { + if (l[0] == '#') + continue; + (n, t) := sys->tokenize(l, " \t\n"); + if (n != 2) { + sys->fprint(stderr, "%s: bad input: %s", prog, l); + return; + } + il = (hd t, hd tl t) :: il; + } + (n, nl) := expand(il); + bits = n; + size = 1 << bits; + table = array[size] of sv; + maketable(nl); + printtable(vlc, sargs); +} + +usage() +{ + sys->fprint(stderr, "usage: %s [-cfp] [-u undef] [stem]\n", prog); +} + +makestr(l: list of string): string +{ + s, t: string; + while (l != nil) { + s = s + t + hd l; + t = " "; + l = tl l; + } + return s; +} + +expand(l: s2list): (int, s2list) +{ + nl: s2list; + max := 0; + while (l != nil) { + (bs, val) := hd l; + n := len bs; + if (n > max) + max = n; + if (bs[n - 1] == 's') { + t := bs[:n - 1]; + nl = (t + "0", val) :: (t + "1", "-" + val) :: nl; + } else + nl = (bs, val) :: nl; + l = tl l; + } + return (max, nl); +} + +maketable(l: s2list) +{ + while (l != nil) { + (bs, val) := hd l; + z := len bs; + if (xfixed && z != bits) + error(sys->sprint("string %s too short", bs)); + s := bits - z; + v := value(bs) << s; + n := 1 << s; + for (i := 0; i < n; i++) { + if (table[v].v != nil) + error(sys->sprint("repeat match for %x", v)); + table[v] = (z, val); + v++; + } + l = tl l; + } +} + +value(s: string): int +{ + n := len s; + v := 0; + for (i := 0; i < n; i++) { + case s[i] { + '0' => + v <<= 1; + '1'=> + v = (v << 1) | 1; + * => + error("bad bitstream: " + s); + } + } + return v; +} + +printtable(s, a: string) +{ + sys->print("# %s\n", a); + sys->print("%s_size: con %d;\n", s, size); + sys->print("%s_bits: con %d;\n", s, bits); + sys->print("%s_table:= array[] of {\n", s); + for (i := 0; i < size; i++) { + if (table[i].v != nil) { + if (xfixed) { + if (paren) + sys->print("\t(%s),\n", table[i].v); + else + sys->print("\t%s,\n", table[i].v); + } else + sys->print("\t(%d, %s),\n", table[i].s, table[i].v); + } else if (!complete) { + if (xfixed) { + if (paren) + sys->print("\t(%s),\n", undef); + else + sys->print("\t%s,\n", undef); + } else + sys->print("\t(0, %s),\n", undef); + } else + error(sys->sprint("no match for %x", i)); + } + sys->print("};\n"); +} + +error(s: string) +{ + sys->fprint(stderr, "%s: error: %s\n", prog, s); + exit; +} |
