Revisão | 105 (tree) |
---|---|
Hora | 2014-12-07 22:25:15 |
Autor | ![]() |
jAVIlibを追加。
java.awt.imageパッケージやjavax.imageioパッケージを参照している。
Androidでは上記のパッケージを参照できないため、ビルドエラーとなる。
@@ -0,0 +1,175 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package test; | |
30 | + | |
31 | +import java.awt.Graphics; | |
32 | +import java.awt.Graphics2D; | |
33 | +import java.awt.RenderingHints; | |
34 | +import java.awt.geom.AffineTransform; | |
35 | +import java.awt.image.BufferedImage; | |
36 | +import java.io.IOException; | |
37 | +import java.util.logging.Level; | |
38 | +import java.util.logging.Logger; | |
39 | +import javax.swing.JFrame; | |
40 | +import javax.swing.WindowConstants; | |
41 | +import javilib.Avi; | |
42 | +import javilib.Debug; | |
43 | +import javilib.StreamRec; | |
44 | + | |
45 | +/** | |
46 | + * | |
47 | + * @author lenny | |
48 | + */ | |
49 | +public class Transcoder extends JFrame implements Runnable { | |
50 | + | |
51 | + private Thread thread; | |
52 | + private boolean running; | |
53 | + // | |
54 | + private final Avi mvIn = new Avi(); | |
55 | + private final Avi mvOut = new Avi(); | |
56 | + private BufferedImage buffer; | |
57 | + private int frame; | |
58 | + | |
59 | + public Transcoder() { | |
60 | + | |
61 | + try { | |
62 | + | |
63 | + Debug.enable = false; | |
64 | + | |
65 | + mvIn.openRead("/home/lenny/junk/desktop/psp/giardini/MOV00018.AVI"); | |
66 | + mvOut.openWrite("/home/lenny/test.avi", StreamRec.RecFormat.MJPEG); | |
67 | + mvOut.setOption(0, Avi.Option.WIDTH, mvIn.header.Width); | |
68 | + mvOut.setOption(0, Avi.Option.HEIGHT, mvIn.header.Height); | |
69 | + mvOut.setOption(0, Avi.Option.FRAMERATE, 1000000 / mvIn.header.MicroSecPerFrame); | |
70 | + mvOut.setOption(0, Avi.Option.QUALITY, 10); | |
71 | + | |
72 | + buffer = new BufferedImage( | |
73 | + mvIn.header.Width, mvIn.header.Height, | |
74 | + BufferedImage.TYPE_3BYTE_BGR); | |
75 | + | |
76 | + setSize(mvIn.header.Width, mvIn.header.Height); | |
77 | + | |
78 | + setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); | |
79 | + | |
80 | + } catch (IOException ex) { | |
81 | + Logger.getLogger(Transcoder.class.getName()).log(Level.SEVERE, null, ex); | |
82 | + } | |
83 | + } | |
84 | + | |
85 | + public void start() { | |
86 | + | |
87 | + if (!running) { | |
88 | + | |
89 | + thread = new Thread(this); | |
90 | + running = true; | |
91 | + | |
92 | + setVisible(true); | |
93 | + thread.start(); | |
94 | + } | |
95 | + } | |
96 | + | |
97 | + public void stop() { | |
98 | + | |
99 | + if (running) { | |
100 | + | |
101 | + running = false; | |
102 | + | |
103 | + try { | |
104 | + thread.join(); | |
105 | + } catch (InterruptedException ex) { | |
106 | + Logger.getLogger(Transcoder.class.getName()).log(Level.SEVERE, null, ex); | |
107 | + } | |
108 | + } | |
109 | + } | |
110 | + | |
111 | + public boolean isRunning() { | |
112 | + return running; | |
113 | + } | |
114 | + | |
115 | + @Override | |
116 | + public void run() { | |
117 | + | |
118 | + try { | |
119 | + | |
120 | + while (running) { | |
121 | + | |
122 | + if (frame == mvIn.header.TotalFrames) { | |
123 | + break; | |
124 | + } | |
125 | + | |
126 | + mvIn.readFrame(frame, 0, buffer); | |
127 | + mvOut.writeFrame(frame, buffer); | |
128 | + | |
129 | + repaint(); | |
130 | + | |
131 | + frame++; | |
132 | + } | |
133 | + | |
134 | + mvIn.closeRead(); | |
135 | + mvOut.closeWrite(); | |
136 | + | |
137 | + dispose(); | |
138 | + | |
139 | + } catch (IOException ex) { | |
140 | + Logger.getLogger(Transcoder.class.getName()).log(Level.SEVERE, null, ex); | |
141 | + } | |
142 | + } | |
143 | + | |
144 | + @Override | |
145 | + public void paint(Graphics g) { | |
146 | + | |
147 | + if (buffer != null) { | |
148 | + | |
149 | + AffineTransform at = new AffineTransform(); | |
150 | + at.setToTranslation(getWidth() / 2, getHeight() / 2); | |
151 | + at.rotate(0.3); | |
152 | + at.translate(-getWidth() / 2, -getHeight() / 2); | |
153 | + | |
154 | + Graphics2D g2 = (Graphics2D) g; | |
155 | + | |
156 | + RenderingHints rh = new RenderingHints( | |
157 | + RenderingHints.KEY_INTERPOLATION, | |
158 | + RenderingHints.VALUE_INTERPOLATION_BICUBIC); | |
159 | + | |
160 | + g2.setRenderingHints(rh); | |
161 | + | |
162 | + g2.drawImage(buffer, at, null); | |
163 | + | |
164 | + } else { | |
165 | + super.paint(g); | |
166 | + } | |
167 | + } | |
168 | + | |
169 | + /** | |
170 | + * @param args the command line arguments | |
171 | + */ | |
172 | + public static void main(String[] args) { | |
173 | + new Transcoder().start(); | |
174 | + } | |
175 | +} |
@@ -0,0 +1,209 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package test; | |
30 | + | |
31 | +import java.awt.Frame; | |
32 | +import java.awt.Graphics; | |
33 | +import java.awt.event.WindowEvent; | |
34 | +import java.awt.event.WindowListener; | |
35 | +import java.awt.image.BufferedImage; | |
36 | +import java.io.IOException; | |
37 | +import java.util.logging.Level; | |
38 | +import java.util.logging.Logger; | |
39 | +import javilib.Avi; | |
40 | +import javilib.Debug; | |
41 | + | |
42 | +/** | |
43 | + * | |
44 | + * @author lenny | |
45 | + */ | |
46 | +public class Player | |
47 | + extends Frame | |
48 | + implements Runnable, WindowListener { | |
49 | + | |
50 | + private Thread thread; | |
51 | + private boolean running; | |
52 | + // | |
53 | + private final long startTime = System.currentTimeMillis(); | |
54 | + // | |
55 | + private int nextTime; | |
56 | + private boolean frameSkip; | |
57 | + private int frameNum; | |
58 | + // | |
59 | + private final Avi mvIn = new Avi(); | |
60 | + private BufferedImage buffer; | |
61 | + | |
62 | + public void start(String fn) { | |
63 | + | |
64 | + Debug.enable = false; | |
65 | + | |
66 | + addWindowListener(this); | |
67 | + | |
68 | + try { | |
69 | + mvIn.openRead(fn); | |
70 | + } catch (IOException ex) { | |
71 | + Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex); | |
72 | + } | |
73 | + | |
74 | + buffer = new BufferedImage( | |
75 | + mvIn.header.Width, mvIn.header.Height, | |
76 | + BufferedImage.TYPE_3BYTE_BGR); | |
77 | + | |
78 | + thread = new Thread(this); | |
79 | + running = true; | |
80 | + | |
81 | + setSize(mvIn.header.Width, mvIn.header.Height); | |
82 | + setVisible(true); | |
83 | + | |
84 | + thread.start(); | |
85 | + } | |
86 | + | |
87 | + @Override | |
88 | + public void run() { | |
89 | + | |
90 | + while (running) { | |
91 | + | |
92 | + if (!frameSkip) { | |
93 | + try { | |
94 | + | |
95 | + mvIn.readFrame(frameNum, 0, buffer); | |
96 | + repaint(); | |
97 | + | |
98 | + } catch (IOException ex) { | |
99 | + Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex); | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + sync(); | |
104 | + | |
105 | + frameNum++; | |
106 | + | |
107 | + if (frameNum == mvIn.header.TotalFrames) { | |
108 | + running = false; | |
109 | + } | |
110 | + } | |
111 | + | |
112 | + try { | |
113 | + mvIn.closeRead(); | |
114 | + } catch (IOException ex) { | |
115 | + Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex); | |
116 | + } | |
117 | + | |
118 | + setVisible(false); | |
119 | + dispose(); | |
120 | + } | |
121 | + | |
122 | + public void sync() { | |
123 | + | |
124 | + nextTime += mvIn.header.MicroSecPerFrame / 1000; | |
125 | + | |
126 | + int now = (int) (System.currentTimeMillis() - startTime); | |
127 | + int dt = nextTime - now; | |
128 | + | |
129 | + if (dt > 0) { | |
130 | + | |
131 | + frameSkip = false; | |
132 | + | |
133 | + try { | |
134 | + Thread.sleep(dt); | |
135 | + } catch (InterruptedException ex) { | |
136 | + Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex); | |
137 | + } | |
138 | + | |
139 | + } else if (dt > -100) { | |
140 | + | |
141 | + frameSkip = true; | |
142 | + | |
143 | + } else { | |
144 | + | |
145 | + nextTime = now; | |
146 | + frameSkip = false; | |
147 | + } | |
148 | + } | |
149 | + | |
150 | + @Override | |
151 | + public void update(Graphics g) { | |
152 | + paint(g); | |
153 | + } | |
154 | + | |
155 | + @Override | |
156 | + public void paint(Graphics g) { | |
157 | + if (buffer != null) { | |
158 | + g.drawImage(buffer, 0, 0, getWidth(), getHeight(), null); | |
159 | + } else { | |
160 | + super.paint(g); | |
161 | + } | |
162 | + } | |
163 | + | |
164 | + @Override | |
165 | + public void windowOpened(WindowEvent e) { | |
166 | + } | |
167 | + | |
168 | + @Override | |
169 | + public void windowClosing(WindowEvent e) { | |
170 | + running = false; | |
171 | + } | |
172 | + | |
173 | + @Override | |
174 | + public void windowClosed(WindowEvent e) { | |
175 | + } | |
176 | + | |
177 | + @Override | |
178 | + public void windowIconified(WindowEvent e) { | |
179 | + } | |
180 | + | |
181 | + @Override | |
182 | + public void windowDeiconified(WindowEvent e) { | |
183 | + } | |
184 | + | |
185 | + @Override | |
186 | + public void windowActivated(WindowEvent e) { | |
187 | + } | |
188 | + | |
189 | + @Override | |
190 | + public void windowDeactivated(WindowEvent e) { | |
191 | + } | |
192 | + | |
193 | + /** | |
194 | + * @param args the command line arguments | |
195 | + */ | |
196 | + public static void main(String[] args) { | |
197 | + | |
198 | + if (args.length > 0) { | |
199 | + | |
200 | + Player p = new Player(); | |
201 | + p.setTitle("AVI MJPEG Player test - by Lenny 2012"); | |
202 | + p.start(args[0]); | |
203 | + | |
204 | + } else { | |
205 | + | |
206 | + System.out.println("Usage: Player <file.avi>"); | |
207 | + } | |
208 | + } | |
209 | +} |
@@ -0,0 +1,40 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +/** | |
32 | + * | |
33 | + * @author lenny | |
34 | + */ | |
35 | +public class Index { | |
36 | + | |
37 | + public int fcc; | |
38 | + public int size; | |
39 | + public IndexEntry[] entrys; | |
40 | +} |
@@ -0,0 +1,49 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class Chunk extends Writable { | |
38 | + | |
39 | + public int fcc; | |
40 | + public int size; | |
41 | + // -- | |
42 | + public static final int sizeof = 8; | |
43 | + | |
44 | + @Override | |
45 | + public void write(AviWriter writer) throws IOException { | |
46 | + Fcc.write(fcc, writer); | |
47 | + Fcc.write(size, writer); | |
48 | + } | |
49 | +} |
@@ -0,0 +1,40 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public abstract class Writable { | |
38 | + | |
39 | + public abstract void write(AviWriter writer) throws IOException; | |
40 | +} |
@@ -0,0 +1,56 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.FileInputStream; | |
32 | +import java.io.FileOutputStream; | |
33 | +import java.io.IOException; | |
34 | + | |
35 | +/** | |
36 | + * | |
37 | + * @author lenny | |
38 | + */ | |
39 | +public class Tcc { | |
40 | + | |
41 | + public static short read(FileInputStream in) throws IOException { | |
42 | + | |
43 | + short r = 0; | |
44 | + | |
45 | + r |= in.read() << 0; | |
46 | + r |= in.read() << 8; | |
47 | + | |
48 | + return r; | |
49 | + } | |
50 | + | |
51 | + public static void write(short tcc, FileOutputStream out) throws IOException { | |
52 | + | |
53 | + out.write((tcc >> 0) & 0xff); | |
54 | + out.write((tcc >> 8) & 0xff); | |
55 | + } | |
56 | +} |
@@ -0,0 +1,51 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class List extends Writable { | |
38 | + | |
39 | + public int fcc; | |
40 | + public int size; | |
41 | + public int ids; | |
42 | + // -- | |
43 | + public static final int sizeof = 12; | |
44 | + | |
45 | + @Override | |
46 | + public void write(AviWriter writer) throws IOException { | |
47 | + Fcc.write(fcc, writer); | |
48 | + Fcc.write(size, writer); | |
49 | + Fcc.write(ids, writer); | |
50 | + } | |
51 | +} |
@@ -0,0 +1,60 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.FileNotFoundException; | |
32 | +import java.io.FileOutputStream; | |
33 | +import java.io.IOException; | |
34 | + | |
35 | +/** | |
36 | + * | |
37 | + * @author lenny | |
38 | + */ | |
39 | +public class AviWriter extends FileOutputStream { | |
40 | + | |
41 | + public AviWriter(String fn) throws FileNotFoundException { | |
42 | + super(fn); | |
43 | + } | |
44 | + | |
45 | + public void seekRel(int off) throws IOException { | |
46 | + getChannel().position(getChannel().position() + off); | |
47 | + } | |
48 | + | |
49 | + public void seek(int off) throws IOException { | |
50 | + getChannel().position(off); | |
51 | + } | |
52 | + | |
53 | + public void seekEnd() throws IOException { | |
54 | + getChannel().position(getChannel().size()); | |
55 | + } | |
56 | + | |
57 | + public int tell() throws IOException { | |
58 | + return (int) getChannel().position(); | |
59 | + } | |
60 | +} |
@@ -0,0 +1,807 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.awt.image.BufferedImage; | |
32 | +import java.io.FileNotFoundException; | |
33 | +import java.io.IOException; | |
34 | + | |
35 | +/** | |
36 | + * | |
37 | + * @author lenny | |
38 | + */ | |
39 | +public class Avi { | |
40 | + | |
41 | + public AviReader reader; | |
42 | + public AviWriter writer; | |
43 | + public int size; | |
44 | + public MainHeader header; | |
45 | + public StreamRec[] streams; | |
46 | + public IndexEntry[] entries; | |
47 | + public int index_entries; | |
48 | + public int movi_offset; | |
49 | + public int read_offset; | |
50 | + public int[] offset_table; | |
51 | + public int interlace; | |
52 | + public int odd_fields; | |
53 | + | |
54 | + public enum Option { | |
55 | + | |
56 | + WIDTH, | |
57 | + HEIGHT, | |
58 | + QUALITY, | |
59 | + FRAMERATE | |
60 | + } | |
61 | + | |
62 | + public enum Error { | |
63 | + | |
64 | + NONE, | |
65 | + COMPRESSION, | |
66 | + OPEN, | |
67 | + READING, | |
68 | + WRITING, | |
69 | + FORMAT, | |
70 | + ALLOC, | |
71 | + FOUND, | |
72 | + OPTION | |
73 | + } | |
74 | + // | |
75 | + public static final int AVI_RIFF_SOFF = 4; | |
76 | + public static final int AVI_HDRL_SOFF = 16; | |
77 | + // | |
78 | + | |
79 | + public Error setOption(int stream, Option option, int value) throws IOException { | |
80 | + | |
81 | + int i; | |
82 | + | |
83 | + if (header.TotalFrames != 0) { | |
84 | + | |
85 | + Debug.print("Can't change params after we have already started writing frames\n"); | |
86 | + return Error.OPTION; | |
87 | + } | |
88 | + | |
89 | + switch (option) { | |
90 | + | |
91 | + case WIDTH: { | |
92 | + | |
93 | + header.Width = value; | |
94 | + header.SuggestedBufferSize = header.Width * header.Height * 3; | |
95 | + | |
96 | + for (i = 0; i < header.Streams; i++) { | |
97 | + | |
98 | + if (Fcc.get_format_type(streams[i].format) == Fcc.FCC("vids")) { | |
99 | + | |
100 | + ((BitmapInfoHeader) streams[i].sf).Width = value; | |
101 | + streams[i].sh.SuggestedBufferSize = header.SuggestedBufferSize; | |
102 | + streams[i].sh.right = (short) value; | |
103 | + ((BitmapInfoHeader) streams[i].sf).SizeImage = header.SuggestedBufferSize; | |
104 | + | |
105 | + writer.seek(offset_table[1 + i * 2 + 1]); | |
106 | + streams[i].sf.write(writer); | |
107 | + } | |
108 | + } | |
109 | + } | |
110 | + break; | |
111 | + | |
112 | + case HEIGHT: { | |
113 | + | |
114 | + header.Height = value; | |
115 | + header.SuggestedBufferSize = header.Width * header.Height * 3; | |
116 | + | |
117 | + for (i = 0; i < header.Streams; i++) { | |
118 | + | |
119 | + if (Fcc.get_format_type(streams[i].format) == Fcc.FCC("vids")) { | |
120 | + | |
121 | + ((BitmapInfoHeader) streams[i].sf).Height = value; | |
122 | + streams[i].sh.SuggestedBufferSize = header.SuggestedBufferSize; | |
123 | + streams[i].sh.bottom = (short) value; | |
124 | + ((BitmapInfoHeader) streams[i].sf).SizeImage = header.SuggestedBufferSize; | |
125 | + | |
126 | + writer.seek(offset_table[1 + i * 2 + 1]); | |
127 | + streams[i].sf.write(writer); | |
128 | + } | |
129 | + } | |
130 | + } | |
131 | + break; | |
132 | + | |
133 | + case QUALITY: { | |
134 | + | |
135 | + for (i = 0; i < header.Streams; i++) { | |
136 | + | |
137 | + if (Fcc.get_format_type(streams[i].format) == Fcc.FCC("vids")) { | |
138 | + | |
139 | + streams[i].sh.Quality = value * 100; | |
140 | + | |
141 | + writer.seek(offset_table[1 + i * 2 + 1]); | |
142 | + streams[i].sf.write(writer); | |
143 | + } | |
144 | + } | |
145 | + } | |
146 | + break; | |
147 | + | |
148 | + case FRAMERATE: { | |
149 | + | |
150 | + header.MicroSecPerFrame = 1000000 / value; | |
151 | + | |
152 | + for (i = 0; i < header.Streams; i++) { | |
153 | + | |
154 | + if (Fcc.get_format_type(streams[i].format) == Fcc.FCC("vids")) { | |
155 | + | |
156 | + streams[i].sh.Scale = header.MicroSecPerFrame; | |
157 | + | |
158 | + writer.seek(offset_table[1 + i * 2 + 1]); | |
159 | + streams[i].sf.write(writer); | |
160 | + } | |
161 | + } | |
162 | + } | |
163 | + break; | |
164 | + | |
165 | + default: | |
166 | + Debug.print("unsupported option\n"); | |
167 | + break; | |
168 | + } | |
169 | + | |
170 | + writer.seek(offset_table[0]); | |
171 | + header.write(writer); | |
172 | + | |
173 | + return Error.NONE; | |
174 | + } | |
175 | + | |
176 | + public Error openRead(String name) throws FileNotFoundException, IOException { | |
177 | + | |
178 | + reader = new AviReader(name); | |
179 | + | |
180 | + offset_table = null; | |
181 | + | |
182 | + if (Fcc.read(reader) != Fcc.FCC("RIFF")) { | |
183 | + | |
184 | + Debug.print("not RIFF\n"); | |
185 | + return Error.FORMAT; | |
186 | + } | |
187 | + | |
188 | + size = Fcc.read(reader); | |
189 | + | |
190 | + if (size == 0) { | |
191 | + | |
192 | + Debug.print("movie size is zero\n"); | |
193 | + return Error.FORMAT; | |
194 | + } | |
195 | + | |
196 | + header = new MainHeader(); | |
197 | + | |
198 | + if (Fcc.read(reader) != Fcc.FCC("AVI ") | |
199 | + || Fcc.read(reader) != Fcc.FCC("LIST") | |
200 | + || Fcc.read(reader) == 0 | |
201 | + || Fcc.read(reader) != Fcc.FCC("hdrl") | |
202 | + || (header.fcc = Fcc.read(reader)) != Fcc.FCC("avih") | |
203 | + || (header.size = Fcc.read(reader)) == 0) { | |
204 | + | |
205 | + Debug.print("bad initial header info\n"); | |
206 | + return Error.FORMAT; | |
207 | + } | |
208 | + | |
209 | + header.MicroSecPerFrame = Fcc.read(reader); | |
210 | + header.MaxBytesPerSec = Fcc.read(reader); | |
211 | + header.PaddingGranularity = Fcc.read(reader); | |
212 | + header.Flags = Fcc.read(reader); | |
213 | + header.TotalFrames = Fcc.read(reader); | |
214 | + header.InitialFrames = Fcc.read(reader); | |
215 | + header.Streams = Fcc.read(reader); | |
216 | + header.SuggestedBufferSize = Fcc.read(reader); | |
217 | + header.Width = Fcc.read(reader); | |
218 | + header.Height = Fcc.read(reader); | |
219 | + header.Reserved[0] = Fcc.read(reader); | |
220 | + header.Reserved[1] = Fcc.read(reader); | |
221 | + header.Reserved[2] = Fcc.read(reader); | |
222 | + header.Reserved[3] = Fcc.read(reader); | |
223 | + | |
224 | + reader.seekRel(header.size - 14 * 4); | |
225 | + | |
226 | + if (header.Streams < 1) { | |
227 | + | |
228 | + Debug.print("streams less than 1\n"); | |
229 | + return Error.FORMAT; | |
230 | + } | |
231 | + | |
232 | + streams = new StreamRec[header.Streams]; | |
233 | + | |
234 | + for (int i = 0; i < header.Streams; i++) { | |
235 | + | |
236 | + streams[i] = new StreamRec(); | |
237 | + | |
238 | + if (Fcc.read(reader) != Fcc.FCC("LIST") | |
239 | + || Fcc.read(reader) == 0 | |
240 | + || Fcc.read(reader) != Fcc.FCC("strl") | |
241 | + || (streams[i].sh.fcc = Fcc.read(reader)) != Fcc.FCC("strh") | |
242 | + || (streams[i].sh.size = Fcc.read(reader)) == 0) { | |
243 | + | |
244 | + Debug.print("bad stream header information\n"); | |
245 | + return Error.FORMAT; | |
246 | + } | |
247 | + | |
248 | + streams[i].sh.Type = Fcc.read(reader); | |
249 | + streams[i].sh.Handler = Fcc.read(reader); | |
250 | + | |
251 | + int fcca = streams[i].sh.Handler; | |
252 | + | |
253 | + if (streams[i].sh.Type == Fcc.FCC("vids")) { | |
254 | + if (fcca == Fcc.FCC("mjpg") || fcca == Fcc.FCC("MJPG")) { | |
255 | + streams[i].format = StreamRec.RecFormat.MJPEG; | |
256 | + } else if (fcca == Fcc.FCC("dib ") || fcca == Fcc.FCC("DIB ")) { | |
257 | + streams[i].format = StreamRec.RecFormat.RGB24; | |
258 | + } else { | |
259 | + Debug.print("unsupported compression\n"); | |
260 | + Debug.print(fcca); | |
261 | + return Error.COMPRESSION; | |
262 | + } | |
263 | + } | |
264 | + | |
265 | + streams[i].sh.Flags = Fcc.read(reader); | |
266 | + streams[i].sh.Priority = Tcc.read(reader); | |
267 | + streams[i].sh.Language = Tcc.read(reader); | |
268 | + streams[i].sh.InitialFrames = Fcc.read(reader); | |
269 | + streams[i].sh.Scale = Fcc.read(reader); | |
270 | + streams[i].sh.Rate = Fcc.read(reader); | |
271 | + streams[i].sh.Start = Fcc.read(reader); | |
272 | + streams[i].sh.Length = Fcc.read(reader); | |
273 | + streams[i].sh.SuggestedBufferSize = Fcc.read(reader); | |
274 | + streams[i].sh.Quality = Fcc.read(reader); | |
275 | + streams[i].sh.SampleSize = Fcc.read(reader); | |
276 | + streams[i].sh.left = Tcc.read(reader); | |
277 | + streams[i].sh.top = Tcc.read(reader); | |
278 | + streams[i].sh.right = Tcc.read(reader); | |
279 | + streams[i].sh.bottom = Tcc.read(reader); | |
280 | + | |
281 | + reader.seekRel(streams[i].sh.size - 14 * 4); | |
282 | + | |
283 | + if (Fcc.read(reader) != Fcc.FCC("strf")) { | |
284 | + | |
285 | + Debug.print("no stream format information\n"); | |
286 | + return Error.FORMAT; | |
287 | + } | |
288 | + | |
289 | + streams[i].sf_size = Fcc.read(reader); | |
290 | + | |
291 | + if (streams[i].sh.Type == Fcc.FCC("vids")) { | |
292 | + | |
293 | + int j = streams[i].sf_size - (BitmapInfoHeader.sizeof - 8); | |
294 | + | |
295 | + if (j >= 0) { | |
296 | + | |
297 | + BitmapInfoHeader sf = new BitmapInfoHeader(); | |
298 | + | |
299 | + streams[i].sf = sf; | |
300 | + streams[i].sf_size = BitmapInfoHeader.sizeof; | |
301 | + | |
302 | + sf.fcc = Fcc.FCC("strf"); | |
303 | + sf.size = streams[i].sf_size; | |
304 | + sf.Size = Fcc.read(reader); | |
305 | + sf.Width = Fcc.read(reader); | |
306 | + sf.Height = Fcc.read(reader); | |
307 | + sf.Planes = Tcc.read(reader); | |
308 | + sf.BitCount = Tcc.read(reader); | |
309 | + sf.Compression = Fcc.read(reader); | |
310 | + sf.SizeImage = Fcc.read(reader); | |
311 | + sf.XPelsPerMeter = Fcc.read(reader); | |
312 | + sf.YPelsPerMeter = Fcc.read(reader); | |
313 | + sf.ClrUsed = Fcc.read(reader); | |
314 | + sf.ClrImportant = Fcc.read(reader); | |
315 | + } | |
316 | + | |
317 | + if (j > 0) { | |
318 | + reader.seekRel(j); | |
319 | + } | |
320 | + | |
321 | + } else { | |
322 | + reader.seekRel(streams[i].sf_size); | |
323 | + } | |
324 | + | |
325 | + // Walk to the next LIST | |
326 | + while (Fcc.read(reader) != Fcc.FCC("LIST")) { | |
327 | + | |
328 | + int j = Fcc.read(reader); | |
329 | + | |
330 | + if (j < 0 || reader.tell() > size) { | |
331 | + Debug.print("incorrect size in header or error in AVI\n"); | |
332 | + return Error.FORMAT; | |
333 | + } | |
334 | + reader.seekRel(j); | |
335 | + } | |
336 | + | |
337 | + reader.seekRel(-4); | |
338 | + } | |
339 | + | |
340 | + int sz = 0; | |
341 | + | |
342 | + while (true) { | |
343 | + | |
344 | + int t = Fcc.read(reader); | |
345 | + sz = Fcc.read(reader); | |
346 | + | |
347 | + if (sz == 0) { | |
348 | + break; | |
349 | + } | |
350 | + | |
351 | + if (t == Fcc.FCC("LIST")) { | |
352 | + if (Fcc.read(reader) == Fcc.FCC("movi")) { | |
353 | + break; | |
354 | + } else { | |
355 | + reader.seekRel(sz - 4); | |
356 | + } | |
357 | + } else { | |
358 | + reader.seekRel(sz); | |
359 | + } | |
360 | + | |
361 | + if (reader.tell() > size) { | |
362 | + | |
363 | + Debug.print("incorrect size in header or error in AVI\n"); | |
364 | + return Error.FORMAT; | |
365 | + } | |
366 | + } | |
367 | + | |
368 | + movi_offset = reader.tell(); | |
369 | + read_offset = movi_offset; | |
370 | + | |
371 | + Debug.print("movi_offset is %d\n", movi_offset); | |
372 | + | |
373 | + // Read in the index if the file has one, otherwise create one | |
374 | + if ((header.Flags & MainHeader.AVIF_HASINDEX) != 0) { | |
375 | + | |
376 | + reader.seekRel(sz - 4); | |
377 | + | |
378 | + if (Fcc.read(reader) != Fcc.FCC("idx1")) { | |
379 | + | |
380 | + Debug.print("bad index information\n"); | |
381 | + return Error.FORMAT; | |
382 | + } | |
383 | + | |
384 | + index_entries = Fcc.read(reader) / IndexEntry.sizeof; | |
385 | + | |
386 | + if (index_entries == 0) { | |
387 | + | |
388 | + Debug.print("no index entries\n"); | |
389 | + return Error.FORMAT; | |
390 | + } | |
391 | + | |
392 | + entries = new IndexEntry[index_entries]; | |
393 | + | |
394 | + for (int i = 0; i < index_entries; i++) { | |
395 | + | |
396 | + entries[i] = new IndexEntry(); | |
397 | + | |
398 | + entries[i].ChunkId = Fcc.read(reader); | |
399 | + entries[i].Flags = Fcc.read(reader); | |
400 | + entries[i].Offset = Fcc.read(reader); | |
401 | + entries[i].Size = Fcc.read(reader); | |
402 | + | |
403 | + Debug.print("Index entry %04d: Flags:%d Offset:%d Size:%d\n", i, entries[i].Flags, entries[i].Offset, entries[i].Size); | |
404 | + Debug.print(entries[i].ChunkId); | |
405 | + } | |
406 | + | |
407 | + // Some AVI'sz have offset e in absolute coordinates | |
408 | + // instead of an offset from the movie beginning... this is... | |
409 | + // wacky, but we need to handle it. The wacky offset always | |
410 | + // starts at movi_offset it seems... so we'll check that. | |
411 | + // Note the the offset needs an extra 4 bytes for some | |
412 | + // undetermined reason | |
413 | + if (entries[0].Offset == movi_offset) { | |
414 | + read_offset = 4; | |
415 | + } | |
416 | + } | |
417 | + | |
418 | + Debug.print("movie succesfully opened\n"); | |
419 | + | |
420 | + return Error.NONE; | |
421 | + } | |
422 | + | |
423 | + public void readFrame(int frame_num, int stream, BufferedImage dst) throws IOException { | |
424 | + | |
425 | + int cur_frame = -1, i = 0, rewind = 1; | |
426 | + | |
427 | + /* | |
428 | + * Retrieve the record number of the desired frame_num in the index If a | |
429 | + * chunk has Size 0 we need to rewind to previous frame_num | |
430 | + */ | |
431 | + while (rewind != 0 && frame_num > -1) { | |
432 | + | |
433 | + i = 0; | |
434 | + cur_frame = -1; | |
435 | + rewind = 0; | |
436 | + | |
437 | + while (cur_frame < frame_num && i < index_entries) { | |
438 | + if (Fcc.is_data(entries[i].ChunkId) | |
439 | + && Fcc.get_stream(entries[i].ChunkId) == stream) { | |
440 | + if ((cur_frame == frame_num - 1) && (entries[i].Size == 0)) { | |
441 | + rewind = 1; | |
442 | + frame_num = frame_num - 1; | |
443 | + } else { | |
444 | + cur_frame++; | |
445 | + } | |
446 | + } | |
447 | + i++; | |
448 | + } | |
449 | + } | |
450 | + | |
451 | + if (cur_frame != frame_num) { | |
452 | + Debug.print("cur_frame != frame\n"); | |
453 | + return; | |
454 | + } | |
455 | + | |
456 | + reader.seek(read_offset + entries[i - 1].Offset); | |
457 | + | |
458 | + byte[] src = new byte[Fcc.read(reader)]; | |
459 | + reader.read(src); | |
460 | + | |
461 | + if (streams[stream].format != StreamRec.RecFormat.MJPEG) { | |
462 | + | |
463 | + Debug.print("can't decode frame (not mjpeg)\n"); | |
464 | + return; | |
465 | + } | |
466 | + | |
467 | + Mjpeg.decode(src, dst); | |
468 | + } | |
469 | + | |
470 | + public Error closeRead() throws IOException { | |
471 | + | |
472 | + reader.close(); | |
473 | + return Error.NONE; | |
474 | + } | |
475 | + | |
476 | + public Error openWrite(String name, StreamRec.RecFormat... formats) throws FileNotFoundException, IOException { | |
477 | + | |
478 | + List list = new List(); | |
479 | + Chunk chunk = new Chunk(); | |
480 | + | |
481 | + int i; | |
482 | + int header_pos1, header_pos2; | |
483 | + int stream_pos1, stream_pos2; | |
484 | + | |
485 | + writer = new AviWriter(name); | |
486 | + | |
487 | + index_entries = 0; | |
488 | + offset_table = new int[1 + formats.length * 2]; | |
489 | + | |
490 | + for (i = 0; i < 1 + formats.length * 2; i++) { | |
491 | + offset_table[i] = -1; | |
492 | + } | |
493 | + | |
494 | + entries = null; | |
495 | + | |
496 | + header = new MainHeader(); | |
497 | + | |
498 | + header.fcc = Fcc.FCC("avih"); | |
499 | + header.size = 56; | |
500 | + header.MicroSecPerFrame = 66667; | |
501 | + header.MaxBytesPerSec = 0; | |
502 | + header.PaddingGranularity = 0; | |
503 | + header.Flags = MainHeader.AVIF_HASINDEX | MainHeader.AVIF_MUSTUSEINDEX; | |
504 | + header.TotalFrames = 0; | |
505 | + header.InitialFrames = 0; | |
506 | + header.Streams = formats.length; | |
507 | + header.SuggestedBufferSize = 0; | |
508 | + header.Width = 0; | |
509 | + header.Height = 0; | |
510 | + header.Reserved[0] = 0; | |
511 | + header.Reserved[1] = 0; | |
512 | + header.Reserved[2] = 0; | |
513 | + header.Reserved[3] = 0; | |
514 | + | |
515 | + streams = new StreamRec[formats.length]; | |
516 | + | |
517 | + for (i = 0; i < header.Streams; i++) { | |
518 | + | |
519 | + streams[i] = new StreamRec(); | |
520 | + | |
521 | + streams[i].format = formats[i]; | |
522 | + | |
523 | + streams[i].sh.fcc = Fcc.FCC("strh"); | |
524 | + streams[i].sh.size = 56; | |
525 | + streams[i].sh.Type = Fcc.get_format_type(formats[i]); | |
526 | + | |
527 | + if (streams[i].sh.Type == 0) { | |
528 | + | |
529 | + Debug.print("streams[%d].sh.Type\n", i); | |
530 | + return Error.FORMAT; | |
531 | + } | |
532 | + | |
533 | + streams[i].sh.Handler = Fcc.get_format(formats[i]); | |
534 | + | |
535 | + if (streams[i].sh.Handler == 0) { | |
536 | + | |
537 | + Debug.print("streams[%d].sh.Handler\n", i); | |
538 | + return Error.FORMAT; | |
539 | + } | |
540 | + | |
541 | + streams[i].sh.Flags = 0; | |
542 | + streams[i].sh.Priority = 0; | |
543 | + streams[i].sh.Language = 0; | |
544 | + streams[i].sh.InitialFrames = 0; | |
545 | + streams[i].sh.Scale = 66667; | |
546 | + streams[i].sh.Rate = 1000000; | |
547 | + streams[i].sh.Start = 0; | |
548 | + streams[i].sh.Length = 0; | |
549 | + streams[i].sh.SuggestedBufferSize = 0; | |
550 | + streams[i].sh.Quality = 10000; | |
551 | + streams[i].sh.SampleSize = 0; | |
552 | + streams[i].sh.left = 0; | |
553 | + streams[i].sh.top = 0; | |
554 | + streams[i].sh.right = 0; | |
555 | + streams[i].sh.bottom = 0; | |
556 | + | |
557 | + if (streams[i].sh.Type == Fcc.FCC("vids")) { | |
558 | + | |
559 | + BitmapInfoHeader sf = new BitmapInfoHeader(); | |
560 | + | |
561 | + streams[i].sf = sf; | |
562 | + streams[i].sf_size = BitmapInfoHeader.sizeof; | |
563 | + | |
564 | + sf.fcc = Fcc.FCC("strf"); | |
565 | + sf.size = streams[i].sf_size - 8; | |
566 | + sf.Size = streams[i].sf_size - 8; | |
567 | + sf.Width = 0; | |
568 | + sf.Height = 0; | |
569 | + sf.Planes = 1; | |
570 | + sf.BitCount = 24; | |
571 | + sf.Compression = Fcc.get_format_compression(streams[i].format); | |
572 | + sf.SizeImage = 0; | |
573 | + sf.XPelsPerMeter = 0; | |
574 | + sf.YPelsPerMeter = 0; | |
575 | + sf.ClrUsed = 0; | |
576 | + sf.ClrImportant = 0; | |
577 | + } | |
578 | + } | |
579 | + | |
580 | + list.fcc = Fcc.FCC("RIFF"); | |
581 | + list.size = 0; | |
582 | + list.ids = Fcc.FCC("AVI "); | |
583 | + | |
584 | + list.write(writer); | |
585 | + | |
586 | + list.fcc = Fcc.FCC("LIST"); | |
587 | + list.size = 0; | |
588 | + list.ids = Fcc.FCC("hdrl"); | |
589 | + | |
590 | + list.write(writer); | |
591 | + | |
592 | + header_pos1 = writer.tell(); | |
593 | + | |
594 | + offset_table[0] = writer.tell(); | |
595 | + | |
596 | + header.write(writer); | |
597 | + | |
598 | + for (i = 0; i < header.Streams; i++) { | |
599 | + | |
600 | + list.fcc = Fcc.FCC("LIST"); | |
601 | + list.size = 0; | |
602 | + list.ids = Fcc.FCC("strl"); | |
603 | + | |
604 | + list.write(writer); | |
605 | + | |
606 | + stream_pos1 = writer.tell(); | |
607 | + | |
608 | + offset_table[1 + i * 2] = writer.tell(); | |
609 | + streams[i].sh.write(writer); | |
610 | + | |
611 | + offset_table[1 + i * 2 + 1] = writer.tell(); | |
612 | + streams[i].sf.write(writer); | |
613 | + | |
614 | + stream_pos2 = writer.tell(); | |
615 | + | |
616 | + writer.seek(stream_pos1 - 8); | |
617 | + | |
618 | + Fcc.write(stream_pos2 - stream_pos1 + 4, writer); | |
619 | + | |
620 | + writer.seek(stream_pos2); | |
621 | + } | |
622 | + | |
623 | + if (writer.tell() < 2024 - 8) { | |
624 | + | |
625 | + chunk.fcc = Fcc.FCC("JUNK"); | |
626 | + chunk.size = 2024 - 8 - writer.tell(); | |
627 | + | |
628 | + chunk.write(writer); | |
629 | + | |
630 | + for (i = 0; i < chunk.size; i++) { | |
631 | + writer.write(0); | |
632 | + } | |
633 | + } | |
634 | + | |
635 | + header_pos2 = writer.tell(); | |
636 | + | |
637 | + list.fcc = Fcc.FCC("LIST"); | |
638 | + list.size = 0; | |
639 | + list.ids = Fcc.FCC("movi"); | |
640 | + | |
641 | + list.write(writer); | |
642 | + | |
643 | + movi_offset = writer.tell() - 8; | |
644 | + | |
645 | + writer.seek(AVI_HDRL_SOFF); | |
646 | + | |
647 | + Fcc.write(header_pos2 - header_pos1 + 4, writer); | |
648 | + | |
649 | + Debug.print("opened for compress\n"); | |
650 | + | |
651 | + return Error.NONE; | |
652 | + } | |
653 | + | |
654 | + public Error closeWrite() throws IOException { | |
655 | + | |
656 | + int temp, movi_size; | |
657 | + | |
658 | + writer.seekEnd(); | |
659 | + movi_size = writer.tell(); | |
660 | + | |
661 | + Fcc.write(Fcc.FCC("idx1"), writer); | |
662 | + Fcc.write(index_entries * (header.Streams + 1) * 16, writer); | |
663 | + | |
664 | + for (temp = 0; temp < index_entries * (header.Streams + 1); temp++) { | |
665 | + entries[temp].write(writer); | |
666 | + } | |
667 | + | |
668 | + temp = writer.tell(); | |
669 | + | |
670 | + writer.seek(AVI_RIFF_SOFF); | |
671 | + | |
672 | + Fcc.write(temp - 8, writer); | |
673 | + | |
674 | + writer.seek(movi_offset); | |
675 | + | |
676 | + Fcc.write(movi_size - movi_offset - 4, writer); | |
677 | + | |
678 | + writer.close(); | |
679 | + | |
680 | + Debug.print("closed compress\n"); | |
681 | + | |
682 | + return Error.NONE; | |
683 | + } | |
684 | + | |
685 | + public Error writeFrame(int frame_num, BufferedImage... im) throws IOException { | |
686 | + | |
687 | + List list = new List(); | |
688 | + Chunk chunk = new Chunk(); | |
689 | + | |
690 | + if (frame_num < 0) { | |
691 | + | |
692 | + Debug.print("frame number less than 0\n"); | |
693 | + return Error.OPTION; | |
694 | + } | |
695 | + | |
696 | + /* | |
697 | + * Allocate the new memory for the index entry | |
698 | + */ | |
699 | + if ((frame_num + 1) > index_entries) { | |
700 | + | |
701 | + int i = 0; | |
702 | + int n = (frame_num + 1) * (header.Streams + 1); | |
703 | + | |
704 | + IndexEntry[] e = new IndexEntry[n]; | |
705 | + | |
706 | + while (i < index_entries * (header.Streams + 1)) { | |
707 | + | |
708 | + e[i] = entries[i]; | |
709 | + i++; | |
710 | + } | |
711 | + | |
712 | + while (i < n) { | |
713 | + | |
714 | + e[i] = new IndexEntry(); | |
715 | + i++; | |
716 | + } | |
717 | + | |
718 | + entries = e; | |
719 | + index_entries = frame_num + 1; | |
720 | + } | |
721 | + | |
722 | + /* | |
723 | + * Slap a new record entry onto the seekEnd of the file | |
724 | + */ | |
725 | + writer.seekEnd(); | |
726 | + | |
727 | + list.fcc = Fcc.FCC("LIST"); | |
728 | + list.size = 0; | |
729 | + list.ids = Fcc.FCC("rec "); | |
730 | + | |
731 | + list.write(writer); | |
732 | + | |
733 | + int rec_off = writer.tell() - 8; | |
734 | + | |
735 | + /* | |
736 | + * Write a frame for every stream | |
737 | + */ | |
738 | + for (int stream = 0; stream < header.Streams; stream++) { | |
739 | + | |
740 | + byte[] buffer = Mjpeg.encode(im[stream], streams[stream].sh.Quality / 10000.0f); | |
741 | + | |
742 | + /* | |
743 | + * Write the header info for this data chunk | |
744 | + */ | |
745 | + writer.seekEnd(); | |
746 | + | |
747 | + chunk.fcc = Fcc.get_data_id(StreamRec.RecFormat.MJPEG, stream); | |
748 | + chunk.size = buffer.length + 4 - (buffer.length % 4); | |
749 | + | |
750 | + chunk.write(writer); | |
751 | + | |
752 | + /* | |
753 | + * Write the index entry for this data chunk | |
754 | + */ | |
755 | + entries[frame_num * (header.Streams + 1) + stream + 1].ChunkId = chunk.fcc; | |
756 | + entries[frame_num * (header.Streams + 1) + stream + 1].Flags = IndexEntry.AVIIF_KEYFRAME; | |
757 | + entries[frame_num * (header.Streams + 1) + stream + 1].Offset = writer.tell() - 12 - movi_offset; | |
758 | + entries[frame_num * (header.Streams + 1) + stream + 1].Size = chunk.size; | |
759 | + | |
760 | + /* | |
761 | + * Write the chunk | |
762 | + */ | |
763 | + writer.write(buffer); | |
764 | + | |
765 | + /* | |
766 | + * Pad | |
767 | + */ | |
768 | + if ((buffer.length % 4) != 0) { | |
769 | + for (int pad = 0; pad < (buffer.length % 4); pad++) { | |
770 | + writer.write(0); | |
771 | + } | |
772 | + } | |
773 | + | |
774 | + /* | |
775 | + * Update the stream headers length field | |
776 | + */ | |
777 | + streams[stream].sh.Length++; | |
778 | + writer.seek(offset_table[1 + stream * 2]); | |
779 | + streams[stream].sh.write(writer); | |
780 | + } | |
781 | + | |
782 | + /* | |
783 | + * Record the entry for the new record | |
784 | + */ | |
785 | + writer.seekEnd(); | |
786 | + | |
787 | + entries[frame_num * (header.Streams + 1)].ChunkId = Fcc.FCC("rec "); | |
788 | + entries[frame_num * (header.Streams + 1)].Flags = IndexEntry.AVIIF_LIST; | |
789 | + entries[frame_num * (header.Streams + 1)].Offset = rec_off - 8 - movi_offset; | |
790 | + entries[frame_num * (header.Streams + 1)].Size = writer.tell() - rec_off + 4; | |
791 | + | |
792 | + /* | |
793 | + * Update the record sz | |
794 | + */ | |
795 | + writer.seek(rec_off); | |
796 | + Fcc.write(entries[frame_num * (header.Streams + 1)].Size, writer); | |
797 | + | |
798 | + /* | |
799 | + * Update the main header information in the file | |
800 | + */ | |
801 | + header.TotalFrames++; | |
802 | + writer.seek(offset_table[0]); | |
803 | + header.write(writer); | |
804 | + | |
805 | + return Error.NONE; | |
806 | + } | |
807 | +} |
@@ -0,0 +1,47 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +/** | |
32 | + * | |
33 | + * @author lenny | |
34 | + */ | |
35 | +public class StreamRec { | |
36 | + | |
37 | + public enum RecFormat { | |
38 | + | |
39 | + RGB24, | |
40 | + MJPEG | |
41 | + } | |
42 | + | |
43 | + public StreamHeader sh = new StreamHeader(); | |
44 | + public Writable sf; | |
45 | + public int sf_size; | |
46 | + public RecFormat format; | |
47 | +} |
@@ -0,0 +1,102 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import javilib.Avi.Error; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class Debug { | |
38 | + | |
39 | + public static boolean enable = true; | |
40 | + | |
41 | + public static void print(String s, Object... args) { | |
42 | + | |
43 | + if (enable) { | |
44 | + | |
45 | + System.out.print(String.format(s, args)); | |
46 | + } | |
47 | + } | |
48 | + | |
49 | + public static void print(Error error) { | |
50 | + | |
51 | + switch (error) { | |
52 | + case NONE: | |
53 | + break; | |
54 | + case COMPRESSION: | |
55 | + print("AVI ERROR: compressed in an unsupported format\n"); | |
56 | + break; | |
57 | + case OPEN: | |
58 | + print("AVI ERROR: could not open file\n"); | |
59 | + break; | |
60 | + case READING: | |
61 | + print("AVI ERROR: could not read from file\n"); | |
62 | + break; | |
63 | + case WRITING: | |
64 | + print("AVI ERROR: could not write to file\n"); | |
65 | + break; | |
66 | + case FORMAT: | |
67 | + print("AVI ERROR: file is in an illegal or unrecognized format\n"); | |
68 | + break; | |
69 | + case ALLOC: | |
70 | + print("AVI ERROR: error encountered while allocating memory\n"); | |
71 | + break; | |
72 | + case OPTION: | |
73 | + print("AVI ERROR: program made illegal request\n"); | |
74 | + break; | |
75 | + case FOUND: | |
76 | + print("AVI ERROR: movie did not contain expected item\n"); | |
77 | + break; | |
78 | + default: | |
79 | + break; | |
80 | + } | |
81 | + } | |
82 | + | |
83 | + public static void print(int fcc) { | |
84 | + | |
85 | + print( | |
86 | + "fcc: %c%c%c%c %d\n", | |
87 | + ((fcc >> 0) & 0xff), | |
88 | + ((fcc >> 8) & 0xff), | |
89 | + ((fcc >> 16) & 0xff), | |
90 | + ((fcc >> 24) & 0xff), | |
91 | + fcc); | |
92 | + } | |
93 | + | |
94 | + public static void print(short tcc) { | |
95 | + | |
96 | + print( | |
97 | + "tcc: %c%c %d\n", | |
98 | + ((tcc >> 0) & 0xff), | |
99 | + ((tcc >> 8) & 0xff), | |
100 | + tcc); | |
101 | + } | |
102 | +} |
@@ -0,0 +1,58 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class IndexEntry extends Writable { | |
38 | + | |
39 | + public int ChunkId; | |
40 | + public int Flags; | |
41 | + // | |
42 | + public static final int AVIIF_LIST = 0x00000001; | |
43 | + public static final int AVIIF_KEYFRAME = 0x00000010; | |
44 | + public static final int AVIIF_NO_TIME = 0x00000100; | |
45 | + public static final int AVIIF_COMPRESSOR = 0x0FFF0000; | |
46 | + // | |
47 | + public int Offset; | |
48 | + public int Size; | |
49 | + // -- | |
50 | + public static final int sizeof = 16; | |
51 | + | |
52 | + public void write(AviWriter writer) throws IOException { | |
53 | + Fcc.write(ChunkId, writer); | |
54 | + Fcc.write(Flags, writer); | |
55 | + Fcc.write(Offset, writer); | |
56 | + Fcc.write(Size, writer); | |
57 | + } | |
58 | +} |
@@ -0,0 +1,155 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | +import javilib.StreamRec.RecFormat; | |
33 | + | |
34 | +/** | |
35 | + * | |
36 | + * @author lenny | |
37 | + */ | |
38 | +public class Fcc { | |
39 | + | |
40 | + public static int FCC(String s) { | |
41 | + | |
42 | + int r = 0; | |
43 | + | |
44 | + r |= (s.charAt(0) & 0xff) << 0; | |
45 | + r |= (s.charAt(1) & 0xff) << 8; | |
46 | + r |= (s.charAt(2) & 0xff) << 16; | |
47 | + r |= (s.charAt(3) & 0xff) << 24; | |
48 | + | |
49 | + return r; | |
50 | + } | |
51 | + | |
52 | + public static int read(AviReader in) throws IOException { | |
53 | + | |
54 | + int r = 0; | |
55 | + | |
56 | + r |= (in.read() & 0xff) << 0; | |
57 | + r |= (in.read() & 0xff) << 8; | |
58 | + r |= (in.read() & 0xff) << 16; | |
59 | + r |= (in.read() & 0xff) << 24; | |
60 | + | |
61 | + return r; | |
62 | + } | |
63 | + | |
64 | + public static void write(int fcc, AviWriter out) throws IOException { | |
65 | + | |
66 | + out.write((fcc >> 0) & 0xff); | |
67 | + out.write((fcc >> 8) & 0xff); | |
68 | + out.write((fcc >> 16) & 0xff); | |
69 | + out.write((fcc >> 24) & 0xff); | |
70 | + } | |
71 | + | |
72 | + public static boolean is_data(int fcc) { | |
73 | + | |
74 | + int[] fccs = new int[4]; | |
75 | + | |
76 | + fccs[0] = (fcc >> 0) & 0xff; | |
77 | + fccs[1] = (fcc >> 8) & 0xff; | |
78 | + fccs[2] = (fcc >> 16) & 0xff; | |
79 | + fccs[3] = (fcc >> 24) & 0xff; | |
80 | + | |
81 | + if (!Character.isDigit(fccs[0]) | |
82 | + || !Character.isDigit(fccs[1]) | |
83 | + || (fccs[2] != 'd' && fccs[2] != 'w')) { | |
84 | + | |
85 | + return false; | |
86 | + } | |
87 | + | |
88 | + if (fccs[3] != 'b' && fccs[3] != 'c') { | |
89 | + | |
90 | + return false; | |
91 | + } | |
92 | + | |
93 | + return true; | |
94 | + } | |
95 | + | |
96 | + public static int get_stream(int fcc) { | |
97 | + | |
98 | + int[] fccs = new int[4]; | |
99 | + | |
100 | + fccs[0] = (fcc >> 0) & 0xff; | |
101 | + fccs[1] = (fcc >> 8) & 0xff; | |
102 | + fccs[2] = (fcc >> 16) & 0xff; | |
103 | + fccs[3] = (fcc >> 24) & 0xff; | |
104 | + | |
105 | + return 10 * (fccs[0] - '0') + (fccs[1] - '0'); | |
106 | + } | |
107 | + | |
108 | + public static int get_format_type(RecFormat format) { | |
109 | + | |
110 | + switch (format) { | |
111 | + case RGB24: | |
112 | + case MJPEG: | |
113 | + return FCC("vids"); | |
114 | + default: | |
115 | + return 0; | |
116 | + } | |
117 | + } | |
118 | + | |
119 | + public static int get_data_id(RecFormat format, int stream) { | |
120 | + | |
121 | + String fccs; | |
122 | + | |
123 | + if (get_format_type(format) == FCC("vids")) { | |
124 | + fccs = String.format("%02ddc", stream); | |
125 | + } else if (get_format_type(format) == FCC("auds")) { | |
126 | + fccs = String.format("%02ddc", stream); | |
127 | + } else { | |
128 | + return 0; | |
129 | + } | |
130 | + | |
131 | + return FCC(fccs); | |
132 | + } | |
133 | + | |
134 | + public static int get_format(RecFormat format) { | |
135 | + | |
136 | + switch (format) { | |
137 | + case MJPEG: | |
138 | + return FCC("MJPG"); | |
139 | + case RGB24: | |
140 | + return FCC("DIB "); | |
141 | + default: | |
142 | + return 0; | |
143 | + } | |
144 | + } | |
145 | + | |
146 | + public static int get_format_compression(RecFormat format) { | |
147 | + | |
148 | + switch (format) { | |
149 | + case MJPEG: | |
150 | + return FCC("MJPG"); | |
151 | + default: | |
152 | + return 0; | |
153 | + } | |
154 | + } | |
155 | +} |
@@ -0,0 +1,82 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class MainHeader extends Writable { | |
38 | + | |
39 | + public int fcc; | |
40 | + public int size; | |
41 | + public int MicroSecPerFrame; // MicroSecPerFrame - timing between frames | |
42 | + public int MaxBytesPerSec; // MaxBytesPerSec - approx bps system must handle | |
43 | + public int PaddingGranularity; | |
44 | + public int Flags; | |
45 | + // | |
46 | + public static final int AVIF_HASINDEX = 0x00000010; // had idx1 chunk | |
47 | + public static final int AVIF_MUSTUSEINDEX = 0x00000020; // must use idx1 chunk to determine order | |
48 | + public static final int AVIF_ISINTERLEAVED = 0x00000100; // AVI file is interleaved | |
49 | + public static final int AVIF_TRUSTCKTYPE = 0x00000800; // | |
50 | + public static final int AVIF_WASCAPTUREFILE = 0x00010000; // specially allocated used for capturing real time video | |
51 | + public static final int AVIF_COPYRIGHTED = 0x00020000; // contains copyrighted data | |
52 | + // | |
53 | + public int TotalFrames; | |
54 | + public int InitialFrames; // InitialFrames - initial frame before interleaving | |
55 | + public int Streams; | |
56 | + public int SuggestedBufferSize; | |
57 | + public int Width; | |
58 | + public int Height; | |
59 | + public int[] Reserved = new int[4]; | |
60 | + // -- | |
61 | + public static final int sizeof = 64; | |
62 | + | |
63 | + @Override | |
64 | + public void write(AviWriter writer) throws IOException { | |
65 | + Fcc.write(fcc, writer); | |
66 | + Fcc.write(size, writer); | |
67 | + Fcc.write(MicroSecPerFrame, writer); | |
68 | + Fcc.write(MaxBytesPerSec, writer); | |
69 | + Fcc.write(PaddingGranularity, writer); | |
70 | + Fcc.write(Flags, writer); | |
71 | + Fcc.write(TotalFrames, writer); | |
72 | + Fcc.write(InitialFrames, writer); | |
73 | + Fcc.write(Streams, writer); | |
74 | + Fcc.write(SuggestedBufferSize, writer); | |
75 | + Fcc.write(Width, writer); | |
76 | + Fcc.write(Height, writer); | |
77 | + Fcc.write(Reserved[0], writer); | |
78 | + Fcc.write(Reserved[1], writer); | |
79 | + Fcc.write(Reserved[2], writer); | |
80 | + Fcc.write(Reserved[3], writer); | |
81 | + } | |
82 | +} |
@@ -0,0 +1,72 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class BitmapInfoHeader extends Writable { | |
38 | + | |
39 | + public int fcc; | |
40 | + public int size; | |
41 | + public int Size; | |
42 | + public int Width; | |
43 | + public int Height; | |
44 | + public short Planes; | |
45 | + public short BitCount; | |
46 | + public int Compression; | |
47 | + public int SizeImage; | |
48 | + public int XPelsPerMeter; | |
49 | + public int YPelsPerMeter; | |
50 | + public int ClrUsed; | |
51 | + public int ClrImportant; | |
52 | + // -- | |
53 | + public static final int sizeof = 48; | |
54 | + | |
55 | + @Override | |
56 | + public void write(AviWriter writer) throws IOException { | |
57 | + | |
58 | + Fcc.write(fcc, writer); | |
59 | + Fcc.write(size, writer); | |
60 | + Fcc.write(Size, writer); | |
61 | + Fcc.write(Width, writer); | |
62 | + Fcc.write(Height, writer); | |
63 | + Tcc.write(Planes, writer); | |
64 | + Tcc.write(BitCount, writer); | |
65 | + Fcc.write(Compression, writer); | |
66 | + Fcc.write(SizeImage, writer); | |
67 | + Fcc.write(XPelsPerMeter, writer); | |
68 | + Fcc.write(YPelsPerMeter, writer); | |
69 | + Fcc.write(ClrUsed, writer); | |
70 | + Fcc.write(ClrImportant, writer); | |
71 | + } | |
72 | +} |
@@ -0,0 +1,90 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.awt.image.BufferedImage; | |
32 | +import java.io.ByteArrayInputStream; | |
33 | +import java.io.ByteArrayOutputStream; | |
34 | +import java.io.IOException; | |
35 | +import javax.imageio.IIOImage; | |
36 | +import javax.imageio.ImageIO; | |
37 | +import javax.imageio.ImageReader; | |
38 | +import javax.imageio.ImageWriter; | |
39 | +import javax.imageio.plugins.jpeg.JPEGHuffmanTable; | |
40 | +import javax.imageio.plugins.jpeg.JPEGImageReadParam; | |
41 | +import javax.imageio.plugins.jpeg.JPEGImageWriteParam; | |
42 | +import javax.imageio.plugins.jpeg.JPEGQTable; | |
43 | + | |
44 | +/** | |
45 | + * | |
46 | + * @author lenny | |
47 | + */ | |
48 | +public class Mjpeg { | |
49 | + | |
50 | + private static final JPEGQTable[] q = { | |
51 | + JPEGQTable.K1Luminance, | |
52 | + JPEGQTable.K2Chrominance | |
53 | + }; | |
54 | + private static final JPEGHuffmanTable[] dc = { | |
55 | + JPEGHuffmanTable.StdDCLuminance, | |
56 | + JPEGHuffmanTable.StdDCChrominance | |
57 | + }; | |
58 | + private static final JPEGHuffmanTable[] ac = { | |
59 | + JPEGHuffmanTable.StdACLuminance, | |
60 | + JPEGHuffmanTable.StdACChrominance | |
61 | + }; | |
62 | + | |
63 | + public static void decode(byte[] src, BufferedImage dst) throws IOException { | |
64 | + | |
65 | + ImageReader reader = ImageIO.getImageReadersByMIMEType("image/jpeg").next(); | |
66 | + reader.setInput(ImageIO.createImageInputStream(new ByteArrayInputStream(src))); | |
67 | + | |
68 | + JPEGImageReadParam param = (JPEGImageReadParam) reader.getDefaultReadParam(); | |
69 | + param.setDecodeTables(q, dc, ac); | |
70 | + param.setDestination(dst); | |
71 | + | |
72 | + reader.read(0, param); | |
73 | + } | |
74 | + | |
75 | + public static byte[] encode(BufferedImage src, float quality) throws IOException { | |
76 | + | |
77 | + ByteArrayOutputStream dst = new ByteArrayOutputStream(); | |
78 | + | |
79 | + ImageWriter writer = ImageIO.getImageWritersByMIMEType("image/jpeg").next(); | |
80 | + writer.setOutput(ImageIO.createImageOutputStream(dst)); | |
81 | + | |
82 | + JPEGImageWriteParam param = (JPEGImageWriteParam) writer.getDefaultWriteParam(); | |
83 | + param.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT); | |
84 | + param.setCompressionQuality(quality); | |
85 | + | |
86 | + writer.write(null, new IIOImage(src, null, null), param); | |
87 | + | |
88 | + return dst.toByteArray(); | |
89 | + } | |
90 | +} |
@@ -0,0 +1,56 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.FileInputStream; | |
32 | +import java.io.FileNotFoundException; | |
33 | +import java.io.IOException; | |
34 | + | |
35 | +/** | |
36 | + * | |
37 | + * @author lenny | |
38 | + */ | |
39 | +public class AviReader extends FileInputStream { | |
40 | + | |
41 | + public AviReader(String fn) throws FileNotFoundException { | |
42 | + super(fn); | |
43 | + } | |
44 | + | |
45 | + public void seekRel(int off) throws IOException { | |
46 | + getChannel().position(getChannel().position() + off); | |
47 | + } | |
48 | + | |
49 | + public void seek(int off) throws IOException { | |
50 | + getChannel().position(off); | |
51 | + } | |
52 | + | |
53 | + public int tell() throws IOException { | |
54 | + return (int) getChannel().position(); | |
55 | + } | |
56 | +} |
@@ -0,0 +1,93 @@ | ||
1 | +/* | |
2 | + Copyright (c) 2012, Lenny <leonardo.masoni@gmail.com> | |
3 | + All rights reserved. | |
4 | + | |
5 | + Redistribution and use in source and binary forms, with or without | |
6 | + modification, are permitted provided that the following conditions are met: | |
7 | + | |
8 | + 1. Redistributions of source code must retain the above copyright notice, this | |
9 | + list of conditions and the following disclaimer. | |
10 | + 2. Redistributions in binary form must reproduce the above copyright notice, | |
11 | + this list of conditions and the following disclaimer in the documentation | |
12 | + and/or other materials provided with the distribution. | |
13 | + | |
14 | + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |
15 | + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
16 | + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
17 | + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | |
18 | + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
19 | + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
20 | + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | |
21 | + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
23 | + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | + | |
25 | + The views and conclusions contained in the software and documentation are those | |
26 | + of the authors and should not be interpreted as representing official policies, | |
27 | + either expressed or implied, of the FreeBSD Project. | |
28 | + */ | |
29 | +package javilib; | |
30 | + | |
31 | +import java.io.IOException; | |
32 | + | |
33 | +/** | |
34 | + * | |
35 | + * @author lenny | |
36 | + */ | |
37 | +public class StreamHeader extends Writable { | |
38 | + | |
39 | + public int fcc; | |
40 | + public int size; | |
41 | + public int Type; | |
42 | + // | |
43 | + public static final int AVIST_VIDEO = Fcc.FCC("vids"); | |
44 | + public static final int AVIST_AUDIO = Fcc.FCC("auds"); | |
45 | + public static final int AVIST_MIDI = Fcc.FCC("mids"); | |
46 | + public static final int AVIST_TEXT = Fcc.FCC("txts"); | |
47 | + // | |
48 | + public int Handler; | |
49 | + public int Flags; | |
50 | + // | |
51 | + public static final int AVISF_DISABLED = 0x00000001; | |
52 | + public static final int AVISF_VIDEO_PALCHANGES = 0x00010000; | |
53 | + // | |
54 | + public short Priority; | |
55 | + public short Language; | |
56 | + public int InitialFrames; | |
57 | + public int Scale; | |
58 | + public int Rate; | |
59 | + public int Start; | |
60 | + public int Length; | |
61 | + public int SuggestedBufferSize; | |
62 | + public int Quality; | |
63 | + public int SampleSize; | |
64 | + public short left; | |
65 | + public short top; | |
66 | + public short right; | |
67 | + public short bottom; | |
68 | + // -- | |
69 | + public static final int sizeof = 64; | |
70 | + | |
71 | + @Override | |
72 | + public void write(AviWriter writer) throws IOException { | |
73 | + Fcc.write(fcc, writer); | |
74 | + Fcc.write(size, writer); | |
75 | + Fcc.write(Type, writer); | |
76 | + Fcc.write(Handler, writer); | |
77 | + Fcc.write(Flags, writer); | |
78 | + Tcc.write(Priority, writer); | |
79 | + Tcc.write(Language, writer); | |
80 | + Fcc.write(InitialFrames, writer); | |
81 | + Fcc.write(Scale, writer); | |
82 | + Fcc.write(Rate, writer); | |
83 | + Fcc.write(Start, writer); | |
84 | + Fcc.write(Length, writer); | |
85 | + Fcc.write(SuggestedBufferSize, writer); | |
86 | + Fcc.write(Quality, writer); | |
87 | + Fcc.write(SampleSize, writer); | |
88 | + Tcc.write(left, writer); | |
89 | + Tcc.write(top, writer); | |
90 | + Tcc.write(right, writer); | |
91 | + Tcc.write(bottom, writer); | |
92 | + } | |
93 | +} |