Index: trunk/cortado/HACKING |
— | — | @@ -9,6 +9,8 @@ |
10 | 10 | - utils: utitity classes used by jst, jheora, examples |
11 | 11 | - jst: a java port of the GStreamer 0.10 design |
12 | 12 | - jheora: a java implementation of the Theora video codec |
| 13 | + - jkate: a basic java implementation of the Kate codec |
| 14 | + - jtiger: a basic Kate stream renderer (simple text/images only for now) |
13 | 15 | - codecs: additional codecs; currently contains the Smoke codec |
14 | 16 | - plugin: plugins implementing/wrapping sources/decoders/sinks |
15 | 17 | - examples: example programs |
Index: trunk/cortado/src/com/fluendo/jst/Element.java |
— | — | @@ -464,4 +464,8 @@ |
465 | 465 | public boolean query (Query query) { |
466 | 466 | return false; |
467 | 467 | } |
| 468 | + |
| 469 | + public Pad requestSinkPad(Pad peer) { |
| 470 | + return null; |
| 471 | + } |
468 | 472 | } |
Index: trunk/cortado/src/com/fluendo/jst/Sink.java |
— | — | @@ -29,7 +29,7 @@ |
30 | 30 | private boolean needPreroll; |
31 | 31 | private Clock.ClockID clockID; |
32 | 32 | protected boolean discont; |
33 | | - protected long segStart; |
| 33 | + protected long segStart = 0; |
34 | 34 | protected long segStop; |
35 | 35 | protected long segPosition; |
36 | 36 | protected long pauseTime; |
— | — | @@ -352,11 +352,11 @@ |
353 | 353 | synchronized (this) { |
354 | 354 | if (currentState == PLAY) { |
355 | 355 | if (clock != null) { |
356 | | - position = clock.getTime() - baseTime + segPosition; |
| 356 | + position = clock.getTime() - baseTime + segPosition + segStart; |
357 | 357 | } |
358 | 358 | } |
359 | 359 | else { |
360 | | - position = pauseTime + segPosition; |
| 360 | + position = pauseTime + segPosition + segStart; |
361 | 361 | } |
362 | 362 | } |
363 | 363 | query.setPosition(Format.TIME, position); |
Index: trunk/cortado/src/com/fluendo/jtiger/Renderer.java |
— | — | @@ -0,0 +1,62 @@ |
| 2 | +/* JTiger |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jtiger; |
| 23 | + |
| 24 | +import java.util.*; |
| 25 | +import java.awt.*; |
| 26 | +import java.awt.image.*; |
| 27 | + |
| 28 | +public class Renderer { |
| 29 | + private Vector items = new Vector(); |
| 30 | + |
| 31 | + /** |
| 32 | + * Add a new event to the renderer. |
| 33 | + */ |
| 34 | + public void add(com.fluendo.jkate.Event ev) { |
| 35 | + items.addElement(new Item(ev)); |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Update the renderer, and all the events it tracks. |
| 40 | + * Returns 1 if there is nothing to draw, as an optimization |
| 41 | + */ |
| 42 | + public int update(Component c, double t) { |
| 43 | + for (int n=0; n<items.size(); ++n) { |
| 44 | + boolean ret = ((Item)items.get(n)).update(c, t); |
| 45 | + if (!ret) { |
| 46 | + items.removeElementAt(n); |
| 47 | + --n; |
| 48 | + } |
| 49 | + } |
| 50 | + if (items.size() == 0) |
| 51 | + return 1; |
| 52 | + return 0; |
| 53 | + } |
| 54 | + |
| 55 | + /** |
| 56 | + * Renders onto the given image. |
| 57 | + */ |
| 58 | + public void render(Component c, BufferedImage bimg) { |
| 59 | + for (int n=0; n<items.size(); ++n) { |
| 60 | + ((Item)items.get(n)).render(c, bimg); |
| 61 | + } |
| 62 | + } |
| 63 | +} |
Index: trunk/cortado/src/com/fluendo/jtiger/TigerBitmap.java |
— | — | @@ -0,0 +1,93 @@ |
| 2 | +/* JTiger |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jtiger; |
| 23 | + |
| 24 | +import java.util.*; |
| 25 | +import java.awt.*; |
| 26 | +import java.awt.image.*; |
| 27 | +import com.fluendo.jkate.*; |
| 28 | +import com.fluendo.utils.*; |
| 29 | + |
| 30 | +public class TigerBitmap { |
| 31 | + private Image image; |
| 32 | + private Image scaled_image; |
| 33 | + |
| 34 | + /** |
| 35 | + * Create a new TigerBitmap from a Kate bitmap and optional palette. |
| 36 | + */ |
| 37 | + public TigerBitmap(Bitmap kb, Palette kp) |
| 38 | + { |
| 39 | + if (kb == null) { |
| 40 | + image = null; |
| 41 | + } |
| 42 | + else if (kb.bpp == 0) { |
| 43 | + /* PNG */ |
| 44 | + image = createPNGBitmap(kb, kp); |
| 45 | + } |
| 46 | + else { |
| 47 | + if (kp == null) { |
| 48 | + image = null; |
| 49 | + } |
| 50 | + else { |
| 51 | + image = createPalettedBitmap(kb, kp); |
| 52 | + } |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Returns a scaled version of the image. |
| 58 | + */ |
| 59 | + public Image getScaled(int width, int height) |
| 60 | + { |
| 61 | + if (scaled_image == null || width != scaled_image.getWidth(null) || height != scaled_image.getHeight(null)) { |
| 62 | + scaled_image = image.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH); // TODO: quality setting |
| 63 | + } |
| 64 | + return scaled_image; |
| 65 | + } |
| 66 | + |
| 67 | + /** |
| 68 | + * Create an image from bits representing a PNG image. |
| 69 | + */ |
| 70 | + private Image createPNGBitmap(Bitmap kb, Palette kp) |
| 71 | + { |
| 72 | + Debug.warning("PNG bitmaps not supported yet"); |
| 73 | + return null; |
| 74 | + } |
| 75 | + |
| 76 | + /** |
| 77 | + * Create a paletted image. |
| 78 | + */ |
| 79 | + private Image createPalettedBitmap(Bitmap kb, Palette kp) |
| 80 | + { |
| 81 | + byte[] cmap = new byte[4*kp.colors.length]; |
| 82 | + for (int n=0; n<kp.colors.length; ++n) { |
| 83 | + cmap[n*4+0] = kp.colors[n].r; |
| 84 | + cmap[n*4+1] = kp.colors[n].g; |
| 85 | + cmap[n*4+2] = kp.colors[n].b; |
| 86 | + cmap[n*4+3] = kp.colors[n].a; |
| 87 | + } |
| 88 | + IndexColorModel icm = new IndexColorModel(kb.bpp, kp.colors.length, cmap, 0, true); |
| 89 | + BufferedImage img = new BufferedImage(kb.width, kb.height, BufferedImage.TYPE_BYTE_INDEXED, icm); |
| 90 | + WritableRaster r = img.getRaster(); |
| 91 | + r.setDataElements(0, 0, kb.width, kb.height, kb.pixels); |
| 92 | + return img; |
| 93 | + } |
| 94 | +} |
Index: trunk/cortado/src/com/fluendo/jtiger/README |
— | — | @@ -0,0 +1,3 @@ |
| 2 | +JTiger is a very basic renderer for Kate streams. |
| 3 | + |
| 4 | +At the moment, only raw text is supported. |
Index: trunk/cortado/src/com/fluendo/jtiger/Item.java |
— | — | @@ -0,0 +1,192 @@ |
| 2 | +/* JTiger |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JTiger are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jtiger; |
| 23 | + |
| 24 | +import java.util.*; |
| 25 | +import java.awt.*; |
| 26 | +import java.awt.image.*; |
| 27 | +import java.awt.font.*; |
| 28 | +import java.text.*; |
| 29 | +import com.fluendo.jkate.Event; |
| 30 | +import com.fluendo.jkate.Tracker; |
| 31 | +import com.fluendo.utils.*; |
| 32 | + |
| 33 | +public class Item { |
| 34 | + private Tracker kin = null; |
| 35 | + private boolean alive = false; |
| 36 | + private Font font = null; |
| 37 | + private String text = null; |
| 38 | + private TigerBitmap background_image = null; |
| 39 | + |
| 40 | + private int width = -1; |
| 41 | + private int height = -1; |
| 42 | + |
| 43 | + private float region_x; |
| 44 | + private float region_y; |
| 45 | + private float region_w; |
| 46 | + private float region_h; |
| 47 | + |
| 48 | + |
| 49 | + /** |
| 50 | + * Create a new item from a Kate event. |
| 51 | + */ |
| 52 | + public Item(com.fluendo.jkate.Event ev) { |
| 53 | + this.kin = new Tracker(ev); |
| 54 | + text = null; |
| 55 | + if (ev.text != null && ev.text.length > 0) { |
| 56 | + try { |
| 57 | + text = new String(ev.text, "UTF8"); |
| 58 | + } |
| 59 | + catch (Exception e) { |
| 60 | + Debug.warning("Failed to convert text from UTF-8 - text will not display"); |
| 61 | + text = null; |
| 62 | + } |
| 63 | + } |
| 64 | + } |
| 65 | + |
| 66 | + /** |
| 67 | + * Create a font suitable for displaying on the given component |
| 68 | + */ |
| 69 | + protected void createFont(Component c) { |
| 70 | + Dimension d = c.getSize(); |
| 71 | + int font_size = d.width / 32; |
| 72 | + if (font_size < 12) font_size = 12; |
| 73 | + font = new Font("sans", Font.BOLD, font_size); // TODO: should be selectable ? |
| 74 | + } |
| 75 | + |
| 76 | + /** |
| 77 | + * Regenerate any cached data to match any relevant changes in the |
| 78 | + * given component |
| 79 | + */ |
| 80 | + protected void updateCachedData(Component c) { |
| 81 | + Dimension d = c.getSize(); |
| 82 | + if (d.width == width && d.height == height) |
| 83 | + return; |
| 84 | + |
| 85 | + createFont(c); |
| 86 | + |
| 87 | + width = d.width; |
| 88 | + height = d.height; |
| 89 | + } |
| 90 | + |
| 91 | + /** |
| 92 | + * Updates the item at the given time. |
| 93 | + * returns true for alive, false for dead |
| 94 | + */ |
| 95 | + public boolean update(Component c, double t) { |
| 96 | + com.fluendo.jkate.Event ev = kin.ev; |
| 97 | + if (ev == null) return false; |
| 98 | + if (t >= ev.end_time) return false; |
| 99 | + |
| 100 | + if (t < ev.start_time) { |
| 101 | + alive = false; |
| 102 | + } |
| 103 | + else { |
| 104 | + alive = true; |
| 105 | + } |
| 106 | + |
| 107 | + Dimension d = c.getSize(); |
| 108 | + return kin.update(t-ev.start_time, d, d); |
| 109 | + } |
| 110 | + |
| 111 | + /** |
| 112 | + * Set up the region. |
| 113 | + */ |
| 114 | + public void setupRegion(Component c) { |
| 115 | + if (kin.has[Tracker.has_region]) { |
| 116 | + region_x = kin.region_x; |
| 117 | + region_y = kin.region_y; |
| 118 | + region_w = kin.region_w; |
| 119 | + region_h = kin.region_h; |
| 120 | + } |
| 121 | + else { |
| 122 | + Dimension d = c.getSize(); |
| 123 | + region_x = d.width * 0.1f; |
| 124 | + region_y = d.height * 0.8f; |
| 125 | + region_w = d.width * 0.8f; |
| 126 | + region_h = d.height * 0.1f; |
| 127 | + } |
| 128 | + } |
| 129 | + |
| 130 | + /** |
| 131 | + * Renders the item on the given image. |
| 132 | + */ |
| 133 | + public void render(Component c, BufferedImage bimg) { |
| 134 | + com.fluendo.jkate.Event ev = kin.ev; |
| 135 | + |
| 136 | + if (!alive) |
| 137 | + return; |
| 138 | + |
| 139 | + updateCachedData(c); |
| 140 | + |
| 141 | + setupRegion(c); |
| 142 | + renderBackground(bimg); |
| 143 | + renderText(bimg); |
| 144 | + } |
| 145 | + |
| 146 | + /** |
| 147 | + * Render a background for the item, if approrpiate. |
| 148 | + * The background may be a color, or an image. |
| 149 | + */ |
| 150 | + public void renderBackground(BufferedImage bimg) |
| 151 | + { |
| 152 | + if (kin.ev.bitmap != null) { |
| 153 | + if (background_image == null) { |
| 154 | + background_image = new TigerBitmap(kin.ev.bitmap, kin.ev.palette); |
| 155 | + } |
| 156 | + |
| 157 | + Graphics2D g = bimg.createGraphics(); |
| 158 | + int rx = (int)(region_x+0.5), ry = (int)(region_y+0.5); |
| 159 | + int rw = (int)(region_w+0.5), rh = (int)(region_h+0.5); |
| 160 | + g.drawImage(background_image.getScaled(rw, rh), rx, ry, null); |
| 161 | + g.dispose(); |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + /** |
| 166 | + * Render text text for the item, if approrpiate. |
| 167 | + */ |
| 168 | + public void renderText(BufferedImage bimg) |
| 169 | + { |
| 170 | + if (text == null) |
| 171 | + return; |
| 172 | + |
| 173 | + Graphics2D g = bimg.createGraphics(); |
| 174 | + |
| 175 | + AttributedString atext = new AttributedString(text, font.getAttributes()); |
| 176 | + AttributedCharacterIterator text_it = atext.getIterator(); |
| 177 | + int text_end = text_it.getEndIndex(); |
| 178 | + g.setColor(Color.white); |
| 179 | + |
| 180 | + FontRenderContext frc = g.getFontRenderContext(); |
| 181 | + LineBreakMeasurer lbm = new LineBreakMeasurer(text_it, frc); |
| 182 | + float dy = 0.0f; |
| 183 | + while (lbm.getPosition() < text_end) { |
| 184 | + TextLayout layout = lbm.nextLayout(region_w); |
| 185 | + dy += layout.getAscent(); |
| 186 | + float tw = layout.getAdvance(); |
| 187 | + layout.draw(g, region_x+((region_w-tw)/2), region_y+dy); |
| 188 | + dy += layout.getDescent() + layout.getLeading(); |
| 189 | + } |
| 190 | + |
| 191 | + g.dispose(); |
| 192 | + } |
| 193 | +} |
Index: trunk/cortado/src/com/fluendo/player/CortadoPipeline.java |
— | — | @@ -18,6 +18,7 @@ |
19 | 19 | |
20 | 20 | package com.fluendo.player; |
21 | 21 | |
| 22 | +import java.util.*; |
22 | 23 | import java.awt.*; |
23 | 24 | import java.net.URL; |
24 | 25 | |
— | — | @@ -31,6 +32,7 @@ |
32 | 33 | private String password; |
33 | 34 | private boolean enableAudio; |
34 | 35 | private boolean enableVideo; |
| 36 | + private int enableKate; |
35 | 37 | private Component component; |
36 | 38 | private int bufferSize = -1; |
37 | 39 | private int bufferLow = -1; |
— | — | @@ -46,8 +48,12 @@ |
47 | 49 | private Element videosink; |
48 | 50 | private Element audiosink; |
49 | 51 | private Element v_queue, a_queue; |
50 | | - private Pad asinkpad, vsinkpad; |
| 52 | + private Element overlay; |
| 53 | + private Pad asinkpad, ovsinkpad, oksinkpad; |
51 | 54 | private Pad apad, vpad; |
| 55 | + private Vector katedec = new Vector(); |
| 56 | + private Vector k_queue = new Vector(); |
| 57 | + private Element kselector = null; |
52 | 58 | |
53 | 59 | public boolean usingJavaX = false; |
54 | 60 | |
— | — | @@ -115,7 +121,7 @@ |
116 | 122 | |
117 | 123 | pad.link(v_queue.getPad("sink")); |
118 | 124 | v_queue.getPad("src").link(videodec.getPad("sink")); |
119 | | - if (!videodec.getPad("src").link(vsinkpad)) { |
| 125 | + if (!videodec.getPad("src").link(ovsinkpad)) { |
120 | 126 | postMessage (Message.newError (this, "videosink already linked")); |
121 | 127 | return; |
122 | 128 | } |
— | — | @@ -132,7 +138,7 @@ |
133 | 139 | videodec.setProperty ("component", component); |
134 | 140 | |
135 | 141 | pad.link(videodec.getPad("sink")); |
136 | | - if (!videodec.getPad("src").link(vsinkpad)) { |
| 142 | + if (!videodec.getPad("src").link(ovsinkpad)) { |
137 | 143 | postMessage (Message.newError (this, "videosink already linked")); |
138 | 144 | return; |
139 | 145 | } |
— | — | @@ -146,7 +152,7 @@ |
147 | 153 | videodec.setProperty ("component", component); |
148 | 154 | |
149 | 155 | pad.link(videodec.getPad("sink")); |
150 | | - if (!videodec.getPad("src").link(vsinkpad)) { |
| 156 | + if (!videodec.getPad("src").link(ovsinkpad)) { |
151 | 157 | postMessage (Message.newError (this, "videosink already linked")); |
152 | 158 | return; |
153 | 159 | } |
— | — | @@ -154,13 +160,85 @@ |
155 | 161 | |
156 | 162 | videodec.setState (PAUSE); |
157 | 163 | } |
| 164 | + else if (enableVideo && mime.equals("application/x-kate")) { |
| 165 | + Element tmp_k_queue, tmp_katedec, tmp_katesink; |
| 166 | + Pad tmp_kpad, tmp_ksinkpad; |
| 167 | + int kate_index = katedec.size(); |
| 168 | + |
| 169 | + Debug.debug("Found Kate stream, setting up pipeline branch"); |
| 170 | + |
| 171 | + /* dynamically create a queue/decoder/overlay pipeline */ |
| 172 | + tmp_k_queue = ElementFactory.makeByName("queue", "k_queue"+kate_index); |
| 173 | + if (tmp_k_queue == null) { |
| 174 | + noSuchElement ("queue"); |
| 175 | + return; |
| 176 | + } |
| 177 | + |
| 178 | + tmp_katedec = ElementFactory.makeByName("katedec", "katedec"+kate_index); |
| 179 | + if (tmp_katedec == null) { |
| 180 | + noSuchElement ("katedec"); |
| 181 | + return; |
| 182 | + } |
| 183 | + |
| 184 | + /* The selector is created when the first Kate stream is encountered */ |
| 185 | + if (kselector == null) { |
| 186 | + Debug.debug("No Kate selector yet, creating one"); |
| 187 | + kselector = ElementFactory.makeByName("selector", "selector"); |
| 188 | + if (kselector == null) { |
| 189 | + noSuchElement ("selector"); |
| 190 | + return; |
| 191 | + } |
| 192 | + add(kselector); |
| 193 | + if (!kselector.getPad("src").link(oksinkpad)) { |
| 194 | + postMessage (Message.newError (this, "Failed linking Kate selector to overlay")); |
| 195 | + return; |
| 196 | + } |
| 197 | + kselector.setState (PAUSE); |
| 198 | + } |
| 199 | + tmp_katesink = kselector; |
| 200 | + |
| 201 | + add(tmp_k_queue); |
| 202 | + add(tmp_katedec); |
| 203 | + |
| 204 | + tmp_kpad = pad; |
| 205 | + tmp_ksinkpad = tmp_katesink.getPad("sink"); |
| 206 | + |
| 207 | + /* link new elements together */ |
| 208 | + if (!pad.link(tmp_k_queue.getPad("sink"))) { |
| 209 | + postMessage (Message.newError (this, "Failed to link new Kate stream to queue")); |
| 210 | + return; |
| 211 | + } |
| 212 | + if (!tmp_k_queue.getPad("src").link(tmp_katedec.getPad("sink"))) { |
| 213 | + postMessage (Message.newError (this, "Failed to link new Kate queue to decoder")); |
| 214 | + return; |
| 215 | + } |
| 216 | + |
| 217 | + Pad new_selector_pad = kselector.requestSinkPad(tmp_katedec.getPad("src")); |
| 218 | + if (!tmp_katedec.getPad("src").link(new_selector_pad)) { |
| 219 | + postMessage (Message.newError (this, "kate sink already linked")); |
| 220 | + return; |
| 221 | + } |
| 222 | + |
| 223 | + tmp_katedec.setState (PAUSE); |
| 224 | + tmp_k_queue.setState (PAUSE); |
| 225 | + |
| 226 | + /* add to the lists */ |
| 227 | + katedec.addElement(tmp_katedec); |
| 228 | + k_queue.addElement(tmp_k_queue); |
| 229 | + |
| 230 | + /* if we have just added the one that was selected, link it now */ |
| 231 | + if (enableKate == katedec.size()-1) { |
| 232 | + doEnableKateIndex(enableKate); |
| 233 | + } |
| 234 | + } |
158 | 235 | } |
159 | 236 | |
160 | 237 | public void padRemoved(Pad pad) { |
161 | 238 | pad.unlink(); |
162 | 239 | if (pad == vpad) { |
163 | 240 | Debug.log(Debug.INFO, "video pad removed "+pad); |
164 | | - vsinkpad.unlink(); |
| 241 | + ovsinkpad.unlink(); |
| 242 | + //oksinkpad.unlink(); // needed ???? |
165 | 243 | vpad = null; |
166 | 244 | } |
167 | 245 | else if (pad == apad) { |
— | — | @@ -172,6 +250,7 @@ |
173 | 251 | |
174 | 252 | public void noMorePads() { |
175 | 253 | boolean changed = false; |
| 254 | + Element el; |
176 | 255 | |
177 | 256 | Debug.log(Debug.INFO, "all streams detected"); |
178 | 257 | |
— | — | @@ -185,8 +264,26 @@ |
186 | 265 | if (vpad == null && enableVideo) { |
187 | 266 | Debug.log(Debug.INFO, "file has no video, remove videosink"); |
188 | 267 | videosink.setState(STOP); |
| 268 | + overlay.setState(STOP); |
| 269 | + for (int n=0; n<katedec.size(); ++n) { |
| 270 | + el = (Element)katedec.get(n); |
| 271 | + el.setState(STOP); |
| 272 | + remove(el); |
| 273 | + el = (Element)k_queue.get(n); |
| 274 | + el.setState(STOP); |
| 275 | + remove(el); |
| 276 | + } |
| 277 | + if (kselector != null) { |
| 278 | + kselector.setState(STOP); |
| 279 | + remove(kselector); |
| 280 | + kselector = null; |
| 281 | + } |
189 | 282 | remove (videosink); |
| 283 | + remove (overlay); |
| 284 | + katedec.clear(); |
| 285 | + k_queue.clear(); |
190 | 286 | videosink = null; |
| 287 | + overlay = null; |
191 | 288 | changed = true; |
192 | 289 | } |
193 | 290 | if (changed) |
— | — | @@ -199,6 +296,7 @@ |
200 | 297 | enableAudio = true; |
201 | 298 | enableVideo = true; |
202 | 299 | application = cortado; |
| 300 | + enableKate = -1; /* none by default */ |
203 | 301 | } |
204 | 302 | |
205 | 303 | public void setUrl(String anUrl) { |
— | — | @@ -228,6 +326,40 @@ |
229 | 327 | return enableVideo; |
230 | 328 | } |
231 | 329 | |
| 330 | + /** |
| 331 | + * Selects the Kate stream index (if any) to enable. |
| 332 | + * The first Kate stream has index 0, the second has index 1, etc. |
| 333 | + * A negative index will enable none. |
| 334 | + */ |
| 335 | + public void enableKateIndex(int idx) { |
| 336 | + if (idx == enableKate) return; |
| 337 | + doEnableKateIndex(idx); |
| 338 | + } |
| 339 | + |
| 340 | + /** |
| 341 | + * Enables the given Kate stream, by index. |
| 342 | + * A negative index will enable none. |
| 343 | + */ |
| 344 | + private void doEnableKateIndex(int idx) |
| 345 | + { |
| 346 | + if (kselector != null) { |
| 347 | + Debug.info("Switching Kate streams from "+enableKate+" to "+idx); |
| 348 | + kselector.setProperty("selected", new Integer(idx)); |
| 349 | + } |
| 350 | + else { |
| 351 | + Debug.warning("Switching Kate stream request, but no Kate selector exists"); |
| 352 | + } |
| 353 | + |
| 354 | + enableKate = idx; |
| 355 | + } |
| 356 | + |
| 357 | + /** |
| 358 | + * Returns the index of the currently enabled Kate stream (negative if none) |
| 359 | + */ |
| 360 | + public int getEnabledKateIndex() { |
| 361 | + return enableKate; |
| 362 | + } |
| 363 | + |
232 | 364 | public void setComponent(Component c) { |
233 | 365 | component = c; |
234 | 366 | } |
— | — | @@ -410,8 +542,22 @@ |
411 | 543 | resize(component.getSize()); |
412 | 544 | |
413 | 545 | videosink.setProperty ("max-lateness", Long.toString(Clock.MSECOND * 20)); |
414 | | - vsinkpad = videosink.getPad("sink"); |
415 | 546 | add(videosink); |
| 547 | + |
| 548 | + /* TODO: we need that in case there are kate streams, but could be |
| 549 | + better to build it only when kate streams are actually found later */ |
| 550 | + overlay = ElementFactory.makeByName("kateoverlay", "overlay"); |
| 551 | + if (overlay == null) { |
| 552 | + noSuchElement ("overlay"); |
| 553 | + return false; |
| 554 | + } |
| 555 | + ovsinkpad = overlay.getPad("videosink"); |
| 556 | + oksinkpad = overlay.getPad("katesink"); |
| 557 | + add(overlay); |
| 558 | + |
| 559 | + overlay.setProperty ("component", component); |
| 560 | + |
| 561 | + overlay.getPad("videosrc").link(videosink.getPad("sink")); |
416 | 562 | } |
417 | 563 | if (audiosink == null && videosink == null) { |
418 | 564 | postMessage(Message.newError(this, "Both audio and video are disabled, can't play anything")); |
— | — | @@ -445,6 +591,7 @@ |
446 | 592 | } |
447 | 593 | |
448 | 594 | private boolean cleanup() { |
| 595 | + int n; |
449 | 596 | Debug.log(Debug.INFO, "cleanup"); |
450 | 597 | if (httpsrc != null) { |
451 | 598 | remove (httpsrc); |
— | — | @@ -458,8 +605,13 @@ |
459 | 606 | if (videosink != null) { |
460 | 607 | remove (videosink); |
461 | 608 | videosink = null; |
462 | | - vsinkpad = null; |
463 | 609 | } |
| 610 | + if (overlay != null) { |
| 611 | + remove (overlay); |
| 612 | + overlay = null; |
| 613 | + ovsinkpad = null; |
| 614 | + oksinkpad = null; |
| 615 | + } |
464 | 616 | if (buffer != null) { |
465 | 617 | remove (buffer); |
466 | 618 | buffer = null; |
— | — | @@ -485,6 +637,23 @@ |
486 | 638 | remove(audiodec); |
487 | 639 | audiodec = null; |
488 | 640 | } |
| 641 | + |
| 642 | + for (n=0; n<katedec.size(); ++n) { |
| 643 | + if (k_queue.get(n) != null) { |
| 644 | + remove ((Element)k_queue.get(n)); |
| 645 | + } |
| 646 | + if (katedec.get(n) != null) { |
| 647 | + remove((Element)katedec.get(n)); |
| 648 | + } |
| 649 | + } |
| 650 | + k_queue.clear(); |
| 651 | + katedec.clear(); |
| 652 | + |
| 653 | + if (kselector != null) { |
| 654 | + remove(kselector); |
| 655 | + kselector = null; |
| 656 | + } |
| 657 | + |
489 | 658 | return true; |
490 | 659 | } |
491 | 660 | |
Index: trunk/cortado/src/com/fluendo/player/Cortado.java |
— | — | @@ -34,6 +34,7 @@ |
35 | 35 | private String urlString; |
36 | 36 | private boolean audio; |
37 | 37 | private boolean video; |
| 38 | + private int kateIndex; |
38 | 39 | private boolean showSpeaker; |
39 | 40 | private boolean keepAspect; |
40 | 41 | private boolean autoPlay; |
— | — | @@ -100,6 +101,7 @@ |
101 | 102 | "Total duration of the file in seconds (default unknown)"}, |
102 | 103 | {"audio", "boolean", "Enable audio playback (default true)"}, |
103 | 104 | {"video", "boolean", "Enable video playback (default true)"}, |
| 105 | + {"kateIndex", "boolean", "Enable playback of a particular Kate stream (default -1 (none))"}, |
104 | 106 | {"statusHeight", "int", "The height of the status area (default 12)"}, |
105 | 107 | {"autoPlay", "boolean", "Automatically start playback (default true)"}, |
106 | 108 | {"showStatus", "enum", "Show status area (auto|show|hide) (default auto)"}, |
— | — | @@ -223,6 +225,7 @@ |
224 | 226 | durationParam = getDoubleParam("duration", -1.0); |
225 | 227 | audio = getBoolParam("audio", true); |
226 | 228 | video = getBoolParam("video", true); |
| 229 | + kateIndex = getIntParam("kateIndex", -1); |
227 | 230 | statusHeight = getIntParam("statusHeight", 12); |
228 | 231 | autoPlay = getBoolParam("autoPlay", true); |
229 | 232 | showStatus = getEnumParam("showStatus", showStatusVals, "auto"); |
— | — | @@ -257,6 +260,7 @@ |
258 | 261 | pipeline.setPassword(password); |
259 | 262 | pipeline.enableAudio(audio); |
260 | 263 | pipeline.enableVideo(video); |
| 264 | + pipeline.enableKateIndex(kateIndex); |
261 | 265 | pipeline.setBufferSize(bufferSize); |
262 | 266 | pipeline.setBufferLow(bufferLow); |
263 | 267 | pipeline.setBufferHigh(bufferHigh); |
Index: trunk/cortado/src/com/fluendo/examples/Player.java |
— | — | @@ -38,6 +38,7 @@ |
39 | 39 | applet.setParam ("keepaspect", "true"); |
40 | 40 | applet.setParam ("video", "true"); |
41 | 41 | applet.setParam ("audio", "true"); |
| 42 | + applet.setParam ("kateIndex", "0"); |
42 | 43 | //applet.setParam ("audio", "false"); |
43 | 44 | applet.setParam ("bufferSize", "200"); |
44 | 45 | applet.setParam ("userId", "wim"); |
Index: trunk/cortado/src/com/fluendo/jkate/Bitmap.java |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A Bitmap definition. |
| 26 | + */ |
| 27 | +public class Bitmap |
| 28 | +{ |
| 29 | + public int width; |
| 30 | + public int height; |
| 31 | + public int bpp; |
| 32 | + public KateBitmapType type; |
| 33 | + public int palette; |
| 34 | + public byte[] pixels; |
| 35 | + public int size; |
| 36 | + public int x_offset; |
| 37 | + public int y_offset; |
| 38 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/README |
— | — | @@ -0,0 +1,4 @@ |
| 2 | +JKate is a simple Kate stream decoder. |
| 3 | + |
| 4 | +At the moment, only text is supported. |
| 5 | + |
Index: trunk/cortado/src/com/fluendo/jkate/Result.java |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public final class Result { |
| 25 | + public static final int KATE_E_NOT_FOUND = -1; |
| 26 | + public static final int KATE_E_INVALID_PARAMETER = -2; |
| 27 | + public static final int KATE_E_OUT_OF_MEMORY = -3; |
| 28 | + public static final int KATE_E_BAD_GRANULE = -4; |
| 29 | + public static final int KATE_E_INIT = -5; |
| 30 | + public static final int KATE_E_BAD_PACKET = -6; |
| 31 | + public static final int KATE_E_TEXT = -7; |
| 32 | + public static final int KATE_E_LIMIT = -8; |
| 33 | + public static final int KATE_E_VERSION = -9; |
| 34 | + public static final int KATE_E_NOT_KATE = -10; |
| 35 | + public static final int KATE_E_BAD_TAG = -11; |
| 36 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Color.java |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class Color |
| 25 | +{ |
| 26 | + public byte r; |
| 27 | + public byte g; |
| 28 | + public byte b; |
| 29 | + public byte a; |
| 30 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/State.java |
— | — | @@ -0,0 +1,128 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +import com.jcraft.jogg.*; |
| 25 | +import com.fluendo.utils.*; |
| 26 | + |
| 27 | +public class State |
| 28 | +{ |
| 29 | + long granulepos; |
| 30 | + |
| 31 | + private Decode dec; |
| 32 | + private Event ev = null; |
| 33 | + |
| 34 | + public void clear() |
| 35 | + { |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Initialize for decoding. |
| 40 | + */ |
| 41 | + public int decodeInit(Info ki) |
| 42 | + { |
| 43 | + dec = new Decode(ki); |
| 44 | + granulepos=-1; |
| 45 | + |
| 46 | + return(0); |
| 47 | + } |
| 48 | + |
| 49 | + /** |
| 50 | + * Decode a Kate data packet. |
| 51 | + * Headers are supposed to have been parsed already. |
| 52 | + * An event may be generated, and will then be available from decodeEventOut. |
| 53 | + */ |
| 54 | + public int decodePacketin (Packet op) |
| 55 | + { |
| 56 | + long ret; |
| 57 | + byte type; |
| 58 | + |
| 59 | + ev = null; |
| 60 | + |
| 61 | + dec.opb.readinit(op.packet_base, op.packet, op.bytes); |
| 62 | + |
| 63 | + /* get packet type */ |
| 64 | + type = (byte)dec.opb.read(8); |
| 65 | + Debug.log(Debug.DEBUG, "decodePacketin: got packet type "+type); |
| 66 | + |
| 67 | + /* ignore headers */ |
| 68 | + if ((type & 0x80) != 0) |
| 69 | + return 0; |
| 70 | + |
| 71 | + switch (type) { |
| 72 | + case 0x00: |
| 73 | + ev = new Event(dec.info); |
| 74 | + ret = dec.decodeTextPacket(ev); |
| 75 | + |
| 76 | + if(ret < 0) { |
| 77 | + ev = null; |
| 78 | + return (int) ret; |
| 79 | + } |
| 80 | + |
| 81 | + if(op.granulepos>-1) |
| 82 | + granulepos=op.granulepos; |
| 83 | + else{ |
| 84 | + if(granulepos==-1){ |
| 85 | + granulepos=0; |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + return 0; |
| 90 | + |
| 91 | + case 0x01: |
| 92 | + /* keepalive */ |
| 93 | + return 0; |
| 94 | + |
| 95 | + case 0x7f: |
| 96 | + /* eos */ |
| 97 | + return 1; |
| 98 | + |
| 99 | + default: |
| 100 | + Debug.debug("Kate packet type "+type+" ignored"); |
| 101 | + return 0; |
| 102 | + } |
| 103 | + } |
| 104 | + |
| 105 | + /** |
| 106 | + * Returns the event (if any) generated from the last decoded packet. |
| 107 | + */ |
| 108 | + public Event decodeEventOut () |
| 109 | + { |
| 110 | + return ev; |
| 111 | + } |
| 112 | + |
| 113 | + /** |
| 114 | + * Returns, in seconds, absolute time of current packet in given |
| 115 | + * logical stream |
| 116 | + */ |
| 117 | + public double granuleTime(long granulepos) |
| 118 | + { |
| 119 | + return dec.granuleTime(granulepos); |
| 120 | + } |
| 121 | + |
| 122 | + /** |
| 123 | + * Returns, in seconds, duration in granule units |
| 124 | + */ |
| 125 | + public double granuleDuration(long granulepos) |
| 126 | + { |
| 127 | + return dec.granuleDuration(granulepos); |
| 128 | + } |
| 129 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Event.java |
— | — | @@ -0,0 +1,69 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class Event |
| 25 | +{ |
| 26 | + public Info ki = null; |
| 27 | + |
| 28 | + public long start; |
| 29 | + public long duration; |
| 30 | + public long backlink; |
| 31 | + public double start_time; |
| 32 | + public double end_time; |
| 33 | + |
| 34 | + public int id = -1; |
| 35 | + |
| 36 | + public KateTextEncoding text_encoding; |
| 37 | + public KateTextDirectionality text_directionality; |
| 38 | + public KateMarkupType markup_type; |
| 39 | + public byte[] language; |
| 40 | + |
| 41 | + public Region kr = null; |
| 42 | + public Style ks = null; |
| 43 | + public Style ks2 = null; |
| 44 | + public Motion motions[] = null; |
| 45 | + public Palette palette = null; |
| 46 | + public Bitmap bitmap = null; |
| 47 | + public FontMapping font_mapping = null; |
| 48 | + |
| 49 | + public byte text[]; |
| 50 | + |
| 51 | + /** |
| 52 | + * Initialize an event to safe defaults. |
| 53 | + */ |
| 54 | + public Event(Info ki) { |
| 55 | + this.ki = ki; |
| 56 | + id = -1; |
| 57 | + kr = null; |
| 58 | + ks = null; |
| 59 | + ks2 = null; |
| 60 | + motions = null; |
| 61 | + palette = null; |
| 62 | + bitmap = null; |
| 63 | + text = null; |
| 64 | + font_mapping = null; |
| 65 | + text_encoding = ki.text_encoding; |
| 66 | + text_directionality = ki.text_directionality; |
| 67 | + markup_type = ki.markup_type; |
| 68 | + language = null; |
| 69 | + } |
| 70 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateMotionSemantics.java |
— | — | @@ -0,0 +1,119 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateMotionSemantics { |
| 25 | + public static final KateMotionSemantics kate_motion_semantics_time = new KateMotionSemantics (); |
| 26 | + public static final KateMotionSemantics kate_motion_semantics_z = new KateMotionSemantics (); |
| 27 | + public static final KateMotionSemantics kate_motion_semantics_region_position = new KateMotionSemantics (); |
| 28 | + public static final KateMotionSemantics kate_motion_semantics_region_size = new KateMotionSemantics (); |
| 29 | + public static final KateMotionSemantics kate_motion_semantics_text_alignment_int = new KateMotionSemantics (); |
| 30 | + public static final KateMotionSemantics kate_motion_semantics_text_alignment_ext = new KateMotionSemantics (); |
| 31 | + public static final KateMotionSemantics kate_motion_semantics_text_position = new KateMotionSemantics (); |
| 32 | + public static final KateMotionSemantics kate_motion_semantics_text_size = new KateMotionSemantics (); |
| 33 | + public static final KateMotionSemantics kate_motion_semantics_marker1_position = new KateMotionSemantics (); |
| 34 | + public static final KateMotionSemantics kate_motion_semantics_marker2_position = new KateMotionSemantics (); |
| 35 | + public static final KateMotionSemantics kate_motion_semantics_marker3_position = new KateMotionSemantics (); |
| 36 | + public static final KateMotionSemantics kate_motion_semantics_marker4_position = new KateMotionSemantics (); |
| 37 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_1 = new KateMotionSemantics (); |
| 38 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_2 = new KateMotionSemantics (); |
| 39 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_3 = new KateMotionSemantics (); |
| 40 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_4 = new KateMotionSemantics (); |
| 41 | + public static final KateMotionSemantics kate_motion_semantics_text_color_rg = new KateMotionSemantics (); |
| 42 | + public static final KateMotionSemantics kate_motion_semantics_text_color_ba = new KateMotionSemantics (); |
| 43 | + public static final KateMotionSemantics kate_motion_semantics_background_color_rg = new KateMotionSemantics (); |
| 44 | + public static final KateMotionSemantics kate_motion_semantics_background_color_ba = new KateMotionSemantics (); |
| 45 | + public static final KateMotionSemantics kate_motion_semantics_draw_color_rg = new KateMotionSemantics (); |
| 46 | + public static final KateMotionSemantics kate_motion_semantics_draw_color_ba = new KateMotionSemantics (); |
| 47 | + public static final KateMotionSemantics kate_motion_semantics_style_morph = new KateMotionSemantics (); |
| 48 | + public static final KateMotionSemantics kate_motion_semantics_text_path = new KateMotionSemantics (); |
| 49 | + public static final KateMotionSemantics kate_motion_semantics_text_path_section = new KateMotionSemantics (); |
| 50 | + public static final KateMotionSemantics kate_motion_semantics_draw = new KateMotionSemantics (); |
| 51 | + public static final KateMotionSemantics kate_motion_semantics_text_visible_section = new KateMotionSemantics (); |
| 52 | + public static final KateMotionSemantics kate_motion_semantics_horizontal_margins = new KateMotionSemantics (); |
| 53 | + public static final KateMotionSemantics kate_motion_semantics_vertical_margins = new KateMotionSemantics (); |
| 54 | + public static final KateMotionSemantics kate_motion_semantics_bitmap_position = new KateMotionSemantics (); |
| 55 | + public static final KateMotionSemantics kate_motion_semantics_bitmap_size = new KateMotionSemantics (); |
| 56 | + public static final KateMotionSemantics kate_motion_semantics_marker1_bitmap = new KateMotionSemantics (); |
| 57 | + public static final KateMotionSemantics kate_motion_semantics_marker2_bitmap = new KateMotionSemantics (); |
| 58 | + public static final KateMotionSemantics kate_motion_semantics_marker3_bitmap = new KateMotionSemantics (); |
| 59 | + public static final KateMotionSemantics kate_motion_semantics_marker4_bitmap = new KateMotionSemantics (); |
| 60 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_1_bitmap = new KateMotionSemantics (); |
| 61 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_2_bitmap = new KateMotionSemantics (); |
| 62 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_3_bitmap = new KateMotionSemantics (); |
| 63 | + public static final KateMotionSemantics kate_motion_semantics_glyph_pointer_4_bitmap = new KateMotionSemantics (); |
| 64 | + public static final KateMotionSemantics kate_motion_semantics_draw_width = new KateMotionSemantics (); |
| 65 | + |
| 66 | + private static final KateMotionSemantics[] list = { |
| 67 | + kate_motion_semantics_time, |
| 68 | + kate_motion_semantics_z, |
| 69 | + kate_motion_semantics_region_position, |
| 70 | + kate_motion_semantics_region_size, |
| 71 | + kate_motion_semantics_text_alignment_int, |
| 72 | + kate_motion_semantics_text_alignment_ext, |
| 73 | + kate_motion_semantics_text_position, |
| 74 | + kate_motion_semantics_text_size, |
| 75 | + kate_motion_semantics_marker1_position, |
| 76 | + kate_motion_semantics_marker2_position, |
| 77 | + kate_motion_semantics_marker3_position, |
| 78 | + kate_motion_semantics_marker4_position, |
| 79 | + kate_motion_semantics_glyph_pointer_1, |
| 80 | + kate_motion_semantics_glyph_pointer_2, |
| 81 | + kate_motion_semantics_glyph_pointer_3, |
| 82 | + kate_motion_semantics_glyph_pointer_4, |
| 83 | + kate_motion_semantics_text_color_rg, |
| 84 | + kate_motion_semantics_text_color_ba, |
| 85 | + kate_motion_semantics_background_color_rg, |
| 86 | + kate_motion_semantics_background_color_ba, |
| 87 | + kate_motion_semantics_draw_color_rg, |
| 88 | + kate_motion_semantics_draw_color_ba, |
| 89 | + kate_motion_semantics_style_morph, |
| 90 | + kate_motion_semantics_text_path, |
| 91 | + kate_motion_semantics_text_path_section, |
| 92 | + kate_motion_semantics_draw, |
| 93 | + kate_motion_semantics_text_visible_section, |
| 94 | + kate_motion_semantics_horizontal_margins, |
| 95 | + kate_motion_semantics_vertical_margins, |
| 96 | + kate_motion_semantics_bitmap_position, |
| 97 | + kate_motion_semantics_bitmap_size, |
| 98 | + kate_motion_semantics_marker1_bitmap, |
| 99 | + kate_motion_semantics_marker2_bitmap, |
| 100 | + kate_motion_semantics_marker3_bitmap, |
| 101 | + kate_motion_semantics_marker4_bitmap, |
| 102 | + kate_motion_semantics_glyph_pointer_1_bitmap, |
| 103 | + kate_motion_semantics_glyph_pointer_2_bitmap, |
| 104 | + kate_motion_semantics_glyph_pointer_3_bitmap, |
| 105 | + kate_motion_semantics_glyph_pointer_4_bitmap, |
| 106 | + kate_motion_semantics_draw_width, |
| 107 | + }; |
| 108 | + |
| 109 | + private KateMotionSemantics() { |
| 110 | + } |
| 111 | + |
| 112 | + /** |
| 113 | + * Create a KateMotionSemantics object from an integer. |
| 114 | + */ |
| 115 | + public static KateMotionSemantics CreateMotionSemantics(int idx) throws KateException { |
| 116 | + if (idx < 0 || idx >= list.length) |
| 117 | + throw new KateException("Motion semantics "+idx+" out of bounds"); |
| 118 | + return list[idx]; |
| 119 | + } |
| 120 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/RLE.java |
— | — | @@ -0,0 +1,296 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +import com.jcraft.jogg.*; |
| 25 | + |
| 26 | +/** |
| 27 | + * RLE decoding routines. |
| 28 | + */ |
| 29 | +public class RLE |
| 30 | +{ |
| 31 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC = 4; |
| 32 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA = 3; |
| 33 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND = 3; |
| 34 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP = 6; |
| 35 | + private static final int KATE_RLE_RUN_LENGTH_BITS_DELTA = 6; |
| 36 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_START = 9; |
| 37 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_END = 8; |
| 38 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP_START = 8; |
| 39 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA_STOP = 3; |
| 40 | + private static final int KATE_RLE_RUN_LENGTH_BITS_DELTA_STOP = 5; |
| 41 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_ZERO = 8; |
| 42 | + private static final int KATE_RLE_RUN_LENGTH_BITS_BASIC_NON_ZERO = 3; |
| 43 | + |
| 44 | + private static final int KATE_RLE_TYPE_EMPTY = 0; |
| 45 | + private static final int KATE_RLE_TYPE_BASIC = 1; |
| 46 | + private static final int KATE_RLE_TYPE_DELTA = 2; |
| 47 | + private static final int KATE_RLE_TYPE_BASIC_STOP = 3; |
| 48 | + private static final int KATE_RLE_TYPE_BASIC_STARTEND = 4; |
| 49 | + private static final int KATE_RLE_TYPE_DELTA_STOP = 5; |
| 50 | + private static final int KATE_RLE_TYPE_BASIC_ZERO = 6; |
| 51 | + |
| 52 | + private static final int KATE_RLE_TYPE_BITS = 3; |
| 53 | + |
| 54 | + private static int decodeLineEmpty(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 55 | + { |
| 56 | + for (int n=0; n<width; ++n) |
| 57 | + pixels[offset+n] = zero; |
| 58 | + return 0; |
| 59 | + } |
| 60 | + |
| 61 | + private static int decodeLineBasic(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 62 | + { |
| 63 | + final int run_length_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC; |
| 64 | + int p = 0; |
| 65 | + int count = width; |
| 66 | + while (count > 0) { |
| 67 | + int run_length = 1+opb.read(run_length_bits); |
| 68 | + if (run_length == 0 || run_length > count) |
| 69 | + return -1; |
| 70 | + byte value = (byte)opb.read(bits); |
| 71 | + for (int n=0; n<run_length; ++n) |
| 72 | + pixels[offset+p++] = value; |
| 73 | + count -= run_length; |
| 74 | + } |
| 75 | + return 0; |
| 76 | + } |
| 77 | + |
| 78 | + private static int decodeLineDelta(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 79 | + { |
| 80 | + final int run_length_delta_bits = KATE_RLE_RUN_LENGTH_BITS_DELTA; |
| 81 | + final int run_length_basic_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA; |
| 82 | + int p = 0; |
| 83 | + int count = width; |
| 84 | + while (count > 0) { |
| 85 | + int type = opb.read1(); |
| 86 | + if (type != 0) { |
| 87 | + int run_length = 1+opb.read(run_length_delta_bits); |
| 88 | + if (run_length == 0 || run_length > count) |
| 89 | + return -1; |
| 90 | + if (offset > 0) { |
| 91 | + for (int n=0; n<run_length; ++n) { |
| 92 | + pixels[offset+p] = pixels[offset+p-width]; |
| 93 | + ++p; |
| 94 | + } |
| 95 | + } |
| 96 | + else { |
| 97 | + for (int n=0; n<run_length; ++n) |
| 98 | + pixels[offset+p++] = zero; |
| 99 | + } |
| 100 | + count -= run_length; |
| 101 | + } |
| 102 | + else { |
| 103 | + int run_length = 1 + opb.read(run_length_basic_bits); |
| 104 | + if (run_length == 0 || run_length > count) |
| 105 | + return -1; |
| 106 | + byte value = (byte)opb.read(bits); |
| 107 | + for (int n=0; n<run_length; ++n) |
| 108 | + pixels[offset+p++] = value; |
| 109 | + count -= run_length; |
| 110 | + } |
| 111 | + } |
| 112 | + return 0; |
| 113 | + } |
| 114 | + |
| 115 | + private static int decodeLineBasicStartEnd(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 116 | + { |
| 117 | + final int run_length_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND; |
| 118 | + int run_length; |
| 119 | + int count = width; |
| 120 | + int p = 0; |
| 121 | + |
| 122 | + run_length = opb.read(KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_START); |
| 123 | + if (run_length > 0) { |
| 124 | + if (run_length > count) |
| 125 | + return -1; |
| 126 | + for (int n=0; n<run_length; ++n) |
| 127 | + pixels[offset+p++] = zero; |
| 128 | + count -= run_length; |
| 129 | + } |
| 130 | + |
| 131 | + run_length = opb.read(KATE_RLE_RUN_LENGTH_BITS_BASIC_STARTEND_END); |
| 132 | + if (run_length > 0) { |
| 133 | + if (run_length > count) |
| 134 | + return -1; |
| 135 | + for (int n=0; n<run_length; ++n) |
| 136 | + pixels[offset+width-1-n] = zero; |
| 137 | + count -= run_length; |
| 138 | + } |
| 139 | + |
| 140 | + while (count > 0) { |
| 141 | + run_length = 1 + opb.read(run_length_bits); |
| 142 | + if (run_length == 0 || run_length > count) |
| 143 | + return -1; |
| 144 | + byte value = (byte)opb.read(bits); |
| 145 | + for (int n=0; n<run_length; ++n) |
| 146 | + pixels[offset+p++] = value; |
| 147 | + count -= run_length; |
| 148 | + } |
| 149 | + |
| 150 | + return 0; |
| 151 | + } |
| 152 | + |
| 153 | + private static int decodeLineBasicStop(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 154 | + { |
| 155 | + final int run_length_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP; |
| 156 | + int run_length; |
| 157 | + int count = width; |
| 158 | + int p = 0; |
| 159 | + |
| 160 | + run_length = opb.read(KATE_RLE_RUN_LENGTH_BITS_BASIC_STOP_START); |
| 161 | + if (run_length > 0) { |
| 162 | + if (run_length > count) |
| 163 | + return -1; |
| 164 | + for (int n=0; n<run_length; ++n) |
| 165 | + pixels[offset+p++] = zero; |
| 166 | + count -= run_length; |
| 167 | + } |
| 168 | + |
| 169 | + while (count > 0) { |
| 170 | + run_length = opb.read(run_length_bits); |
| 171 | + if (run_length > count) |
| 172 | + return -1; |
| 173 | + if (run_length == 0) { |
| 174 | + for (int n=0; n<run_length; ++n) |
| 175 | + pixels[offset+p++] = zero; |
| 176 | + break; |
| 177 | + } |
| 178 | + byte value = (byte)opb.read(bits); |
| 179 | + for (int n=0; n<run_length; ++n) |
| 180 | + pixels[offset+p++] = value; |
| 181 | + count -= run_length; |
| 182 | + } |
| 183 | + |
| 184 | + return 0; |
| 185 | + } |
| 186 | + |
| 187 | + private static int decodeLineDeltaStop(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 188 | + { |
| 189 | + final int run_length_delta_bits = KATE_RLE_RUN_LENGTH_BITS_DELTA_STOP; |
| 190 | + final int run_length_basic_bits = KATE_RLE_RUN_LENGTH_BITS_BASIC_IN_DELTA_STOP; |
| 191 | + int run_length; |
| 192 | + int count = width; |
| 193 | + int p = 0; |
| 194 | + |
| 195 | + while (count > 0) { |
| 196 | + int type = opb.read1(); |
| 197 | + if (type != 0) { |
| 198 | + run_length = 1 + opb.read(run_length_delta_bits); |
| 199 | + if (run_length == 0 || run_length > count) |
| 200 | + return -1; |
| 201 | + if (offset > 0) { |
| 202 | + for (int n=0; n<run_length; ++n) { |
| 203 | + pixels[offset+p] = pixels[offset+p-width]; |
| 204 | + ++p; |
| 205 | + } |
| 206 | + } |
| 207 | + else { |
| 208 | + for (int n=0; n<run_length; ++n) |
| 209 | + pixels[offset+p++] = zero; |
| 210 | + } |
| 211 | + } |
| 212 | + else { |
| 213 | + run_length = opb.read(run_length_basic_bits); |
| 214 | + if (run_length == 0) { |
| 215 | + for (int n=0; n<run_length; ++n) |
| 216 | + pixels[offset+p++] = zero; |
| 217 | + break; |
| 218 | + } |
| 219 | + if (run_length > count) |
| 220 | + return -1; |
| 221 | + byte value = (byte)opb.read(bits); |
| 222 | + for (int n=0; n<run_length; ++n) |
| 223 | + pixels[offset+p++] = value; |
| 224 | + } |
| 225 | + count -= run_length; |
| 226 | + } |
| 227 | + |
| 228 | + return 0; |
| 229 | + } |
| 230 | + |
| 231 | + private static int decodeLineBasicZero(Buffer opb, int width, byte pixels[], int offset, int bits, byte zero) |
| 232 | + { |
| 233 | + final int run_length_bits_zero = KATE_RLE_RUN_LENGTH_BITS_BASIC_ZERO; |
| 234 | + final int run_length_bits_non_zero = KATE_RLE_RUN_LENGTH_BITS_BASIC_NON_ZERO; |
| 235 | + int run_length; |
| 236 | + int count = width; |
| 237 | + int p = 0; |
| 238 | + |
| 239 | + while (count > 0) { |
| 240 | + byte value = (byte)opb.read(bits); |
| 241 | + if (value == zero) { |
| 242 | + run_length = 1 + opb.read(run_length_bits_zero); |
| 243 | + } |
| 244 | + else { |
| 245 | + run_length = 1 + opb.read(run_length_bits_non_zero); |
| 246 | + } |
| 247 | + if (run_length == 0 || run_length > count) |
| 248 | + return -1; |
| 249 | + for (int n=0; n<run_length; ++n) |
| 250 | + pixels[offset+p++] = value; |
| 251 | + count -= run_length; |
| 252 | + } |
| 253 | + |
| 254 | + return 0; |
| 255 | + } |
| 256 | + |
| 257 | + public static byte[] decodeRLE(Buffer opb, int width, int height, int bpp) |
| 258 | + { |
| 259 | + byte[] pixels = new byte[width*height]; |
| 260 | + int offset = 0; |
| 261 | + int ret; |
| 262 | + byte zero = (byte)opb.read(bpp); |
| 263 | + while (height > 0) { |
| 264 | + int type = opb.read(KATE_RLE_TYPE_BITS); |
| 265 | + switch (type) { |
| 266 | + case KATE_RLE_TYPE_EMPTY: |
| 267 | + ret = decodeLineEmpty(opb, width, pixels, offset, bpp, zero); |
| 268 | + break; |
| 269 | + case KATE_RLE_TYPE_DELTA: |
| 270 | + ret = decodeLineDelta(opb, width, pixels, offset, bpp, zero); |
| 271 | + break; |
| 272 | + case KATE_RLE_TYPE_BASIC: |
| 273 | + ret = decodeLineBasic(opb, width, pixels, offset, bpp, zero); |
| 274 | + break; |
| 275 | + case KATE_RLE_TYPE_BASIC_STARTEND: |
| 276 | + ret = decodeLineBasicStartEnd(opb, width, pixels, offset, bpp, zero); |
| 277 | + break; |
| 278 | + case KATE_RLE_TYPE_BASIC_STOP: |
| 279 | + ret = decodeLineBasicStop(opb, width, pixels, offset, bpp, zero); |
| 280 | + break; |
| 281 | + case KATE_RLE_TYPE_DELTA_STOP: |
| 282 | + ret = decodeLineDeltaStop(opb, width, pixels, offset, bpp, zero); |
| 283 | + break; |
| 284 | + case KATE_RLE_TYPE_BASIC_ZERO: |
| 285 | + ret = decodeLineBasicZero(opb, width, pixels, offset, bpp, zero); |
| 286 | + break; |
| 287 | + default: |
| 288 | + return null; |
| 289 | + } |
| 290 | + if (ret != 0) |
| 291 | + return null; |
| 292 | + offset += width; |
| 293 | + --height; |
| 294 | + } |
| 295 | + return pixels; |
| 296 | + } |
| 297 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/FontMapping.java |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A set of ranges defining a mapping from code points to bitmaps. |
| 26 | + */ |
| 27 | +class FontMapping |
| 28 | +{ |
| 29 | + FontRange ranges[]; |
| 30 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Region.java |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A region definition, for placement of text/images. |
| 26 | + */ |
| 27 | +public class Region |
| 28 | +{ |
| 29 | + public KateSpaceMetric metric; |
| 30 | + public int x; |
| 31 | + public int y; |
| 32 | + public int w; |
| 33 | + public int h; |
| 34 | + public int style; |
| 35 | + public boolean clip; |
| 36 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateWrapMode.java |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateWrapMode { |
| 25 | + public static final KateWrapMode kate_wrap_word = new KateWrapMode (); |
| 26 | + public static final KateWrapMode kate_wrap_none = new KateWrapMode (); |
| 27 | + |
| 28 | + private static final KateWrapMode[] list = { |
| 29 | + kate_wrap_word, |
| 30 | + kate_wrap_none, |
| 31 | + }; |
| 32 | + |
| 33 | + private KateWrapMode() { |
| 34 | + } |
| 35 | + |
| 36 | + /** |
| 37 | + * Create a KateWrapMode object from an integer. |
| 38 | + */ |
| 39 | + public static KateWrapMode CreateWrapMode(int idx) throws KateException { |
| 40 | + if (idx < 0 || idx >= list.length) |
| 41 | + throw new KateException("Wrap mode "+idx+" out of bounds"); |
| 42 | + return list[idx]; |
| 43 | + } |
| 44 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Decode.java |
— | — | @@ -0,0 +1,238 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +import com.jcraft.jogg.*; |
| 25 | +import com.fluendo.utils.*; |
| 26 | + |
| 27 | +public final class Decode { |
| 28 | + |
| 29 | + Buffer opb = new Buffer(); |
| 30 | + Info info; |
| 31 | + |
| 32 | + public Decode (Info i) { |
| 33 | + info = i; |
| 34 | + } |
| 35 | + |
| 36 | + /** |
| 37 | + * Decode a text data packet (packet type 0x00), and fills the passed event |
| 38 | + * from the decoded data. |
| 39 | + */ |
| 40 | + int decodeTextPacket(Event ev) |
| 41 | + { |
| 42 | + ev.ki = info; |
| 43 | + |
| 44 | + ev.start = Bitwise.read64(opb); |
| 45 | + ev.duration = Bitwise.read64(opb); |
| 46 | + ev.backlink = Bitwise.read64(opb); |
| 47 | + |
| 48 | + ev.start_time = granuleDuration(ev.start); |
| 49 | + ev.end_time = ev.start_time+granuleDuration(ev.duration); |
| 50 | + |
| 51 | + /* text */ |
| 52 | + int len = Bitwise.read32(opb); |
| 53 | + ev.text = new byte[len]; |
| 54 | + Bitwise.readbuf(opb, ev.text, len); |
| 55 | + |
| 56 | + /* event ID */ |
| 57 | + ev.id = -1; |
| 58 | + if (opb.read1() != 0) { |
| 59 | + ev.id = Bitwise.read32v(opb); |
| 60 | + } |
| 61 | + |
| 62 | + /* motions */ |
| 63 | + ev.motions = null; |
| 64 | + if (opb.read1() != 0) { |
| 65 | + int nmotions = Bitwise.read32v(opb); |
| 66 | + if (nmotions < 0) |
| 67 | + return -1; |
| 68 | + ev.motions = new Motion[nmotions]; |
| 69 | + for (int n=0; n<nmotions; ++n) { |
| 70 | + if (opb.read1() != 0) { |
| 71 | + int idx = Bitwise.read32v(opb); |
| 72 | + if (idx < 0 || idx >= info.motions.length) |
| 73 | + return -1; |
| 74 | + ev.motions[n] = info.motions[idx]; |
| 75 | + } |
| 76 | + else { |
| 77 | + try { |
| 78 | + ev.motions[n] = info.unpackMotion(opb); |
| 79 | + } |
| 80 | + catch (KateException ke) { |
| 81 | + return Result.KATE_E_BAD_PACKET; |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + } |
| 86 | + |
| 87 | + /* overrides */ |
| 88 | + if (opb.read1() != 0) { |
| 89 | + try { |
| 90 | + if (opb.read1() != 0) |
| 91 | + ev.text_encoding = KateTextEncoding.CreateTextEncoding(opb.read(8)); |
| 92 | + if (opb.read1() != 0) |
| 93 | + ev.text_directionality = KateTextDirectionality.CreateTextDirectionality(opb.read(8)); |
| 94 | + } |
| 95 | + catch (KateException ke) { |
| 96 | + return Result.KATE_E_BAD_PACKET; |
| 97 | + } |
| 98 | + |
| 99 | + /* language override */ |
| 100 | + if (opb.read1() != 0) { |
| 101 | + int nbytes = Bitwise.read32v(opb); |
| 102 | + if (nbytes < 0) |
| 103 | + return Result.KATE_E_BAD_PACKET; |
| 104 | + if (nbytes > 0) { |
| 105 | + ev.language=new byte[nbytes]; |
| 106 | + Bitwise.readbuf(opb, ev.language, nbytes); |
| 107 | + } |
| 108 | + } |
| 109 | + |
| 110 | + /* region override */ |
| 111 | + if (opb.read1() != 0) { |
| 112 | + int idx = Bitwise.read32v(opb); |
| 113 | + if (idx < 0 || idx >= info.regions.length) |
| 114 | + return Result.KATE_E_BAD_PACKET; |
| 115 | + ev.kr = info.regions[idx]; |
| 116 | + } |
| 117 | + if (opb.read1() != 0) { |
| 118 | + try { |
| 119 | + ev.kr = info.unpackRegion(opb); |
| 120 | + } |
| 121 | + catch (KateException ke) { |
| 122 | + return Result.KATE_E_BAD_PACKET; |
| 123 | + } |
| 124 | + } |
| 125 | + |
| 126 | + /* style override */ |
| 127 | + if (opb.read1() != 0) { |
| 128 | + int idx = Bitwise.read32v(opb); |
| 129 | + if (idx < 0 || idx >= info.styles.length) |
| 130 | + return Result.KATE_E_BAD_PACKET; |
| 131 | + ev.ks = info.styles[idx]; |
| 132 | + } |
| 133 | + if (opb.read1() != 0) { |
| 134 | + try { |
| 135 | + ev.ks = info.unpackStyle(opb); |
| 136 | + } |
| 137 | + catch (KateException ke) { |
| 138 | + return Result.KATE_E_BAD_PACKET; |
| 139 | + } |
| 140 | + } |
| 141 | + if (opb.read1() != 0) { |
| 142 | + int idx = Bitwise.read32v(opb); |
| 143 | + if (idx < 0 || idx >= info.styles.length) |
| 144 | + return Result.KATE_E_BAD_PACKET; |
| 145 | + ev.ks2 = info.styles[idx]; |
| 146 | + } |
| 147 | + if (opb.read1() != 0) { |
| 148 | + try { |
| 149 | + ev.ks2 = info.unpackStyle(opb); |
| 150 | + } |
| 151 | + catch (KateException ke) { |
| 152 | + return Result.KATE_E_BAD_PACKET; |
| 153 | + } |
| 154 | + } |
| 155 | + |
| 156 | + /* font mapping */ |
| 157 | + if (opb.read1() != 0) { |
| 158 | + int idx = Bitwise.read32v(opb); |
| 159 | + if (idx < 0 || idx >= info.font_mappings.length) |
| 160 | + return Result.KATE_E_BAD_PACKET; |
| 161 | + ev.font_mapping = info.font_mappings[idx]; |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + /* new in 0.2: palettes/bitmaps/markup type */ |
| 166 | + if (((info.bitstream_version_major<<8) | info.bitstream_version_minor) >= 0x0002) { |
| 167 | + Bitwise.read32v(opb); |
| 168 | + if (opb.read1() != 0) { |
| 169 | + if (opb.read1() != 0) { |
| 170 | + int idx = Bitwise.read32v(opb); |
| 171 | + if (idx < 0 || idx >= info.palettes.length) |
| 172 | + return Result.KATE_E_BAD_PACKET; |
| 173 | + ev.palette = info.palettes[idx]; |
| 174 | + } |
| 175 | + if (opb.read1() != 0) { |
| 176 | + try { |
| 177 | + ev.palette = info.unpackPalette(opb); |
| 178 | + } |
| 179 | + catch (KateException e) { |
| 180 | + return Result.KATE_E_BAD_PACKET; |
| 181 | + } |
| 182 | + } |
| 183 | + if (opb.read1() != 0) { |
| 184 | + int idx = Bitwise.read32v(opb); |
| 185 | + if (idx < 0 || idx >= info.bitmaps.length) |
| 186 | + return Result.KATE_E_BAD_PACKET; |
| 187 | + ev.bitmap = info.bitmaps[idx]; |
| 188 | + } |
| 189 | + if (opb.read1() != 0) { |
| 190 | + try { |
| 191 | + ev.bitmap = info.unpackBitmap(opb); |
| 192 | + } |
| 193 | + catch (KateException e) { |
| 194 | + return Result.KATE_E_BAD_PACKET; |
| 195 | + } |
| 196 | + } |
| 197 | + if (opb.read1() != 0) { |
| 198 | + try { |
| 199 | + ev.markup_type = KateMarkupType.CreateMarkupType(opb.read(8)); |
| 200 | + } |
| 201 | + catch (KateException e) { |
| 202 | + return Result.KATE_E_BAD_PACKET; |
| 203 | + } |
| 204 | + } |
| 205 | + } |
| 206 | + } |
| 207 | + |
| 208 | +// TODO: remainder |
| 209 | + return 0; |
| 210 | + } |
| 211 | + |
| 212 | + /** |
| 213 | + * Convert a granule to a time. |
| 214 | + */ |
| 215 | + public double granuleTime(long granulepos) |
| 216 | + { |
| 217 | + if(granulepos>=0){ |
| 218 | + long base=granulepos>>info.granule_shift; |
| 219 | + long offset=granulepos-(base<<info.granule_shift); |
| 220 | + |
| 221 | + return (base+offset)* |
| 222 | + ((double)info.gps_denominator/info.gps_numerator); |
| 223 | + } |
| 224 | + return(-1); |
| 225 | + } |
| 226 | + |
| 227 | + /** |
| 228 | + * Convert a time in granule units to a duration. |
| 229 | + */ |
| 230 | + public double granuleDuration(long granule) |
| 231 | + { |
| 232 | + if(granule>=0){ |
| 233 | + return (granule)* |
| 234 | + ((double)info.gps_denominator/info.gps_numerator); |
| 235 | + } |
| 236 | + return(-1); |
| 237 | + } |
| 238 | + |
| 239 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/FontRange.java |
— | — | @@ -0,0 +1,32 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A code point range mapping to a set of bitmaps. |
| 26 | + */ |
| 27 | +public class FontRange |
| 28 | +{ |
| 29 | + int first_code_point; |
| 30 | + int last_code_point; |
| 31 | + int first_bitmap; |
| 32 | +} |
| 33 | + |
Index: trunk/cortado/src/com/fluendo/jkate/KateBitmapType.java |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateBitmapType { |
| 25 | + public static final KateBitmapType kate_bitmap_type_paletted = new KateBitmapType (); |
| 26 | + public static final KateBitmapType kate_bitmap_type_png = new KateBitmapType (); |
| 27 | + |
| 28 | + private static final KateBitmapType[] list = { |
| 29 | + kate_bitmap_type_paletted, |
| 30 | + kate_bitmap_type_png, |
| 31 | + }; |
| 32 | + |
| 33 | + private KateBitmapType() { |
| 34 | + } |
| 35 | + |
| 36 | + /** |
| 37 | + * Create a KateBitmapType object from an integer. |
| 38 | + */ |
| 39 | + public static KateBitmapType CreateBitmapType(int idx) throws KateException { |
| 40 | + if (idx < 0 || idx >= list.length) |
| 41 | + throw new KateException("Bitmap type "+idx+" out of bounds"); |
| 42 | + return list[idx]; |
| 43 | + } |
| 44 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Curve.java |
— | — | @@ -0,0 +1,31 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A curve definition, splines, segments, etc. |
| 26 | + */ |
| 27 | +public class Curve |
| 28 | +{ |
| 29 | + public KateCurveType type; |
| 30 | + public int npts; |
| 31 | + public double pts[][]; |
| 32 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateMotionMapping.java |
— | — | @@ -0,0 +1,51 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateMotionMapping { |
| 25 | + public static final KateMotionMapping kate_motion_mapping_none = new KateMotionMapping (); |
| 26 | + public static final KateMotionMapping kate_motion_mapping_frame = new KateMotionMapping (); |
| 27 | + public static final KateMotionMapping kate_motion_mapping_window = new KateMotionMapping (); |
| 28 | + public static final KateMotionMapping kate_motion_mapping_region = new KateMotionMapping (); |
| 29 | + public static final KateMotionMapping kate_motion_mapping_event_duration = new KateMotionMapping (); |
| 30 | + public static final KateMotionMapping kate_motion_mapping_bitmap_size = new KateMotionMapping (); |
| 31 | + |
| 32 | + private static final KateMotionMapping[] list = { |
| 33 | + kate_motion_mapping_none, |
| 34 | + kate_motion_mapping_frame, |
| 35 | + kate_motion_mapping_window, |
| 36 | + kate_motion_mapping_region, |
| 37 | + kate_motion_mapping_event_duration, |
| 38 | + kate_motion_mapping_bitmap_size, |
| 39 | + }; |
| 40 | + |
| 41 | + private KateMotionMapping() { |
| 42 | + } |
| 43 | + |
| 44 | + /** |
| 45 | + * Create a KateMotionMapping object from an integer. |
| 46 | + */ |
| 47 | + public static KateMotionMapping CreateMotionMapping(int idx) throws KateException { |
| 48 | + if (idx < 0 || idx >= list.length) |
| 49 | + throw new KateException("Motion mapping "+idx+" out of bounds"); |
| 50 | + return list[idx]; |
| 51 | + } |
| 52 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateCurveType.java |
— | — | @@ -0,0 +1,51 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateCurveType { |
| 25 | + public static final KateCurveType kate_curve_none = new KateCurveType (); |
| 26 | + public static final KateCurveType kate_curve_static = new KateCurveType (); |
| 27 | + public static final KateCurveType kate_curve_linear = new KateCurveType (); |
| 28 | + public static final KateCurveType kate_curve_catmull_rom_spline = new KateCurveType (); |
| 29 | + public static final KateCurveType kate_curve_bezier_cubic_spline = new KateCurveType (); |
| 30 | + public static final KateCurveType kate_curve_bspline = new KateCurveType (); |
| 31 | + |
| 32 | + private static final KateCurveType[] list = { |
| 33 | + kate_curve_none, |
| 34 | + kate_curve_static, |
| 35 | + kate_curve_linear, |
| 36 | + kate_curve_catmull_rom_spline, |
| 37 | + kate_curve_bezier_cubic_spline, |
| 38 | + kate_curve_bspline, |
| 39 | + }; |
| 40 | + |
| 41 | + private KateCurveType() { |
| 42 | + } |
| 43 | + |
| 44 | + /** |
| 45 | + * Create a KateCurveType object from an integer. |
| 46 | + */ |
| 47 | + public static KateCurveType CreateCurveType(int idx) throws KateException { |
| 48 | + if (idx < 0 || idx >= list.length) |
| 49 | + throw new KateException("Curve type "+idx+" out of bounds"); |
| 50 | + return list[idx]; |
| 51 | + } |
| 52 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Info.java |
— | — | @@ -0,0 +1,742 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +import com.jcraft.jogg.*; |
| 25 | +import com.fluendo.utils.*; |
| 26 | + |
| 27 | +public class Info { |
| 28 | + public int bitstream_version_major = -1; |
| 29 | + public int bitstream_version_minor = -1; |
| 30 | + public KateTextEncoding text_encoding; |
| 31 | + public KateTextDirectionality text_directionality; |
| 32 | + public int num_headers = 0; |
| 33 | + public int granule_shift; |
| 34 | + public int gps_numerator; |
| 35 | + public int gps_denominator; |
| 36 | + public byte language[]; |
| 37 | + public byte category[]; |
| 38 | + public Region regions[]; |
| 39 | + public Style styles[]; |
| 40 | + public Curve curves[]; |
| 41 | + public Motion motions[]; |
| 42 | + public Palette palettes[]; |
| 43 | + public Bitmap bitmaps[]; |
| 44 | + public FontRange font_ranges[]; |
| 45 | + public FontMapping font_mappings[]; |
| 46 | + |
| 47 | + public KateMarkupType markup_type; |
| 48 | + public int original_canvas_width; |
| 49 | + public int original_canvas_height; |
| 50 | + |
| 51 | + /* used to track which header we need to decode next */ |
| 52 | + private int probe = 0; |
| 53 | + |
| 54 | + /** |
| 55 | + * Read a packet canvas size (width or height). |
| 56 | + * Format defined in the Kate specification. |
| 57 | + */ |
| 58 | + private static int read_canvas_size(Buffer opb) |
| 59 | + { |
| 60 | + int value, base, shift; |
| 61 | + |
| 62 | + value = opb.read(8) | (opb.read(8)<<8); |
| 63 | + base = value>>4; |
| 64 | + shift = value&15; |
| 65 | + return base<<shift; |
| 66 | + } |
| 67 | + |
| 68 | + /** |
| 69 | + * Decodes a Kate info header packet and fills the class data with |
| 70 | + * what was found in it. |
| 71 | + */ |
| 72 | + private int unpackInfo(Buffer opb){ |
| 73 | + int reserved, tmp; |
| 74 | + |
| 75 | + bitstream_version_major = (byte)opb.read(8); |
| 76 | + bitstream_version_minor = (byte)opb.read(8); |
| 77 | + Debug.info("Kate bitstream v"+bitstream_version_major+"."+bitstream_version_minor); |
| 78 | + |
| 79 | + if (bitstream_version_major > 0) |
| 80 | + return Result.KATE_E_VERSION; |
| 81 | + |
| 82 | + num_headers = (int)opb.read(8); |
| 83 | + if (num_headers < 1) |
| 84 | + return Result.KATE_E_BAD_PACKET; |
| 85 | + tmp = opb.read(8); |
| 86 | + if (tmp != 0) |
| 87 | + return Result.KATE_E_BAD_PACKET; |
| 88 | + try { |
| 89 | + text_encoding = KateTextEncoding.CreateTextEncoding(tmp); |
| 90 | + text_directionality = KateTextDirectionality.CreateTextDirectionality(opb.read(8)); |
| 91 | + } |
| 92 | + catch (KateException e) { |
| 93 | + return Result.KATE_E_BAD_PACKET; |
| 94 | + } |
| 95 | + reserved = opb.read(8); |
| 96 | + if (bitstream_version_major==0 && bitstream_version_minor<3) { |
| 97 | + if (reserved != 0) |
| 98 | + return Result.KATE_E_BAD_PACKET; |
| 99 | + } |
| 100 | + granule_shift = opb.read(8); |
| 101 | + |
| 102 | + original_canvas_width = read_canvas_size(opb); |
| 103 | + original_canvas_height = read_canvas_size(opb); |
| 104 | + |
| 105 | + reserved = Bitwise.read32(opb); |
| 106 | + if (bitstream_version_major==0 && bitstream_version_minor<3) { |
| 107 | + if (reserved != 0) |
| 108 | + return Result.KATE_E_BAD_PACKET; |
| 109 | + } |
| 110 | + |
| 111 | + gps_numerator = Bitwise.read32(opb); |
| 112 | + gps_denominator = Bitwise.read32(opb); |
| 113 | + |
| 114 | + if (granule_shift >= 64) |
| 115 | + return Result.KATE_E_BAD_PACKET; |
| 116 | + if (gps_numerator == 0 || gps_denominator == 0) |
| 117 | + return Result.KATE_E_BAD_PACKET; |
| 118 | + |
| 119 | + language=new byte[16]; |
| 120 | + Bitwise.readbuf(opb, language, 16); |
| 121 | + if (language[15] != 0) |
| 122 | + return Result.KATE_E_BAD_PACKET; |
| 123 | + |
| 124 | + category=new byte[16]; |
| 125 | + Bitwise.readbuf(opb, category, 16); |
| 126 | + if (category[15] != 0) |
| 127 | + return Result.KATE_E_BAD_PACKET; |
| 128 | + |
| 129 | + /* end of packet */ |
| 130 | + if (opb.read(1) != -1) |
| 131 | + return (Result.KATE_E_BAD_PACKET); |
| 132 | + |
| 133 | + return(0); |
| 134 | + } |
| 135 | + |
| 136 | + /** |
| 137 | + * Checks that we have reached the end of the packet. |
| 138 | + */ |
| 139 | + static int checkEOP(Buffer opb) { |
| 140 | + int bits = 7 & (8 - (opb.bits()&7)); |
| 141 | + if (bits > 0) { |
| 142 | + if (opb.read(bits) != 0) |
| 143 | + return Result.KATE_E_BAD_PACKET; |
| 144 | + } |
| 145 | + if (opb.look1() != -1) |
| 146 | + return (Result.KATE_E_BAD_PACKET); |
| 147 | + return 0; |
| 148 | + } |
| 149 | + |
| 150 | + /** |
| 151 | + * Decodes a Vorbis comment packet. |
| 152 | + * straight copy of the jheora one |
| 153 | + */ |
| 154 | + private int unpackComment (Comment kc, Buffer opb) |
| 155 | + { |
| 156 | + int i; |
| 157 | + int len; |
| 158 | + byte[] tmp; |
| 159 | + int comments; |
| 160 | + |
| 161 | + len = Bitwise.read32(opb); |
| 162 | + if(len<0) |
| 163 | + return(Result.KATE_E_BAD_PACKET); |
| 164 | + |
| 165 | + tmp=new byte[len]; |
| 166 | + Bitwise.readbuf(opb, tmp, len); |
| 167 | + kc.vendor=new String(tmp); |
| 168 | + |
| 169 | + comments = Bitwise.read32(opb); |
| 170 | + if(comments<0) { |
| 171 | + kc.clear(); |
| 172 | + return Result.KATE_E_BAD_PACKET; |
| 173 | + } |
| 174 | + kc.user_comments=new String[comments]; |
| 175 | + for(i=0;i<comments;i++){ |
| 176 | + len = Bitwise.read32(opb); |
| 177 | + if(len<0) { |
| 178 | + kc.clear(); |
| 179 | + return Result.KATE_E_BAD_PACKET; |
| 180 | + } |
| 181 | + |
| 182 | + tmp=new byte[len]; |
| 183 | + Bitwise.readbuf(opb,tmp,len); |
| 184 | + kc.user_comments[i]=new String(tmp); |
| 185 | + } |
| 186 | + return 0; |
| 187 | + } |
| 188 | + |
| 189 | + /** |
| 190 | + * Decode a single region. |
| 191 | + */ |
| 192 | + public Region unpackRegion (Buffer opb) throws KateException |
| 193 | + { |
| 194 | + Region kr = new Region(); |
| 195 | + |
| 196 | + kr.metric = KateSpaceMetric.CreateSpaceMetric(opb.read(8)); |
| 197 | + kr.x = Bitwise.read32v(opb); |
| 198 | + kr.y = Bitwise.read32v(opb); |
| 199 | + kr.w = Bitwise.read32v(opb); |
| 200 | + kr.h = Bitwise.read32v(opb); |
| 201 | + kr.style = Bitwise.read32v(opb); |
| 202 | + |
| 203 | + if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0002) { |
| 204 | + Bitwise.read32v(opb); |
| 205 | + kr.clip = (opb.read1() != 0); |
| 206 | + } |
| 207 | + else { |
| 208 | + kr.clip = false; |
| 209 | + } |
| 210 | + |
| 211 | + Bitwise.skipWarp(opb); |
| 212 | + |
| 213 | + return kr; |
| 214 | + } |
| 215 | + |
| 216 | + /** |
| 217 | + * Decode the regions header packet. |
| 218 | + */ |
| 219 | + private int unpackRegions (Buffer opb) |
| 220 | + { |
| 221 | + int nregions = Bitwise.read32v(opb); |
| 222 | + if (nregions < 0) return Result.KATE_E_BAD_PACKET; |
| 223 | + regions = new Region[nregions]; |
| 224 | + for (int n=0; n<nregions; ++n) { |
| 225 | + try { |
| 226 | + regions[n] = unpackRegion(opb); |
| 227 | + } |
| 228 | + catch (KateException ke) { |
| 229 | + regions = null; |
| 230 | + return Result.KATE_E_BAD_PACKET; |
| 231 | + } |
| 232 | + } |
| 233 | + |
| 234 | + Bitwise.skipWarp(opb); |
| 235 | + |
| 236 | + /* end of packet */ |
| 237 | + return checkEOP(opb); |
| 238 | + } |
| 239 | + |
| 240 | + /** |
| 241 | + * Decode a color. |
| 242 | + */ |
| 243 | + private Color unpackColor (Buffer opb) |
| 244 | + { |
| 245 | + Color color = new Color(); |
| 246 | + color.r = (byte)opb.read(8); |
| 247 | + color.g = (byte)opb.read(8); |
| 248 | + color.b = (byte)opb.read(8); |
| 249 | + color.a = (byte)opb.read(8); |
| 250 | + return color; |
| 251 | + } |
| 252 | + |
| 253 | + /** |
| 254 | + * Decode a single style. |
| 255 | + */ |
| 256 | + public Style unpackStyle (Buffer opb) throws KateException |
| 257 | + { |
| 258 | + Style ks = new Style(); |
| 259 | + |
| 260 | + double floats[][] = Bitwise.readFloats(opb, 8, 1); |
| 261 | + int idx = 0; |
| 262 | + ks.halign = floats[0][idx++]; |
| 263 | + ks.valign = floats[0][idx++]; |
| 264 | + ks.font_width = floats[0][idx++]; |
| 265 | + ks.font_height = floats[0][idx++]; |
| 266 | + ks.left_margin = floats[0][idx++]; |
| 267 | + ks.top_margin = floats[0][idx++]; |
| 268 | + ks.right_margin = floats[0][idx++]; |
| 269 | + ks.bottom_margin = floats[0][idx++]; |
| 270 | + ks.text_color = unpackColor(opb); |
| 271 | + ks.background_color = unpackColor(opb); |
| 272 | + ks.draw_color = unpackColor(opb); |
| 273 | + ks.font_metric = KateSpaceMetric.CreateSpaceMetric(opb.read(8)); |
| 274 | + ks.margin_metric = KateSpaceMetric.CreateSpaceMetric(opb.read(8)); |
| 275 | + ks.bold = opb.read1() != 0; |
| 276 | + ks.italics = opb.read1() != 0; |
| 277 | + ks.underline = opb.read1() != 0; |
| 278 | + ks.strike = opb.read1() != 0; |
| 279 | + |
| 280 | + if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0002) { |
| 281 | + Bitwise.read32v(opb); |
| 282 | + ks.justify = opb.read1() != 0; |
| 283 | + int len = Bitwise.read32v(opb); |
| 284 | + if (len < 0) |
| 285 | + throw new KateBadPacketException(); |
| 286 | + byte s[] = new byte[len]; |
| 287 | + Bitwise.readbuf(opb, s, len); |
| 288 | + ks.font = new String(s); |
| 289 | + } |
| 290 | + else { |
| 291 | + ks.justify = false; |
| 292 | + ks.font = null; |
| 293 | + } |
| 294 | + |
| 295 | + if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0004) { |
| 296 | + Bitwise.read32v(opb); |
| 297 | + ks.wrap_mode = KateWrapMode.CreateWrapMode(Bitwise.read32v(opb)); |
| 298 | + } |
| 299 | + else { |
| 300 | + ks.wrap_mode = KateWrapMode.kate_wrap_word; |
| 301 | + } |
| 302 | + |
| 303 | + Bitwise.skipWarp(opb); |
| 304 | + |
| 305 | + return ks; |
| 306 | + } |
| 307 | + |
| 308 | + /** |
| 309 | + * Decode the styles header packet. |
| 310 | + */ |
| 311 | + private int unpackStyles (Buffer opb) |
| 312 | + { |
| 313 | + int nstyles = Bitwise.read32v(opb); |
| 314 | + if (nstyles < 0) return Result.KATE_E_BAD_PACKET; |
| 315 | + styles = new Style[nstyles]; |
| 316 | + for (int n=0; n<nstyles; ++n) { |
| 317 | + try { |
| 318 | + styles[n] = unpackStyle(opb); |
| 319 | + } |
| 320 | + catch (KateException ke) { |
| 321 | + styles = null; |
| 322 | + return Result.KATE_E_BAD_PACKET; |
| 323 | + } |
| 324 | + } |
| 325 | + |
| 326 | + Bitwise.skipWarp(opb); |
| 327 | + |
| 328 | + /* end of packet */ |
| 329 | + return checkEOP(opb); |
| 330 | + } |
| 331 | + |
| 332 | + /** |
| 333 | + * Decode a single curve. |
| 334 | + */ |
| 335 | + private Curve unpackCurve (Buffer opb) throws KateException |
| 336 | + { |
| 337 | + Curve kc = new Curve(); |
| 338 | + |
| 339 | + kc.type = KateCurveType.CreateCurveType(opb.read(8)); |
| 340 | + kc.npts = Bitwise.read32v(opb); |
| 341 | + if (kc.npts < 0) |
| 342 | + throw new KateBadPacketException(); |
| 343 | + Bitwise.skipWarp(opb); |
| 344 | + |
| 345 | + kc.pts = Bitwise.readFloats(opb, kc.npts, 2); |
| 346 | + |
| 347 | + return kc; |
| 348 | + } |
| 349 | + |
| 350 | + /** |
| 351 | + * Decode the curves header packet. |
| 352 | + */ |
| 353 | + private int unpackCurves (Buffer opb) |
| 354 | + { |
| 355 | + int ncurves = Bitwise.read32v(opb); |
| 356 | + if (ncurves < 0) return Result.KATE_E_BAD_PACKET; |
| 357 | + curves = new Curve[ncurves]; |
| 358 | + for (int n=0; n<ncurves; ++n) { |
| 359 | + try { |
| 360 | + curves[n] = unpackCurve(opb); |
| 361 | + } |
| 362 | + catch (KateException ke) { |
| 363 | + curves = null; |
| 364 | + return Result.KATE_E_BAD_PACKET; |
| 365 | + } |
| 366 | + } |
| 367 | + |
| 368 | + Bitwise.skipWarp(opb); |
| 369 | + |
| 370 | + /* end of packet */ |
| 371 | + return checkEOP(opb); |
| 372 | + } |
| 373 | + |
| 374 | + /** |
| 375 | + * Decode a single motion. |
| 376 | + */ |
| 377 | + public Motion unpackMotion (Buffer opb) throws KateException |
| 378 | + { |
| 379 | + Motion km = new Motion(); |
| 380 | + |
| 381 | + int ncurves = Bitwise.read32v(opb); |
| 382 | + if (ncurves < 0) |
| 383 | + throw new KateBadPacketException(); |
| 384 | + km.curves = new Curve[ncurves]; |
| 385 | + for (int n=0; n<ncurves; ++n) { |
| 386 | + if (opb.read1() != 0) { |
| 387 | + int idx = Bitwise.read32v(opb); |
| 388 | + if (idx < 0 || idx >= this.curves.length) |
| 389 | + throw new KateBadPacketException(); |
| 390 | + km.curves[n] = this.curves[idx]; |
| 391 | + } |
| 392 | + else { |
| 393 | + km.curves[n] = unpackCurve(opb); |
| 394 | + } |
| 395 | + } |
| 396 | + |
| 397 | + double floats[][] = Bitwise.readFloats(opb, ncurves, 1); |
| 398 | + km.durations = new double[ncurves]; |
| 399 | + for (int n=0; n<ncurves; ++n) { |
| 400 | + km.durations[n] = floats[0][n]; |
| 401 | + } |
| 402 | + |
| 403 | + km.x_mapping = KateMotionMapping.CreateMotionMapping(opb.read(8)); |
| 404 | + km.y_mapping = KateMotionMapping.CreateMotionMapping(opb.read(8)); |
| 405 | + km.semantics = KateMotionSemantics.CreateMotionSemantics(opb.read(8)); |
| 406 | + km.periodic = (opb.read1() != 0); |
| 407 | + |
| 408 | + Bitwise.skipWarp(opb); |
| 409 | + |
| 410 | + return km; |
| 411 | + } |
| 412 | + |
| 413 | + /** |
| 414 | + * Decode the motions header packet. |
| 415 | + */ |
| 416 | + private int unpackMotions (Buffer opb) |
| 417 | + { |
| 418 | + int nmotions = Bitwise.read32v(opb); |
| 419 | + if (nmotions < 0) return Result.KATE_E_BAD_PACKET; |
| 420 | + motions = new Motion[nmotions]; |
| 421 | + for (int n=0; n<nmotions; ++n) { |
| 422 | + try { |
| 423 | + motions[n] = unpackMotion(opb); |
| 424 | + } |
| 425 | + catch (KateException ke) { |
| 426 | + motions = null; |
| 427 | + return Result.KATE_E_BAD_PACKET; |
| 428 | + } |
| 429 | + } |
| 430 | + |
| 431 | + Bitwise.skipWarp(opb); |
| 432 | + |
| 433 | + /* end of packet */ |
| 434 | + return checkEOP(opb); |
| 435 | + } |
| 436 | + |
| 437 | + /** |
| 438 | + * Decode a single palette. |
| 439 | + */ |
| 440 | + public Palette unpackPalette (Buffer opb) throws KateException |
| 441 | + { |
| 442 | + Palette kp = new Palette(); |
| 443 | + |
| 444 | + int ncolors = opb.read(8)+1; |
| 445 | + kp.colors = new Color[ncolors]; |
| 446 | + for (int n=0; n<ncolors; ++n) { |
| 447 | + kp.colors[n] = unpackColor(opb); |
| 448 | + } |
| 449 | + |
| 450 | + Bitwise.skipWarp(opb); |
| 451 | + |
| 452 | + return kp; |
| 453 | + } |
| 454 | + |
| 455 | + /** |
| 456 | + * Decodes the palettes packet. |
| 457 | + */ |
| 458 | + private int unpackPalettes (Buffer opb) |
| 459 | + { |
| 460 | + int npalettes = Bitwise.read32v(opb); |
| 461 | + if (npalettes < 0) return Result.KATE_E_BAD_PACKET; |
| 462 | + palettes = new Palette[npalettes]; |
| 463 | + for (int n=0; n<npalettes; ++n) { |
| 464 | + try { |
| 465 | + palettes[n] = unpackPalette(opb); |
| 466 | + } |
| 467 | + catch (KateException ke) { |
| 468 | + palettes = null; |
| 469 | + return Result.KATE_E_BAD_PACKET; |
| 470 | + } |
| 471 | + } |
| 472 | + |
| 473 | + Bitwise.skipWarp(opb); |
| 474 | + |
| 475 | + /* end of packet */ |
| 476 | + return checkEOP(opb); |
| 477 | + } |
| 478 | + |
| 479 | + /** |
| 480 | + * Decode a single bitmap. |
| 481 | + */ |
| 482 | + public Bitmap unpackBitmap (Buffer opb) throws KateException |
| 483 | + { |
| 484 | + Bitmap kb = new Bitmap(); |
| 485 | + |
| 486 | + kb.width = Bitwise.read32v(opb); |
| 487 | + kb.height = Bitwise.read32v(opb); |
| 488 | + kb.bpp = opb.read(8); |
| 489 | + if (kb.width < 0 || kb.height < 0 || kb.bpp < 0 || kb.bpp > 8) |
| 490 | + throw new KateBadPacketException(); |
| 491 | + |
| 492 | + if (kb.bpp == 0) { |
| 493 | + kb.type = KateBitmapType.CreateBitmapType(opb.read(8)); |
| 494 | + kb.palette = -1; |
| 495 | + if (kb.type == KateBitmapType.kate_bitmap_type_paletted) { |
| 496 | + int encoding = opb.read(8); |
| 497 | + switch (encoding) { |
| 498 | + case 1: /* RLE */ |
| 499 | + kb.bpp = Bitwise.read32v(opb); |
| 500 | + kb.palette = Bitwise.read32v(opb); |
| 501 | + kb.pixels = RLE.decodeRLE(opb, kb.width, kb.height, kb.bpp); |
| 502 | + break; |
| 503 | + default: |
| 504 | + Debug.warning("Unsupported bitmap type"); |
| 505 | + throw new KateBadPacketException(); |
| 506 | + } |
| 507 | + } |
| 508 | + else if (kb.type == KateBitmapType.kate_bitmap_type_png) { |
| 509 | + kb.size = Bitwise.read32(opb); |
| 510 | + kb.pixels = new byte[kb.size]; |
| 511 | + Bitwise.readbuf(opb, kb.pixels, kb.size); |
| 512 | + } |
| 513 | + else { |
| 514 | + Debug.warning("Unsupported bitmap type"); |
| 515 | + throw new KateBadPacketException(); |
| 516 | + } |
| 517 | + } |
| 518 | + else { |
| 519 | + kb.type = KateBitmapType.kate_bitmap_type_paletted; |
| 520 | + kb.palette = Bitwise.read32v(opb); |
| 521 | + int npixels = kb.width * kb.height; |
| 522 | + kb.pixels = new byte[npixels]; |
| 523 | + for (int n=0; n<npixels; ++n) |
| 524 | + kb.pixels[n] = (byte)opb.read(kb.bpp); |
| 525 | + } |
| 526 | + |
| 527 | + if (((bitstream_version_major<<8) | bitstream_version_minor) >= 0x0004) { |
| 528 | + Bitwise.read32v(opb); |
| 529 | + kb.x_offset = Bitwise.read32v(opb); |
| 530 | + kb.y_offset = Bitwise.read32v(opb); |
| 531 | + } |
| 532 | + else { |
| 533 | + kb.x_offset = 0; |
| 534 | + kb.y_offset = 0; |
| 535 | + } |
| 536 | + |
| 537 | + Bitwise.skipWarp(opb); |
| 538 | + |
| 539 | + return kb; |
| 540 | + } |
| 541 | + |
| 542 | + /** |
| 543 | + * Decodes the bitmaps packet. |
| 544 | + */ |
| 545 | + private int unpackBitmaps (Buffer opb) |
| 546 | + { |
| 547 | + int nbitmaps = Bitwise.read32v(opb); |
| 548 | + if (nbitmaps < 0) return Result.KATE_E_BAD_PACKET; |
| 549 | + bitmaps = new Bitmap[nbitmaps]; |
| 550 | + for (int n=0; n<nbitmaps; ++n) { |
| 551 | + try { |
| 552 | + bitmaps[n] = unpackBitmap(opb); |
| 553 | + } |
| 554 | + catch (KateException ke) { |
| 555 | + bitmaps = null; |
| 556 | + return Result.KATE_E_BAD_PACKET; |
| 557 | + } |
| 558 | + } |
| 559 | + |
| 560 | + Bitwise.skipWarp(opb); |
| 561 | + |
| 562 | + /* end of packet */ |
| 563 | + return checkEOP(opb); |
| 564 | + } |
| 565 | + |
| 566 | + /** |
| 567 | + * Decodes a single font range. |
| 568 | + */ |
| 569 | + private FontRange unpackFontRange (Buffer opb) |
| 570 | + { |
| 571 | + FontRange fr = new FontRange(); |
| 572 | + fr.first_code_point = Bitwise.read32v(opb); |
| 573 | + fr.last_code_point = Bitwise.read32v(opb); |
| 574 | + fr.first_bitmap = Bitwise.read32v(opb); |
| 575 | + Bitwise.skipWarp(opb); |
| 576 | + return fr; |
| 577 | + } |
| 578 | + |
| 579 | + /** |
| 580 | + * Decodes the font ranges/mappings packet. |
| 581 | + */ |
| 582 | + private int unpackFontMappings (Buffer opb) |
| 583 | + { |
| 584 | + int nranges = Bitwise.read32v(opb); |
| 585 | + if (nranges < 0) |
| 586 | + return Result.KATE_E_BAD_PACKET; |
| 587 | + if (nranges > 0) { |
| 588 | + font_ranges = new FontRange[nranges]; |
| 589 | + for (int n=0; n<nranges; ++n) { |
| 590 | + font_ranges[n] = unpackFontRange(opb); |
| 591 | + } |
| 592 | + } |
| 593 | + |
| 594 | + int nmappings = Bitwise.read32v(opb); |
| 595 | + if (nmappings < 0) |
| 596 | + return Result.KATE_E_BAD_PACKET; |
| 597 | + if (nmappings > 0) { |
| 598 | + font_mappings = new FontMapping[nmappings]; |
| 599 | + for (int n=0; n<nmappings; ++n) { |
| 600 | + nranges = Bitwise.read32v(opb); |
| 601 | + if (nranges < 0) |
| 602 | + return Result.KATE_E_BAD_PACKET; |
| 603 | + if (nranges > 0) { |
| 604 | + FontRange fr[] = new FontRange[nranges]; |
| 605 | + for (int l=0; l<nranges; ++l) { |
| 606 | + if (opb.read1() != 0) { |
| 607 | + int idx = Bitwise.read32v(opb); |
| 608 | + if (idx < 0 || idx >= this.font_ranges.length) |
| 609 | + return Result.KATE_E_BAD_PACKET; |
| 610 | + fr[l] = this.font_ranges[idx]; |
| 611 | + } |
| 612 | + else { |
| 613 | + fr[l] = unpackFontRange(opb); |
| 614 | + } |
| 615 | + } |
| 616 | + font_mappings[n].ranges = fr; |
| 617 | + } |
| 618 | + else { |
| 619 | + font_mappings[n] = null; |
| 620 | + } |
| 621 | + } |
| 622 | + } |
| 623 | + |
| 624 | + Bitwise.skipWarp(opb); |
| 625 | + |
| 626 | + /* end of packet */ |
| 627 | + return checkEOP(opb); |
| 628 | + } |
| 629 | + |
| 630 | + /** |
| 631 | + * Resets the header decoder to the start, so a new stream may be decoded. |
| 632 | + */ |
| 633 | + public void clear() { |
| 634 | + num_headers = 0; |
| 635 | + regions = null; |
| 636 | + styles = null; |
| 637 | + curves = null; |
| 638 | + motions = null; |
| 639 | + probe = 0; |
| 640 | + } |
| 641 | + |
| 642 | + /** |
| 643 | + * Decodes a Kate header, updating the info with the data decoded from the header. |
| 644 | + * If the next expected header is decoded properly, the next header will be expected. |
| 645 | + * Headers beyond the ones we know about are ignored. |
| 646 | + */ |
| 647 | + public int decodeHeader (Comment kc, Packet op) |
| 648 | + { |
| 649 | + long ret; |
| 650 | + Buffer opb = new Buffer(); |
| 651 | + |
| 652 | + opb.readinit (op.packet_base, op.packet, op.bytes); |
| 653 | + |
| 654 | + { |
| 655 | + byte[] id = new byte[7]; |
| 656 | + int typeflag; |
| 657 | + |
| 658 | + typeflag = opb.read(8); |
| 659 | + |
| 660 | + /* header types have the MSB set */ |
| 661 | + if((typeflag & 0x80) == 0) { |
| 662 | + return Result.KATE_E_BAD_PACKET; |
| 663 | + } |
| 664 | + |
| 665 | + /* Kate header magic */ |
| 666 | + Bitwise.readbuf(opb,id,7); |
| 667 | + if (!"kate\0\0\0".equals(new String(id))) { |
| 668 | + return Result.KATE_E_NOT_KATE; |
| 669 | + } |
| 670 | + |
| 671 | + if (op.packetno < num_headers) { |
| 672 | + if (probe != op.packetno) return Result.KATE_E_BAD_PACKET; |
| 673 | + } |
| 674 | + |
| 675 | + /* reserved 0 byte */ |
| 676 | + if (opb.read(8) != 0) |
| 677 | + return Result.KATE_E_BAD_PACKET; |
| 678 | + |
| 679 | + Debug.debug("decodeHeader: packet type "+typeflag+", probe "+probe); |
| 680 | + |
| 681 | + /* ensure packets are received in order */ |
| 682 | + switch(probe){ |
| 683 | + case 0: |
| 684 | + if(op.b_o_s == 0){ |
| 685 | + /* Not the initial packet */ |
| 686 | + return Result.KATE_E_BAD_PACKET; |
| 687 | + } |
| 688 | + ret = unpackInfo(opb); |
| 689 | + break; |
| 690 | + |
| 691 | + case 1: |
| 692 | + ret = unpackComment(kc,opb); |
| 693 | + break; |
| 694 | + |
| 695 | + case 2: |
| 696 | + ret = unpackRegions(opb); |
| 697 | + break; |
| 698 | + |
| 699 | + case 3: |
| 700 | + ret = unpackStyles(opb); |
| 701 | + break; |
| 702 | + |
| 703 | + case 4: |
| 704 | + ret = unpackCurves(opb); |
| 705 | + break; |
| 706 | + |
| 707 | + case 5: |
| 708 | + ret = unpackMotions(opb); |
| 709 | + break; |
| 710 | + |
| 711 | + case 6: |
| 712 | + ret = unpackPalettes(opb); |
| 713 | + break; |
| 714 | + |
| 715 | + case 7: |
| 716 | + ret = unpackBitmaps(opb); |
| 717 | + break; |
| 718 | + |
| 719 | + case 8: |
| 720 | + ret = unpackFontMappings(opb); |
| 721 | + /* last known header, we can init for decode */ |
| 722 | + if (ret == 0) { |
| 723 | + Debug.debug("Found last known header, returning 1"); |
| 724 | + ret = 1; |
| 725 | + } |
| 726 | + break; |
| 727 | + |
| 728 | + default: |
| 729 | + /* ignore any trailing header packets for forward compatibility */ |
| 730 | + ret = 0; |
| 731 | + break; |
| 732 | + } |
| 733 | + } |
| 734 | + |
| 735 | + /* decode was successful, we're now expecting the next packet in sequence */ |
| 736 | + if (ret >= 0) { |
| 737 | + ++probe; |
| 738 | + } |
| 739 | + |
| 740 | + return (int)ret; |
| 741 | + } |
| 742 | +} |
| 743 | + |
Index: trunk/cortado/src/com/fluendo/jkate/Tracker.java |
— | — | @@ -0,0 +1,96 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +import java.util.*; |
| 25 | +import java.awt.*; |
| 26 | +import com.fluendo.utils.*; |
| 27 | + |
| 28 | +public final class Tracker { |
| 29 | + |
| 30 | + private Dimension window; |
| 31 | + private Dimension frame; |
| 32 | + |
| 33 | + public com.fluendo.jkate.Event ev = null; |
| 34 | + |
| 35 | + public boolean has[] = new boolean[64]; |
| 36 | + public static final int has_region = 0; |
| 37 | + public static final int has_text_alignment_int = 1; |
| 38 | + public static final int has_text_alignment_ext = 2; |
| 39 | + |
| 40 | + public float region_x; |
| 41 | + public float region_y; |
| 42 | + public float region_w; |
| 43 | + public float region_h; |
| 44 | + |
| 45 | + public Tracker (com.fluendo.jkate.Event ev) { |
| 46 | + this.ev = ev; |
| 47 | + } |
| 48 | + |
| 49 | + /** |
| 50 | + * Update the tracker at the given time for the given image's dimensions. |
| 51 | + */ |
| 52 | + public boolean update(double t, Dimension window, Dimension frame) |
| 53 | + { |
| 54 | + this.window = window; |
| 55 | + this.frame = frame; |
| 56 | + |
| 57 | + /* find current region and style, if any */ |
| 58 | + Region kr = ev.kr; |
| 59 | + Style ks = ev.ks; |
| 60 | + if (ks == null && kr != null && kr.style >= 0) { |
| 61 | + ks = ev.ki.styles[kr.style]; |
| 62 | + } |
| 63 | + |
| 64 | + /* start with nothing */ |
| 65 | + for (int n=0; n<has.length; ++n) has[n] = false; |
| 66 | + |
| 67 | + /* define region */ |
| 68 | + if (kr != null) { |
| 69 | + if (kr.metric == KateSpaceMetric.kate_metric_percentage) { |
| 70 | + region_x = kr.x * frame.width / 100.0f; |
| 71 | + region_y = kr.y * frame.height / 100.0f; |
| 72 | + region_w = kr.w * frame.width / 100.0f; |
| 73 | + region_h = kr.h * frame.height / 100.0f; |
| 74 | + } |
| 75 | + else if (kr.metric == KateSpaceMetric.kate_metric_millionths) { |
| 76 | + region_x = kr.x * frame.width / 1000000.0f; |
| 77 | + region_y = kr.y * frame.height / 1000000.0f; |
| 78 | + region_w = kr.w * frame.width / 1000000.0f; |
| 79 | + region_h = kr.h * frame.height / 1000000.0f; |
| 80 | + } |
| 81 | + else if (kr.metric == KateSpaceMetric.kate_metric_pixels) { |
| 82 | + region_x = kr.x; |
| 83 | + region_y = kr.y; |
| 84 | + region_w = kr.w; |
| 85 | + region_h = kr.h; |
| 86 | + } |
| 87 | + else { |
| 88 | + Debug.debug("Invalid metrics"); |
| 89 | + return false; |
| 90 | + } |
| 91 | + has[has_region] = true; |
| 92 | + } |
| 93 | + |
| 94 | + return true; |
| 95 | + } |
| 96 | + |
| 97 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateTextDirectionality.java |
— | — | @@ -0,0 +1,47 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateTextDirectionality { |
| 25 | + public static final KateTextDirectionality kate_l2r_t2b = new KateTextDirectionality (); |
| 26 | + public static final KateTextDirectionality kate_r2l_t2b = new KateTextDirectionality (); |
| 27 | + public static final KateTextDirectionality kate_t2b_r2l = new KateTextDirectionality (); |
| 28 | + public static final KateTextDirectionality kate_t2b_l2r = new KateTextDirectionality (); |
| 29 | + |
| 30 | + private static final KateTextDirectionality[] list = { |
| 31 | + kate_l2r_t2b, |
| 32 | + kate_r2l_t2b, |
| 33 | + kate_t2b_r2l, |
| 34 | + kate_t2b_l2r |
| 35 | + }; |
| 36 | + |
| 37 | + private KateTextDirectionality() { |
| 38 | + } |
| 39 | + |
| 40 | + /** |
| 41 | + * Create a KateTextDirectionality object from an integer. |
| 42 | + */ |
| 43 | + public static KateTextDirectionality CreateTextDirectionality(int idx) throws KateException { |
| 44 | + if (idx < 0 || idx >= list.length) |
| 45 | + throw new KateException("Text directionality "+idx+" out of bounds"); |
| 46 | + return list[idx]; |
| 47 | + } |
| 48 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Palette.java |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A Palette definition, containing between 0 and 256 colors. |
| 26 | + */ |
| 27 | +public class Palette |
| 28 | +{ |
| 29 | + public Color colors[] = null; |
| 30 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateTextEncoding.java |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateTextEncoding { |
| 25 | + public static final KateTextEncoding kate_utf8 = new KateTextEncoding (); |
| 26 | + |
| 27 | + private static final KateTextEncoding[] list = { |
| 28 | + kate_utf8, |
| 29 | + }; |
| 30 | + |
| 31 | + private KateTextEncoding() { |
| 32 | + } |
| 33 | + |
| 34 | + /** |
| 35 | + * Create a KateTextEncoding object from an integer. |
| 36 | + */ |
| 37 | + public static KateTextEncoding CreateTextEncoding(int idx) throws KateException { |
| 38 | + if (idx < 0 || idx >= list.length) |
| 39 | + throw new KateException("Text encoding "+idx+" out of bounds"); |
| 40 | + return list[idx]; |
| 41 | + } |
| 42 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Style.java |
— | — | @@ -0,0 +1,54 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A style definition. |
| 26 | + */ |
| 27 | + |
| 28 | +public class Style |
| 29 | +{ |
| 30 | + public double halign; |
| 31 | + public double valign; |
| 32 | + |
| 33 | + public Color text_color; |
| 34 | + public Color background_color; |
| 35 | + public Color draw_color; |
| 36 | + |
| 37 | + public KateSpaceMetric font_metric; |
| 38 | + public double font_width; |
| 39 | + public double font_height; |
| 40 | + |
| 41 | + public KateSpaceMetric margin_metric; |
| 42 | + public double left_margin; |
| 43 | + public double top_margin; |
| 44 | + public double right_margin; |
| 45 | + public double bottom_margin; |
| 46 | + |
| 47 | + public boolean bold; |
| 48 | + public boolean italics; |
| 49 | + public boolean underline; |
| 50 | + public boolean strike; |
| 51 | + public boolean justify; |
| 52 | + public KateWrapMode wrap_mode; |
| 53 | + |
| 54 | + public String font; |
| 55 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Comment.java |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * Vorbis comments are used in Kate streams too. |
| 26 | + */ |
| 27 | +public class Comment { |
| 28 | + String[] user_comments; |
| 29 | + String vendor; |
| 30 | + |
| 31 | + |
| 32 | + public void clear() { |
| 33 | + user_comments = null; |
| 34 | + vendor = null; |
| 35 | + } |
| 36 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/KateException.java |
— | — | @@ -0,0 +1,30 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +class KateException extends java.lang.Exception { |
| 25 | + public KateException(String s) { super(); } |
| 26 | +} |
| 27 | + |
| 28 | +class KateBadPacketException extends KateException { |
| 29 | + public KateBadPacketException() { super("Bad packet"); } |
| 30 | +} |
| 31 | + |
Index: trunk/cortado/src/com/fluendo/jkate/KateSpaceMetric.java |
— | — | @@ -0,0 +1,45 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateSpaceMetric { |
| 25 | + public static final KateSpaceMetric kate_metric_pixels = new KateSpaceMetric (); |
| 26 | + public static final KateSpaceMetric kate_metric_percentage = new KateSpaceMetric (); |
| 27 | + public static final KateSpaceMetric kate_metric_millionths = new KateSpaceMetric (); |
| 28 | + |
| 29 | + private static final KateSpaceMetric[] list = { |
| 30 | + kate_metric_pixels, |
| 31 | + kate_metric_percentage, |
| 32 | + kate_metric_millionths, |
| 33 | + }; |
| 34 | + |
| 35 | + private KateSpaceMetric() { |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Create a KateSpaceMetric object from an integer. |
| 40 | + */ |
| 41 | + public static KateSpaceMetric CreateSpaceMetric(int idx) throws KateException { |
| 42 | + if (idx < 0 || idx >= list.length) |
| 43 | + throw new KateException("Space metrics "+idx+" out of bounds"); |
| 44 | + return list[idx]; |
| 45 | + } |
| 46 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Motion.java |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +/** |
| 25 | + * A motion definition, composed of a series of curves |
| 26 | + */ |
| 27 | +public class Motion |
| 28 | +{ |
| 29 | + public Curve curves[]; |
| 30 | + public double durations[]; |
| 31 | + KateMotionMapping x_mapping; |
| 32 | + KateMotionMapping y_mapping; |
| 33 | + KateMotionSemantics semantics; |
| 34 | + boolean periodic; |
| 35 | +} |
| 36 | + |
Index: trunk/cortado/src/com/fluendo/jkate/KateMarkupType.java |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +public class KateMarkupType { |
| 25 | + public static final KateMarkupType kate_markup_none = new KateMarkupType (); |
| 26 | + public static final KateMarkupType kate_markup_simple = new KateMarkupType (); |
| 27 | + |
| 28 | + private static final KateMarkupType[] list = { |
| 29 | + kate_markup_none, |
| 30 | + kate_markup_simple, |
| 31 | + }; |
| 32 | + |
| 33 | + private KateMarkupType() { |
| 34 | + } |
| 35 | + |
| 36 | + /** |
| 37 | + * Create a KateMarkupType object from an integer. |
| 38 | + */ |
| 39 | + public static KateMarkupType CreateMarkupType(int idx) throws KateException { |
| 40 | + if (idx < 0 || idx >= list.length) |
| 41 | + throw new KateException("Markup type "+idx+" out of bounds"); |
| 42 | + return list[idx]; |
| 43 | + } |
| 44 | +} |
Index: trunk/cortado/src/com/fluendo/jkate/Bitwise.java |
— | — | @@ -0,0 +1,154 @@ |
| 2 | +/* JKate |
| 3 | + * Copyright (C) 2008 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 4 | + * |
| 5 | + * Parts of JKate are based on code by Wim Taymans <wim@fluendo.com> |
| 6 | + * |
| 7 | + * This program is free software; you can redistribute it and/or |
| 8 | + * modify it under the terms of the GNU Library General Public License |
| 9 | + * as published by the Free Software Foundation; either version 2 of |
| 10 | + * the License, or (at your option) any later version. |
| 11 | + * |
| 12 | + * This program is distributed in the hope that it will be useful, |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | + * GNU Library General Public License for more details. |
| 16 | + * |
| 17 | + * You should have received a copy of the GNU Library General Public |
| 18 | + * License along with this program; if not, write to the Free Software |
| 19 | + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 20 | + */ |
| 21 | + |
| 22 | +package com.fluendo.jkate; |
| 23 | + |
| 24 | +import com.jcraft.jogg.*; |
| 25 | + |
| 26 | +/** |
| 27 | + * Various methods to read data from a bitstream. |
| 28 | + */ |
| 29 | +public class Bitwise { |
| 30 | + |
| 31 | + /** |
| 32 | + * Read a number of bytes into a buffer. |
| 33 | + */ |
| 34 | + static void readbuf(Buffer opb, byte[] buf, int len) |
| 35 | + { |
| 36 | + for (int i=0; i<len; i++) { |
| 37 | + buf[i] = (byte)opb.read(8); |
| 38 | + } |
| 39 | + } |
| 40 | + |
| 41 | + /** |
| 42 | + * Read a little endian 32 bit integer. |
| 43 | + */ |
| 44 | + static int read32(Buffer opb) |
| 45 | + { |
| 46 | + int value; |
| 47 | + |
| 48 | + value = opb.read(8); |
| 49 | + value |= opb.read(8) << 8; |
| 50 | + value |= opb.read(8) << 16; |
| 51 | + value |= opb.read(8) << 24; |
| 52 | + |
| 53 | + return value; |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Read a variable size integer. |
| 58 | + * Format defined in the Kate specification. |
| 59 | + */ |
| 60 | + static int read32v(Buffer opb) |
| 61 | + { |
| 62 | + int value; |
| 63 | + |
| 64 | + value = opb.read(4); |
| 65 | + if (value == 15) { |
| 66 | + int sign = opb.read(1); |
| 67 | + int bits = opb.read(5)+1; |
| 68 | + value = opb.read(bits); |
| 69 | + if (sign != 0) value = -value; |
| 70 | + } |
| 71 | + |
| 72 | + return value; |
| 73 | + } |
| 74 | + |
| 75 | + /** |
| 76 | + * Read a little endian 64 bit integer. |
| 77 | + */ |
| 78 | + static long read64(Buffer opb) |
| 79 | + { |
| 80 | + long vl, vh; |
| 81 | + vl = (long)read32(opb); |
| 82 | + vh = (long)read32(opb); |
| 83 | + return vl | (vh<<32); |
| 84 | + } |
| 85 | + |
| 86 | + /** |
| 87 | + * Read a (possibly multiple) warp. |
| 88 | + * Used to skip over unhandled data from newer (bit still compatible) |
| 89 | + * bitstream versions. |
| 90 | + */ |
| 91 | + static int skipWarp(Buffer opb) |
| 92 | + { |
| 93 | + while (true) { |
| 94 | + int bits = read32v(opb); |
| 95 | + if (bits == 0) |
| 96 | + break; |
| 97 | + if (bits < 0) |
| 98 | + return Result.KATE_E_BAD_PACKET; |
| 99 | + opb.adv(bits); |
| 100 | + } |
| 101 | + |
| 102 | + return 0; |
| 103 | + } |
| 104 | + |
| 105 | + static private final int fp_bits = (4*8); |
| 106 | + static private final int fp_cuts_bits = fp_bits/2-1; |
| 107 | + static private final int fp_cuts_bits_bits = 4; |
| 108 | + static private final int fp_sign_bit = 0x80000000; |
| 109 | + private static int[] readFixed(Buffer opb, int count) { |
| 110 | + int head = opb.read(fp_cuts_bits_bits); |
| 111 | + int tail = opb.read(fp_cuts_bits_bits); |
| 112 | + int bits = fp_bits - head - tail; |
| 113 | + int values[] = new int[count]; |
| 114 | + int n = 0; |
| 115 | + while (count-- > 0) { |
| 116 | + int sign = 0; |
| 117 | + if (head > 0) |
| 118 | + sign = opb.read1(); |
| 119 | + int v = opb.read(bits); |
| 120 | + v <<= tail; |
| 121 | + if (sign != 0) |
| 122 | + v = -v; |
| 123 | + values[n++] = v; |
| 124 | + } |
| 125 | + return values; |
| 126 | + } |
| 127 | + static private double fixedToFloat(int v) { |
| 128 | + return ((double)v) / (1<<16); |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * Read an array of float channels. |
| 133 | + * Float format defined in the Kate specification. |
| 134 | + */ |
| 135 | + static double[][] readFloats(Buffer opb, int count, int streams) { |
| 136 | + if (count*streams == 0) |
| 137 | + return null; |
| 138 | + if (streams > 1) { |
| 139 | + if (opb.read1() != 0) { |
| 140 | + count *= streams; |
| 141 | + streams = 1; |
| 142 | + } |
| 143 | + } |
| 144 | + |
| 145 | + double values[][] = new double[streams][]; |
| 146 | + for (int s=0; s<streams; ++s) { |
| 147 | + int ints[] = readFixed(opb, count); |
| 148 | + values[s] = new double[count]; |
| 149 | + for (int c=0; c<count; ++c) { |
| 150 | + values[s][c] = fixedToFloat(ints[c]); |
| 151 | + } |
| 152 | + } |
| 153 | + return values; |
| 154 | + } |
| 155 | +} |
Index: trunk/cortado/src/com/fluendo/plugin/KateDec.java |
— | — | @@ -0,0 +1,334 @@ |
| 2 | +/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 3 | + * based on code Copyright (C) <2004> Wim Taymans <wim@fluendo.com> |
| 4 | + * |
| 5 | + * This library is free software; you can redistribute it and/or |
| 6 | + * modify it under the terms of the GNU Library General Public |
| 7 | + * License as published by the Free Software Foundation; either |
| 8 | + * version 2 of the License, or (at your option) any later version. |
| 9 | + * |
| 10 | + * This library is distributed in the hope that it will be useful, |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 | + * Library General Public License for more details. |
| 14 | + * |
| 15 | + * You should have received a copy of the GNU Library General Public |
| 16 | + * License along with this library; if not, write to the |
| 17 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 18 | + * Boston, MA 02111-1307, USA. |
| 19 | + */ |
| 20 | + |
| 21 | +package com.fluendo.plugin; |
| 22 | + |
| 23 | +import java.util.*; |
| 24 | +import com.jcraft.jogg.*; |
| 25 | +import com.fluendo.jkate.*; |
| 26 | +import com.fluendo.jst.*; |
| 27 | +import com.fluendo.utils.*; |
| 28 | + |
| 29 | +/** |
| 30 | + * Katedec is a decoder element for the Kate stream format. |
| 31 | + * See http://wiki.xiph.org/index.php/OggKate for more information. |
| 32 | + * Kate streams may be multiplexed in Ogg. |
| 33 | + * The Katedec element accepts Kate packets (presumably demultiplexed by an |
| 34 | + * Ogg demuxer element) on its sink, and generates Kate events on its source. |
| 35 | + * Kate events are Kate specific structures, which may then be interpreted |
| 36 | + * by a renderer. |
| 37 | +*/ |
| 38 | +public class KateDec extends Element implements OggPayload |
| 39 | +{ |
| 40 | + /* Kate magic: 0x80 (BOS header) followed by "kate\0\0\0" */ |
| 41 | + private static final byte[] signature = { -128, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00 }; |
| 42 | + |
| 43 | + private Info ki; |
| 44 | + private Comment kc; |
| 45 | + private State k; |
| 46 | + private Packet op; |
| 47 | + private int packetno; |
| 48 | + |
| 49 | + private long basetime = 0; |
| 50 | + private long lastTs; |
| 51 | + private boolean haveDecoder = false; |
| 52 | + |
| 53 | + /* |
| 54 | + * OggPayload interface |
| 55 | + */ |
| 56 | + public boolean isType (Packet op) |
| 57 | + { |
| 58 | + return typeFind (op.packet_base, op.packet, op.bytes) > 0; |
| 59 | + } |
| 60 | + public boolean isKeyFrame (Packet op) |
| 61 | + { |
| 62 | + return true; |
| 63 | + } |
| 64 | + |
| 65 | + /** |
| 66 | + * A discontinuous codec will not cause the pipeline to wait for data if starving |
| 67 | + */ |
| 68 | + public boolean isDiscontinuous () |
| 69 | + { |
| 70 | + return true; |
| 71 | + } |
| 72 | + public int takeHeader (Packet op) |
| 73 | + { |
| 74 | + int ret = ki.decodeHeader(kc, op); |
| 75 | + if (ret > 0) { |
| 76 | + k.decodeInit(ki); |
| 77 | + Debug.debug("Kate decoder ready"); |
| 78 | + haveDecoder = true; |
| 79 | + } |
| 80 | + return ret; |
| 81 | + } |
| 82 | + public boolean isHeader (Packet op) |
| 83 | + { |
| 84 | + return (op.packet_base[op.packet] & 0x80) == 0x80; |
| 85 | + } |
| 86 | + public long getFirstTs (Vector packets) |
| 87 | + { |
| 88 | + int len = packets.size(); |
| 89 | + int i; |
| 90 | + long time; |
| 91 | + com.fluendo.jst.Buffer data = null; |
| 92 | + |
| 93 | + /* first find buffer with valid offset */ |
| 94 | + for (i=0; i<len; i++) { |
| 95 | + data = (com.fluendo.jst.Buffer) packets.elementAt(i); |
| 96 | + |
| 97 | + if (data.time_offset != -1) |
| 98 | + break; |
| 99 | + } |
| 100 | + if (i == packets.size()) |
| 101 | + return -1; |
| 102 | + |
| 103 | + time = granuleToTime (data.time_offset); |
| 104 | + |
| 105 | + data = (com.fluendo.jst.Buffer) packets.elementAt(0); |
| 106 | + data.timestamp = time - (long) ((i+1) * (Clock.SECOND * ki.gps_denominator / ki.gps_numerator)); |
| 107 | + |
| 108 | + return time; |
| 109 | + } |
| 110 | + |
| 111 | + /** |
| 112 | + * Converts a granule position to its time equivalent |
| 113 | + */ |
| 114 | + public long granuleToTime (long gp) |
| 115 | + { |
| 116 | + long res; |
| 117 | + |
| 118 | + if (gp < 0 || !haveDecoder) |
| 119 | + return -1; |
| 120 | + |
| 121 | + res = (long) (k.granuleTime(gp) * Clock.SECOND); |
| 122 | + |
| 123 | + return res; |
| 124 | + } |
| 125 | + |
| 126 | + /** |
| 127 | + * Converts a granule position to its duration equivalent |
| 128 | + */ |
| 129 | + public long granuleToDuration (long gp) |
| 130 | + { |
| 131 | + long res; |
| 132 | + |
| 133 | + if (gp < 0 || !haveDecoder) |
| 134 | + return -1; |
| 135 | + |
| 136 | + res = (long) (k.granuleDuration(gp) * Clock.SECOND); |
| 137 | + |
| 138 | + return res; |
| 139 | + } |
| 140 | + |
| 141 | + private Pad srcPad = new Pad(Pad.SRC, "src") { |
| 142 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 143 | + return sinkPad.pushEvent(event); |
| 144 | + } |
| 145 | + }; |
| 146 | + |
| 147 | + private Pad sinkPad = new Pad(Pad.SINK, "sink") { |
| 148 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 149 | + boolean result; |
| 150 | + |
| 151 | + switch (event.getType()) { |
| 152 | + case com.fluendo.jst.Event.FLUSH_START: |
| 153 | + result = srcPad.pushEvent (event); |
| 154 | + synchronized (streamLock) { |
| 155 | + Debug.log(Debug.DEBUG, "synced "+this); |
| 156 | + } |
| 157 | + break; |
| 158 | + case com.fluendo.jst.Event.FLUSH_STOP: |
| 159 | + result = srcPad.pushEvent(event); |
| 160 | + break; |
| 161 | + case com.fluendo.jst.Event.EOS: |
| 162 | + Debug.log(Debug.INFO, "got EOS "+this); |
| 163 | + result = srcPad.pushEvent(event); |
| 164 | + break; |
| 165 | + case com.fluendo.jst.Event.NEWSEGMENT: |
| 166 | + basetime = event.parseNewsegmentStart(); |
| 167 | + Debug.info("new segment: base time "+basetime); |
| 168 | + result = srcPad.pushEvent(event); |
| 169 | + break; |
| 170 | + default: |
| 171 | + result = srcPad.pushEvent(event); |
| 172 | + break; |
| 173 | + } |
| 174 | + return result; |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * receives Kate packets, and generates Kate events |
| 179 | + */ |
| 180 | + protected int chainFunc (com.fluendo.jst.Buffer buf) { |
| 181 | + int result; |
| 182 | + long timestamp; |
| 183 | + |
| 184 | + Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf ); |
| 185 | + |
| 186 | + op.packet_base = buf.data; |
| 187 | + op.packet = buf.offset; |
| 188 | + op.bytes = buf.length; |
| 189 | + op.b_o_s = (packetno == 0 ? 1 : 0); |
| 190 | + op.e_o_s = 0; |
| 191 | + op.packetno = packetno; |
| 192 | + timestamp = buf.timestamp; |
| 193 | + |
| 194 | + Debug.log(Debug.DEBUG, "Kate chainFunc with packetno "+packetno+", haveDecoder "+haveDecoder); |
| 195 | + |
| 196 | +// if (buf.isFlagSet (com.fluendo.jst.Buffer.FLAG_DISCONT)) { |
| 197 | +// Debug.log(Debug.INFO, "kate: got discont"); |
| 198 | +// /* should flush, if we keep events to handle repeats in the future */ |
| 199 | +// lastTs = -1; |
| 200 | +// } |
| 201 | + |
| 202 | + if (!haveDecoder) { |
| 203 | + //System.out.println ("decoding header"); |
| 204 | + result = takeHeader(op); |
| 205 | + if (result < 0){ |
| 206 | + buf.free(); |
| 207 | + // error case; not a kate header |
| 208 | + Debug.log(Debug.ERROR, "does not contain Kate data."); |
| 209 | + return ERROR; |
| 210 | + } |
| 211 | + else if (result > 0) { |
| 212 | + // we've decoded all headers |
| 213 | + Debug.log(Debug.DEBUG, "Kate initialized for decoding"); |
| 214 | + |
| 215 | + /* we're sending raw kate_event structures */ |
| 216 | + caps = new Caps ("application/x-kate-event"); |
| 217 | + } |
| 218 | + buf.free(); |
| 219 | + packetno++; |
| 220 | + |
| 221 | + return OK; |
| 222 | + } |
| 223 | + else { |
| 224 | + if ((op.packet_base[op.packet] & 0x80) == 0x80) { |
| 225 | + Debug.log(Debug.DEBUG, "ignoring header"); |
| 226 | + buf.free(); |
| 227 | + return OK; |
| 228 | + } |
| 229 | + |
| 230 | + if (timestamp != -1) { |
| 231 | + lastTs = timestamp; |
| 232 | + } |
| 233 | + |
| 234 | + if (true) { |
| 235 | + try{ |
| 236 | + result = k.decodePacketin(op); |
| 237 | + if (result < 0) { |
| 238 | + buf.free(); |
| 239 | + Debug.log(Debug.ERROR, "Error Decoding Kate."); |
| 240 | + postMessage (Message.newError (this, "Error decoding Kate")); |
| 241 | + return ERROR; |
| 242 | + } |
| 243 | + com.fluendo.jkate.Event ev = k.decodeEventOut(); |
| 244 | + if (ev != null) { |
| 245 | + buf.object = ev; |
| 246 | + buf.caps = caps; |
| 247 | + buf.timestamp = granuleToDuration(ev.start); |
| 248 | + buf.timestampEnd = buf.timestamp + granuleToDuration(ev.duration); |
| 249 | + Debug.log( Debug.DEBUG, parent.getName() + " >>> " + buf ); |
| 250 | + Debug.debug("Got Kate text: "+new String(ev.text)+" from "+buf.timestamp+" to "+buf.timestampEnd+", basetime "+basetime); |
| 251 | + result = srcPad.push(buf); |
| 252 | + Debug.log(Debug.DEBUG, "push returned "+result); |
| 253 | + } |
| 254 | + else { |
| 255 | + Debug.debug("Got no event"); |
| 256 | + buf.free(); |
| 257 | + result = OK; |
| 258 | + } |
| 259 | + } |
| 260 | + catch (Exception e) { |
| 261 | + e.printStackTrace(); |
| 262 | + postMessage (Message.newError (this, e.getMessage())); |
| 263 | + result = ERROR; |
| 264 | + } |
| 265 | + } |
| 266 | + else { |
| 267 | + result = OK; |
| 268 | + buf.free(); |
| 269 | + } |
| 270 | + } |
| 271 | + packetno++; |
| 272 | + |
| 273 | + return result; |
| 274 | + } |
| 275 | + |
| 276 | + protected boolean activateFunc (int mode) |
| 277 | + { |
| 278 | + return true; |
| 279 | + } |
| 280 | + }; |
| 281 | + |
| 282 | + public KateDec() { |
| 283 | + super(); |
| 284 | + |
| 285 | + ki = new Info(); |
| 286 | + kc = new Comment(); |
| 287 | + k = new State(); |
| 288 | + op = new Packet(); |
| 289 | + |
| 290 | + addPad (srcPad); |
| 291 | + addPad (sinkPad); |
| 292 | + } |
| 293 | + |
| 294 | + protected int changeState (int transition) { |
| 295 | + int res; |
| 296 | + |
| 297 | + switch (transition) { |
| 298 | + case STOP_PAUSE: |
| 299 | + lastTs = -1; |
| 300 | + packetno = 0; |
| 301 | + break; |
| 302 | + default: |
| 303 | + break; |
| 304 | + } |
| 305 | + |
| 306 | + res = super.changeState (transition); |
| 307 | + |
| 308 | + switch (transition) { |
| 309 | + case PAUSE_STOP: |
| 310 | + ki.clear(); |
| 311 | + kc.clear(); |
| 312 | + k.clear(); |
| 313 | + break; |
| 314 | + default: |
| 315 | + break; |
| 316 | + } |
| 317 | + |
| 318 | + return res; |
| 319 | + } |
| 320 | + |
| 321 | + public String getFactoryName () |
| 322 | + { |
| 323 | + return "katedec"; |
| 324 | + } |
| 325 | + public String getMime () |
| 326 | + { |
| 327 | + return "application/x-kate"; |
| 328 | + } |
| 329 | + public int typeFind (byte[] data, int offset, int length) |
| 330 | + { |
| 331 | + if (MemUtils.startsWith (data, offset, length, signature)) |
| 332 | + return 10; |
| 333 | + return -1; |
| 334 | + } |
| 335 | +} |
Index: trunk/cortado/src/com/fluendo/plugin/OggDemux.java |
— | — | @@ -41,7 +41,8 @@ |
42 | 42 | |
43 | 43 | private OggPayload payloads[] = { |
44 | 44 | new TheoraDec(), |
45 | | - new VorbisDec() |
| 45 | + new VorbisDec(), |
| 46 | + new KateDec() |
46 | 47 | }; |
47 | 48 | |
48 | 49 | class OggStream extends Pad { |
— | — | @@ -222,15 +223,20 @@ |
223 | 224 | complete = true; |
224 | 225 | return Pad.OK; |
225 | 226 | } |
| 227 | + |
226 | 228 | /* first read all the headers */ |
227 | 229 | if (!haveHeaders) { |
228 | 230 | if (payload.isHeader(op)) { |
229 | | - if (payload.takeHeader (op) < 0) { |
| 231 | + int result = payload.takeHeader (op); |
| 232 | + if (result < 0) { |
230 | 233 | postMessage (Message.newError (this, "cannot read header")); |
231 | 234 | return Pad.ERROR; |
232 | 235 | } |
233 | 236 | com.fluendo.jst.Buffer data = bufferFromPacket (op); |
234 | 237 | headers.addElement(data); |
| 238 | + if (result > 0) { |
| 239 | + haveHeaders = true; |
| 240 | + } |
235 | 241 | } |
236 | 242 | else { |
237 | 243 | haveHeaders = true; |
— | — | @@ -238,6 +244,10 @@ |
239 | 245 | } |
240 | 246 | /* if we have all the headers we can stream */ |
241 | 247 | if (haveHeaders) { |
| 248 | + /* discontinuous codecs do not need to wait for data to allow playback */ |
| 249 | + if (!complete && payload.isDiscontinuous()) { |
| 250 | + complete = true; |
| 251 | + } |
242 | 252 | if (complete && started) { |
243 | 253 | int ret; |
244 | 254 | com.fluendo.jst.Buffer data = bufferFromPacket (op); |
Index: trunk/cortado/src/com/fluendo/plugin/VorbisDec.java |
— | — | @@ -56,6 +56,10 @@ |
57 | 57 | { |
58 | 58 | return true; |
59 | 59 | } |
| 60 | + public boolean isDiscontinuous () |
| 61 | + { |
| 62 | + return false; |
| 63 | + } |
60 | 64 | public long getFirstTs (Vector packets) |
61 | 65 | { |
62 | 66 | int len = packets.size(); |
Index: trunk/cortado/src/com/fluendo/plugin/Selector.java |
— | — | @@ -0,0 +1,137 @@ |
| 2 | +/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 3 | + * |
| 4 | + * This library is free software; you can redistribute it and/or |
| 5 | + * modify it under the terms of the GNU Library General Public |
| 6 | + * License as published by the Free Software Foundation; either |
| 7 | + * version 2 of the License, or (at your option) any later version. |
| 8 | + * |
| 9 | + * This library is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | + * Library General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU Library General Public |
| 15 | + * License along with this library; if not, write to the |
| 16 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 17 | + * Boston, MA 02111-1307, USA. |
| 18 | + */ |
| 19 | + |
| 20 | +package com.fluendo.plugin; |
| 21 | + |
| 22 | +import java.util.*; |
| 23 | +import java.awt.*; |
| 24 | +import com.fluendo.jst.*; |
| 25 | +import com.fluendo.utils.*; |
| 26 | + |
| 27 | +/** |
| 28 | + * This element receives data from N sinks, and selects one of them |
| 29 | + * to send from its source. |
| 30 | + */ |
| 31 | +public class Selector extends Element |
| 32 | +{ |
| 33 | + private Vector sinks = new Vector(); |
| 34 | + int selected = -1; |
| 35 | + Pad selectedPad = null; |
| 36 | + |
| 37 | + private Pad srcPad = new Pad(Pad.SRC, "src") { |
| 38 | + /** |
| 39 | + * Pushes the event to every sink. |
| 40 | + */ |
| 41 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 42 | + boolean ret = true; |
| 43 | + for (int n=0; n<sinks.size(); ++n) { |
| 44 | + ret &= ((Pad)sinks.get(n)).pushEvent(event); |
| 45 | + } |
| 46 | + return ret; |
| 47 | + } |
| 48 | + }; |
| 49 | + |
| 50 | + private int findPad (Pad pad) { |
| 51 | + for (int n=0; n<sinks.size(); ++n) { |
| 52 | + if (sinks.get(n) == pad) |
| 53 | + return n; |
| 54 | + } |
| 55 | + return -1; |
| 56 | + } |
| 57 | + |
| 58 | + /** |
| 59 | + * Requests a new sink pad to be created for the given peer. |
| 60 | + * The caps do not matter, as Selector is a caps agnostic element. |
| 61 | + */ |
| 62 | + public Pad requestSinkPad(Pad peer) { |
| 63 | + Pad pad = new Pad(Pad.SINK, "sink"+sinks.size()) { |
| 64 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 65 | + if (selectedPad == this) { |
| 66 | + return srcPad.pushEvent (event); |
| 67 | + } |
| 68 | + return true; |
| 69 | + } |
| 70 | + |
| 71 | + protected int chainFunc (com.fluendo.jst.Buffer buf) { |
| 72 | + int result = Pad.OK; |
| 73 | + |
| 74 | + //Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf ); |
| 75 | + Debug.debug("Selector got "+buf.caps+" buffer on "+this.toString()); |
| 76 | + |
| 77 | + if (selectedPad == this) { |
| 78 | + Debug.debug("what a coincidence, we're selected - pushing"); |
| 79 | + result = srcPad.push(buf); |
| 80 | + } |
| 81 | + |
| 82 | + return result; |
| 83 | + } |
| 84 | + |
| 85 | + protected boolean activateFunc (int mode) |
| 86 | + { |
| 87 | + return true; |
| 88 | + } |
| 89 | + }; |
| 90 | + |
| 91 | + sinks.addElement(pad); |
| 92 | + addPad(pad); |
| 93 | + return pad; |
| 94 | + } |
| 95 | + |
| 96 | + public Selector() { |
| 97 | + super(); |
| 98 | + |
| 99 | + addPad (srcPad); |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * The selected sink may be selected via the "selected" property - negative to select nothing |
| 104 | + */ |
| 105 | + public boolean setProperty (String name, java.lang.Object value) { |
| 106 | + if (name.equals("selected")) { |
| 107 | + int new_selected = Integer.valueOf(value.toString()).intValue(); |
| 108 | + Debug.info("Selector: request to select "+new_selected+" (from "+selected+"), within 0-"+(sinks.size()-1)); |
| 109 | + if (new_selected < 0 || new_selected >= sinks.size()) { |
| 110 | + selected = -1; |
| 111 | + selectedPad = null; |
| 112 | + } |
| 113 | + else { |
| 114 | + selected = new_selected; |
| 115 | + selectedPad = (Pad)sinks.get(selected); |
| 116 | + } |
| 117 | + } |
| 118 | + else { |
| 119 | + return super.setProperty(name, value); |
| 120 | + } |
| 121 | + |
| 122 | + return true; |
| 123 | + } |
| 124 | + |
| 125 | + public java.lang.Object getProperty (String name) { |
| 126 | + if (name.equals("selected")) { |
| 127 | + return new Integer(selected); |
| 128 | + } |
| 129 | + else { |
| 130 | + return super.getProperty(name); |
| 131 | + } |
| 132 | + } |
| 133 | + |
| 134 | + public String getFactoryName () |
| 135 | + { |
| 136 | + return "selector"; |
| 137 | + } |
| 138 | +} |
Index: trunk/cortado/src/com/fluendo/plugin/Overlay.java |
— | — | @@ -0,0 +1,122 @@ |
| 2 | +/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 3 | + * |
| 4 | + * This library is free software; you can redistribute it and/or |
| 5 | + * modify it under the terms of the GNU Library General Public |
| 6 | + * License as published by the Free Software Foundation; either |
| 7 | + * version 2 of the License, or (at your option) any later version. |
| 8 | + * |
| 9 | + * This library is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | + * Library General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU Library General Public |
| 15 | + * License along with this library; if not, write to the |
| 16 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 17 | + * Boston, MA 02111-1307, USA. |
| 18 | + */ |
| 19 | + |
| 20 | +package com.fluendo.plugin; |
| 21 | + |
| 22 | +import java.util.*; |
| 23 | +import java.awt.*; |
| 24 | +import com.fluendo.jst.*; |
| 25 | +import com.fluendo.utils.*; |
| 26 | + |
| 27 | +/** |
| 28 | + * This is a base overlay element, just passes images from sink to source. |
| 29 | + * Extend this and override the overlay function to draw something onto |
| 30 | + * images as they go from sink to source. |
| 31 | + */ |
| 32 | +public class Overlay extends Element |
| 33 | +{ |
| 34 | + protected Component component; |
| 35 | + |
| 36 | + private Pad videoSrcPad = new Pad(Pad.SRC, "videosrc") { |
| 37 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 38 | + return videoSinkPad.pushEvent(event); |
| 39 | + } |
| 40 | + }; |
| 41 | + |
| 42 | + private Pad videoSinkPad = new Pad(Pad.SINK, "videosink") { |
| 43 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 44 | + return videoSrcPad.pushEvent (event); |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Receives an image, allows a derived class to overlay whatever it wants on it, |
| 49 | + * and sends it to the video source pad. |
| 50 | + */ |
| 51 | + protected int chainFunc (com.fluendo.jst.Buffer buf) { |
| 52 | + int result; |
| 53 | + |
| 54 | + Debug.log( Debug.DEBUG, parent.getName() + " <<< " + buf ); |
| 55 | + |
| 56 | + overlay(buf); |
| 57 | + |
| 58 | + result = videoSrcPad.push(buf); |
| 59 | + if (result != Pad.OK) { |
| 60 | + Debug.log( Debug.WARNING, parent.getName() + ": failed to push buffer to video source pad: "+result); |
| 61 | + } |
| 62 | + |
| 63 | + return result; |
| 64 | + } |
| 65 | + |
| 66 | + protected boolean activateFunc (int mode) |
| 67 | + { |
| 68 | + return true; |
| 69 | + } |
| 70 | + }; |
| 71 | + |
| 72 | + public Overlay() { |
| 73 | + super(); |
| 74 | + |
| 75 | + addPad (videoSinkPad); |
| 76 | + addPad (videoSrcPad); |
| 77 | + } |
| 78 | + |
| 79 | + /** |
| 80 | + * this function may be overridden to draw whatever the derived |
| 81 | + * class wants onto the incoming image. |
| 82 | + * By default, the image is passed without alteration. |
| 83 | + */ |
| 84 | + protected void overlay(com.fluendo.jst.Buffer buf) { |
| 85 | + /* straight pass through by default */ |
| 86 | + } |
| 87 | + |
| 88 | + public boolean setProperty (String name, java.lang.Object value) { |
| 89 | + if (name.equals("component")) { |
| 90 | + component = (Component) value; |
| 91 | + } |
| 92 | + else { |
| 93 | + return super.setProperty(name, value); |
| 94 | + } |
| 95 | + |
| 96 | + return true; |
| 97 | + } |
| 98 | + |
| 99 | + public java.lang.Object getProperty (String name) { |
| 100 | + if (name.equals("component")) { |
| 101 | + return component; |
| 102 | + } |
| 103 | + else { |
| 104 | + return super.getProperty(name); |
| 105 | + } |
| 106 | + } |
| 107 | + |
| 108 | + /* from the video sink code, I do not understand what this does semantically, |
| 109 | + the frame would be 0x0 sized. Maybe just to avoid possible null dereference, |
| 110 | + but I suspect there might be something more clever, so it goes in for safety */ |
| 111 | + protected int changeState (int transition) { |
| 112 | + if (currentState == STOP && pendingState == PAUSE && component == null) { |
| 113 | + Frame frame = new Frame(); |
| 114 | + component = (Component) frame; |
| 115 | + } |
| 116 | + return super.changeState(transition); |
| 117 | + } |
| 118 | + |
| 119 | + public String getFactoryName () |
| 120 | + { |
| 121 | + return "overlay"; |
| 122 | + } |
| 123 | +} |
Index: trunk/cortado/src/com/fluendo/plugin/TextOverlay.java |
— | — | @@ -0,0 +1,114 @@ |
| 2 | +/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlecode.com> |
| 3 | + * |
| 4 | + * This library is free software; you can redistribute it and/or |
| 5 | + * modify it under the terms of the GNU Library General Public |
| 6 | + * License as published by the Free Software Foundation; either |
| 7 | + * version 2 of the License, or (at your option) any later version. |
| 8 | + * |
| 9 | + * This library is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | + * Library General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU Library General Public |
| 15 | + * License along with this library; if not, write to the |
| 16 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 17 | + * Boston, MA 02111-1307, USA. |
| 18 | + */ |
| 19 | + |
| 20 | +package com.fluendo.plugin; |
| 21 | + |
| 22 | +import java.util.*; |
| 23 | +import java.awt.*; |
| 24 | +import java.awt.image.*; |
| 25 | +import com.fluendo.jst.*; |
| 26 | +import com.fluendo.utils.*; |
| 27 | + |
| 28 | +/** |
| 29 | + * This class displays a simple text string on top of incoming video. |
| 30 | + */ |
| 31 | +public class TextOverlay extends Overlay |
| 32 | +{ |
| 33 | + private BufferedImage bimg = null; |
| 34 | + private Font font = null; |
| 35 | + private String text = null; |
| 36 | + |
| 37 | + public TextOverlay() { |
| 38 | + super(); |
| 39 | + } |
| 40 | + |
| 41 | + /** |
| 42 | + * Display a text string (from a property) onto the image. |
| 43 | + */ |
| 44 | + protected void overlay(com.fluendo.jst.Buffer buf) { |
| 45 | + Image img; |
| 46 | + |
| 47 | + /* img retrieval from VideoSink.java */ |
| 48 | + if (buf.object instanceof ImageProducer) { |
| 49 | + img = component.createImage((ImageProducer)buf.object); |
| 50 | + } |
| 51 | + else if (buf.object instanceof Image) { |
| 52 | + img = (Image)buf.object; |
| 53 | + } |
| 54 | + else { |
| 55 | + System.out.println(this+": unknown buffer received "+buf); |
| 56 | + return; |
| 57 | + } |
| 58 | + |
| 59 | + Dimension d = component.getSize(); |
| 60 | + int x = 0; |
| 61 | + int y = 0; |
| 62 | + int w = d.width; |
| 63 | + int h = d.height; |
| 64 | + |
| 65 | + /* based on a java SDK example */ |
| 66 | + if (bimg == null || bimg.getWidth() != w || bimg.getHeight() != h) { |
| 67 | + bimg = component.getGraphicsConfiguration().createCompatibleImage(w, h); |
| 68 | + int font_size = w / 32; |
| 69 | + if (font_size < 12) font_size = 12; |
| 70 | + font = new Font("sans", Font.BOLD, font_size); // TODO: should be selectable ? |
| 71 | + } |
| 72 | + |
| 73 | + Graphics2D g2 = bimg.createGraphics(); |
| 74 | + g2.drawImage(img, x, y, w, h, null); |
| 75 | + |
| 76 | + /* render text on top */ |
| 77 | + if (text != null) { |
| 78 | + double tw; |
| 79 | + g2.setFont(font); |
| 80 | + g2.setColor(Color.white); |
| 81 | + FontMetrics fm = g2.getFontMetrics(); |
| 82 | + tw = fm.stringWidth(text); |
| 83 | + g2.drawString(text, x+(int)((w-tw)/2), y+(int)(h*0.85)); |
| 84 | + } |
| 85 | + |
| 86 | + g2.dispose(); |
| 87 | + |
| 88 | + buf.object = bimg; |
| 89 | + } |
| 90 | + |
| 91 | + public boolean setProperty (String name, java.lang.Object value) { |
| 92 | + if (name.equals("text")) { |
| 93 | + text = value.toString(); |
| 94 | + } |
| 95 | + else { |
| 96 | + return super.setProperty(name, value); |
| 97 | + } |
| 98 | + |
| 99 | + return true; |
| 100 | + } |
| 101 | + |
| 102 | + public java.lang.Object getProperty (String name) { |
| 103 | + if (name.equals("text")) { |
| 104 | + return text; |
| 105 | + } |
| 106 | + else { |
| 107 | + return super.getProperty(name); |
| 108 | + } |
| 109 | + } |
| 110 | + |
| 111 | + public String getFactoryName () |
| 112 | + { |
| 113 | + return "textoverlay"; |
| 114 | + } |
| 115 | +} |
Index: trunk/cortado/src/com/fluendo/plugin/KateOverlay.java |
— | — | @@ -0,0 +1,121 @@ |
| 2 | +/* Copyright (C) <2008> ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> |
| 3 | + * |
| 4 | + * This library is free software; you can redistribute it and/or |
| 5 | + * modify it under the terms of the GNU Library General Public |
| 6 | + * License as published by the Free Software Foundation; either |
| 7 | + * version 2 of the License, or (at your option) any later version. |
| 8 | + * |
| 9 | + * This library is distributed in the hope that it will be useful, |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 12 | + * Library General Public License for more details. |
| 13 | + * |
| 14 | + * You should have received a copy of the GNU Library General Public |
| 15 | + * License along with this library; if not, write to the |
| 16 | + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 17 | + * Boston, MA 02111-1307, USA. |
| 18 | + */ |
| 19 | + |
| 20 | +package com.fluendo.plugin; |
| 21 | + |
| 22 | +import java.util.*; |
| 23 | +import java.awt.*; |
| 24 | +import java.awt.image.*; |
| 25 | +import com.fluendo.jst.*; |
| 26 | +import com.fluendo.jkate.Event; |
| 27 | +import com.fluendo.jtiger.Renderer; |
| 28 | +import com.fluendo.utils.*; |
| 29 | + |
| 30 | +/* This element renders a Kate stream on incoming video */ |
| 31 | +public class KateOverlay extends Overlay |
| 32 | +{ |
| 33 | + private BufferedImage bimg = null; |
| 34 | + private Font font = null; |
| 35 | + private String text = null; |
| 36 | + private Renderer tr = new Renderer(); |
| 37 | + |
| 38 | + private Pad kateSinkPad = new Pad(Pad.SINK, "katesink") { |
| 39 | + protected boolean eventFunc (com.fluendo.jst.Event event) { |
| 40 | + /* don't propagate, the video sink is the master */ |
| 41 | + return true; |
| 42 | + } |
| 43 | + |
| 44 | + /** |
| 45 | + * This pad receives Kate events, and add them to the renderer. |
| 46 | + * They will be removed from it as they become inactive. |
| 47 | + */ |
| 48 | + protected synchronized int chainFunc (com.fluendo.jst.Buffer buf) { |
| 49 | + addKateEvent((com.fluendo.jkate.Event)buf.object); |
| 50 | + return Pad.OK; |
| 51 | + } |
| 52 | + }; |
| 53 | + |
| 54 | + /** |
| 55 | + * Create a new Kate overlay |
| 56 | + */ |
| 57 | + public KateOverlay() { |
| 58 | + super(); |
| 59 | + addPad(kateSinkPad); |
| 60 | + } |
| 61 | + |
| 62 | + |
| 63 | + /** |
| 64 | + * Add a new Kate event to the renderer. |
| 65 | + * This needs locking so the Kate events are not changed while the |
| 66 | + * overlay is rendering them to an image. |
| 67 | + */ |
| 68 | + protected synchronized void addKateEvent(com.fluendo.jkate.Event ev) { |
| 69 | + tr.add(ev); |
| 70 | + Debug.log(Debug.DEBUG, "Kate overlay got Kate event: "+new String(ev.text)); |
| 71 | + } |
| 72 | + |
| 73 | + /** |
| 74 | + * Overlay the Kate renderer onto the given image. |
| 75 | + */ |
| 76 | + protected synchronized void overlay(com.fluendo.jst.Buffer buf) { |
| 77 | + Image img; |
| 78 | + |
| 79 | + if (buf.object instanceof ImageProducer) { |
| 80 | + img = component.createImage((ImageProducer)buf.object); |
| 81 | + } |
| 82 | + else if (buf.object instanceof Image) { |
| 83 | + img = (Image)buf.object; |
| 84 | + } |
| 85 | + else { |
| 86 | + System.out.println(this+": unknown buffer received "+buf); |
| 87 | + return; |
| 88 | + } |
| 89 | + |
| 90 | + /* before rendering, we update the state of the events; for now this |
| 91 | + just weeds out old ones, but at some point motions could be tracked. */ |
| 92 | + int ret = tr.update(component, buf.timestamp/(double)Clock.SECOND); |
| 93 | + /* if there are no Kate events active, just return the buffer as is */ |
| 94 | + if (ret == 1) |
| 95 | + return; |
| 96 | + |
| 97 | + Dimension d = component.getSize(); |
| 98 | + int x = 0; |
| 99 | + int y = 0; |
| 100 | + int w = d.width; |
| 101 | + int h = d.height; |
| 102 | + |
| 103 | + if (bimg == null || bimg.getWidth() != w || bimg.getHeight() != h) { |
| 104 | + bimg = component.getGraphicsConfiguration().createCompatibleImage(w, h); |
| 105 | + } |
| 106 | + |
| 107 | + Graphics2D g2 = bimg.createGraphics(); |
| 108 | + g2.drawImage(img, x, y, w, h, null); |
| 109 | + |
| 110 | + /* render Kate stream on top */ |
| 111 | + tr.render(component, bimg); |
| 112 | + |
| 113 | + g2.dispose(); |
| 114 | + |
| 115 | + buf.object = bimg; |
| 116 | + } |
| 117 | + |
| 118 | + public String getFactoryName () |
| 119 | + { |
| 120 | + return "kateoverlay"; |
| 121 | + } |
| 122 | +} |
Index: trunk/cortado/src/com/fluendo/plugin/OggPayload.java |
— | — | @@ -30,6 +30,7 @@ |
31 | 31 | public boolean isType (Packet op); |
32 | 32 | /** |
33 | 33 | * Initialize the payload with a header packet. |
| 34 | + * Returns < 0 for error, 0 if OK, 1 if OK and ready for decoding data. |
34 | 35 | */ |
35 | 36 | public int takeHeader (Packet op); |
36 | 37 | /** |
— | — | @@ -52,5 +53,10 @@ |
53 | 54 | * Get mime type |
54 | 55 | */ |
55 | 56 | public String getMime (); |
| 57 | + /** |
| 58 | + * Check if the stream is discontinuous (eg, no need to wait |
| 59 | + * for data on this stream before playing) |
| 60 | + */ |
| 61 | + public boolean isDiscontinuous (); |
56 | 62 | } |
57 | 63 | |
Index: trunk/cortado/src/com/fluendo/plugin/TheoraDec.java |
— | — | @@ -66,6 +66,10 @@ |
67 | 67 | { |
68 | 68 | return ts.isKeyframe(op); |
69 | 69 | } |
| 70 | + public boolean isDiscontinuous () |
| 71 | + { |
| 72 | + return false; |
| 73 | + } |
70 | 74 | public long getFirstTs (Vector packets) |
71 | 75 | { |
72 | 76 | int len = packets.size(); |
Index: trunk/cortado/README |
— | — | @@ -7,6 +7,8 @@ |
8 | 8 | - JST, a port of the GStreamer 0.10 design to Java |
9 | 9 | - jcraft, a copy of the JCraft JOgg/Jorbis code |
10 | 10 | - jheora, an implementation of Theora in Java |
| 11 | +- jkate, an implementation of a basic Kate decoder in Java |
| 12 | +- jtiger, a basic Kate renderer (simple text/images only for now) |
11 | 13 | - codecs (currently only containing the Smoke codec, a variant on Jpeg) |
12 | 14 | - JST plugins for: |
13 | 15 | - HTTP source element |
— | — | @@ -15,6 +17,9 @@ |
16 | 18 | - Vorbis and MuLaw audio decoders |
17 | 19 | - Java 1.1 sun.audio API audio sink |
18 | 20 | - Java 1.4 javax.sound.sampled API audio sink |
| 21 | + - Overlay element |
| 22 | + - Kate text decoder and overlay |
| 23 | + - Selector element |
19 | 24 | - examples |
20 | 25 | - applets |
21 | 26 | |
— | — | @@ -152,6 +157,13 @@ |
153 | 158 | resources to play an audio stream. true or false. |
154 | 159 | Defaults to true |
155 | 160 | |
| 161 | + kateIndex: int |
| 162 | + Use text from the given Kate stream (indexed from zero). |
| 163 | + The first Kate stream found will have index 0, the second will |
| 164 | + have index 1, etc. |
| 165 | + At most one Kate stream may be enabled at a time. |
| 166 | + Defaults to -1 (none) |
| 167 | + |
156 | 168 | statusHeight: int |
157 | 169 | The height of the status area (default 12) |
158 | 170 | |
Index: trunk/cortado/build.xml |
— | — | @@ -175,11 +175,14 @@ |
176 | 176 | <condition property="plugin.Vorbis.false"> |
177 | 177 | <contains string="${exclude}" substring="Vorbis" casesensitive="false" /> |
178 | 178 | </condition> |
| 179 | + <condition property="plugin.Kate.false"> |
| 180 | + <contains string="${exclude}" substring="Kate" casesensitive="false" /> |
| 181 | + </condition> |
179 | 182 | </target> |
180 | 183 | |
181 | 184 | <!-- generate includes and plugins.ini based on contents of exclude --> |
182 | 185 | <target name="includes" |
183 | | - depends="plugins,includes-delete,include-JPEG,include-Mulaw,include-Multipart,include-Ogg,include-Smoke,include-Theora,include-Vorbis"> |
| 186 | + depends="plugins,includes-delete,include-JPEG,include-Mulaw,include-Multipart,include-Ogg,include-Smoke,include-Theora,include-Vorbis,include-Kate"> |
184 | 187 | <echo>Generating ${out.buildtyped}/includes</echo> |
185 | 188 | </target> |
186 | 189 | |
— | — | @@ -192,8 +195,11 @@ |
193 | 196 | com/fluendo/jst/* |
194 | 197 | com/fluendo/plugin/AudioSink* |
195 | 198 | com/fluendo/plugin/VideoSink** |
| 199 | +com/fluendo/plugin/FakeSink* |
| 200 | +com/fluendo/plugin/Overlay* |
196 | 201 | com/fluendo/plugin/HTTPSrc* |
197 | 202 | com/fluendo/plugin/Queue* |
| 203 | +com/fluendo/plugin/Selector* |
198 | 204 | plugins.ini |
199 | 205 | </echo> |
200 | 206 | <echo file="${out.buildtyped}/plugins.ini" |
— | — | @@ -202,6 +208,9 @@ |
203 | 209 | com.fluendo.plugin.AudioSinkJ2 |
204 | 210 | com.fluendo.plugin.AudioSinkSA |
205 | 211 | com.fluendo.plugin.Queue |
| 212 | +com.fluendo.plugin.FakeSink |
| 213 | +com.fluendo.plugin.Overlay |
| 214 | +com.fluendo.plugin.Selector |
206 | 215 | </echo> |
207 | 216 | |
208 | 217 | </target> |
— | — | @@ -280,6 +289,19 @@ |
281 | 290 | </echo> |
282 | 291 | </target> |
283 | 292 | |
| 293 | + <target name="include-Kate" unless="plugin.Kate.false"> |
| 294 | + <echo>Including Kate</echo> |
| 295 | + <echo file="${out.buildtyped}/includes" append="true" |
| 296 | +>com/fluendo/jkate/* |
| 297 | +com/fluendo/jtiger/* |
| 298 | +com/fluendo/plugin/Kate* |
| 299 | +</echo> |
| 300 | + <echo file="${out.buildtyped}/plugins.ini" append="true" |
| 301 | +>com.fluendo.plugin.KateDec |
| 302 | +com.fluendo.plugin.KateOverlay |
| 303 | +</echo> |
| 304 | + </target> |
| 305 | + |
284 | 306 | <!-- COMPILATION --> |
285 | 307 | |
286 | 308 | <!-- FIXME: not used currently --> |
— | — | @@ -358,6 +380,36 @@ |
359 | 381 | </javac> |
360 | 382 | </target> |
361 | 383 | |
| 384 | + <target name="compile-jkate" |
| 385 | + description="compile com.fluendo.jkate source" |
| 386 | + depends="init,compile-utils,compile-jcraft" |
| 387 | + > |
| 388 | + <javac |
| 389 | + srcdir="${src}" |
| 390 | + destdir="${out.buildtyped}" |
| 391 | + target="1.1" source="1.3" |
| 392 | + debug="${build.isdebug}" debuglevel="${build.debuglevel}" |
| 393 | + > |
| 394 | + <include name="com/fluendo/jkate/**" /> |
| 395 | + <compilerarg line="${build.flags}" /> |
| 396 | + </javac> |
| 397 | + </target> |
| 398 | + |
| 399 | + <target name="compile-jtiger" |
| 400 | + description="compile com.fluendo.jtiger source" |
| 401 | + depends="init,compile-utils,compile-jkate" |
| 402 | + > |
| 403 | + <javac |
| 404 | + srcdir="${src}" |
| 405 | + destdir="${out.buildtyped}" |
| 406 | + target="1.1" source="1.3" |
| 407 | + debug="${build.isdebug}" debuglevel="${build.debuglevel}" |
| 408 | + > |
| 409 | + <include name="com/fluendo/jtiger/**" /> |
| 410 | + <compilerarg line="${build.flags}" /> |
| 411 | + </javac> |
| 412 | + </target> |
| 413 | + |
362 | 414 | <target name="compile-codecs" |
363 | 415 | description="compile com.fluendo.codecs source" |
364 | 416 | depends="init,compile-utils" |
— | — | @@ -439,7 +491,7 @@ |
440 | 492 | |
441 | 493 | <target name="compile" |
442 | 494 | description="compile the source" |
443 | | - depends="init,compile-stubs,compile-jcraft,compile-jst,compile-jheora,compile-codecs,compile-plugin,compile-player,compile-examples" /> |
| 495 | + depends="init,compile-stubs,compile-jcraft,compile-jst,compile-jheora,compile-jkate,compile-jtiger,compile-codecs,compile-plugin,compile-player,compile-examples" /> |
444 | 496 | |
445 | 497 | <!-- only here for reference --> |
446 | 498 | <target name="oldcompile"> |
— | — | @@ -494,6 +546,16 @@ |
495 | 547 | includes="com/fluendo/jheora/*" /> |
496 | 548 | </target> |
497 | 549 | |
| 550 | + <target name="jar-jkate" depends="compile-jkate"> |
| 551 | + <jar jarfile="${out.dist}/${build.type}/jkate.jar" basedir="${out.buildtyped}" |
| 552 | + includes="com/fluendo/jkate/*" /> |
| 553 | + </target> |
| 554 | + |
| 555 | + <target name="jar-jtiger" depends="compile-jtiger"> |
| 556 | + <jar jarfile="${out.dist}/${build.type}/jtiger.jar" basedir="${out.buildtyped}" |
| 557 | + includes="com/fluendo/jtiger/*" /> |
| 558 | + </target> |
| 559 | + |
498 | 560 | <target name="jar-jst" depends="compile-jst"> |
499 | 561 | <jar jarfile="${out.dist}/${build.type}/jst.jar" basedir="${out.buildtyped}" |
500 | 562 | includes="com/fluendo/jst/*" /> |
— | — | @@ -515,7 +577,7 @@ |
516 | 578 | <target name="applet-ovt" depends="compile" |
517 | 579 | description="generate the Ogg/Vorbis+Theora applet"> |
518 | 580 | <antcall target="includes"> |
519 | | - <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw" /> |
| 581 | + <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw,Kate" /> |
520 | 582 | </antcall> |
521 | 583 | <jar jarfile="${out.dist}/applet/cortado-ovt-${build.type}-${real_version}.jar" |
522 | 584 | includesfile="${out.buildtyped}/includes" |
— | — | @@ -526,7 +588,7 @@ |
527 | 589 | <target name="applet-ov" depends="compile" |
528 | 590 | description="generate the Ogg/Vorbis applet"> |
529 | 591 | <antcall target="includes"> |
530 | | - <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw,Theora" /> |
| 592 | + <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw,Theora,Kate" /> |
531 | 593 | </antcall> |
532 | 594 | <jar jarfile="${out.dist}/applet/cortado-ov-${build.type}-${real_version}.jar" |
533 | 595 | includesfile="${out.buildtyped}/includes" |
— | — | @@ -534,10 +596,21 @@ |
535 | 597 | </jar> |
536 | 598 | </target> |
537 | 599 | |
| 600 | + <target name="applet-ovtk" depends="compile" |
| 601 | + description="generate the Ogg/Vorbis+Theora+Kate applet"> |
| 602 | + <antcall target="includes"> |
| 603 | + <param name="exclude" value="Smoke,Jpeg,Multipart,Mulaw" /> |
| 604 | + </antcall> |
| 605 | + <jar jarfile="${out.dist}/applet/cortado-ovtk-${build.type}-${real_version}.jar" |
| 606 | + includesfile="${out.buildtyped}/includes" |
| 607 | + basedir="${out.buildtyped}"> |
| 608 | + </jar> |
| 609 | + </target> |
| 610 | + |
538 | 611 | <target name="applet-mmjs" depends="compile" |
539 | 612 | description="generate the Multipart/Mulaw+Smoke+Jpeg applet"> |
540 | 613 | <antcall target="includes"> |
541 | | - <param name="exclude" value="Ogg,Vorbis,Theora" /> |
| 614 | + <param name="exclude" value="Ogg,Vorbis,Theora,Kate" /> |
542 | 615 | </antcall> |
543 | 616 | <jar jarfile="${out.dist}/applet/cortado-mmjs-${build.type}-${real_version}.jar" |
544 | 617 | includesfile="${out.buildtyped}/includes" |
— | — | @@ -546,10 +619,10 @@ |
547 | 620 | </target> |
548 | 621 | |
549 | 622 | |
550 | | - <target name="applet" depends="applet-ovt,applet-ov,applet-mmjs" |
| 623 | + <target name="applet" depends="applet-ovt,applet-ov,applet-ovtk,applet-mmjs" |
551 | 624 | description="generate all applets" /> |
552 | 625 | |
553 | | - <target name="jar" depends="jar-jcraft,jar-utils,jar-jheora,jar-jst,jar-codecs,jar-plugin,jar-player" |
| 626 | + <target name="jar" depends="jar-jcraft,jar-utils,jar-jheora,jar-jkate,jar-jtiger,jar-jst,jar-codecs,jar-plugin,jar-player" |
554 | 627 | description="generate all jar files" /> |
555 | 628 | |
556 | 629 | <!-- instead of using depends, which doesn't necessarily preserve order, |
— | — | @@ -641,6 +714,8 @@ |
642 | 715 | <include name="src/com/jcraft/jogg/*.java" /> |
643 | 716 | <include name="src/com/jcraft/jorbis/*.java" /> |
644 | 717 | <include name="src/com/fluendo/jheora/*.java" /> |
| 718 | + <include name="src/com/fluendo/jkate/*.java" /> |
| 719 | + <include name="src/com/fluendo/jtiger/*.java" /> |
645 | 720 | <include name="src/com/fluendo/player/*.java" /> |
646 | 721 | <include name="src/com/fluendo/utils/*.java" /> |
647 | 722 | <include name="src/com/fluendo/codecs/*.java" /> |
Index: trunk/cortado/plugins.ini |
— | — | @@ -3,9 +3,14 @@ |
4 | 4 | com.fluendo.plugin.VideoSink |
5 | 5 | com.fluendo.plugin.AudioSinkJ2 |
6 | 6 | com.fluendo.plugin.AudioSinkSA |
| 7 | +com.fluendo.plugin.Overlay |
| 8 | +com.fluendo.plugin.TextOverlay |
| 9 | +com.fluendo.plugin.KateOverlay |
| 10 | +com.fluendo.plugin.Selector |
7 | 11 | com.fluendo.plugin.OggDemux |
8 | 12 | com.fluendo.plugin.TheoraDec |
9 | 13 | com.fluendo.plugin.VorbisDec |
| 14 | +com.fluendo.plugin.KateDec |
10 | 15 | com.fluendo.plugin.Queue |
11 | 16 | com.fluendo.plugin.MultipartDemux |
12 | 17 | com.fluendo.plugin.JPEGDec |