Quadcap Embeddable Server

com/quadcap/http/client/Mp3FrameStream.java

Go to the documentation of this file.
00001 package com.quadcap.http.client; 00002 00003 import java.io.BufferedOutputStream; 00004 import java.io.ByteArrayOutputStream; 00005 import java.io.FileInputStream; 00006 import java.io.FileOutputStream; 00007 import java.io.IOException; 00008 import java.io.OutputStream; 00009 00010 import com.quadcap.util.Debug; 00011 00012 import com.quadcap.io.IO; 00013 00014 /* 00015 * Copyright 2004 by Stan Bailes and Quadcap Software. 00016 * 00017 **/ 00018 public class Mp3FrameStream extends OutputStream { 00019 ByteArrayOutputStream frame = new ByteArrayOutputStream(); 00020 OutputStream frameData; 00021 OutputStream nonFrameData; 00022 int state = 0; 00023 00024 int id = 0; 00025 int layer = 0; 00026 int protection = 0; 00027 int bitrateEnc = 0; 00028 int frequency = 0; 00029 int pad = 0; 00030 int priv = 0; 00031 int mode = 0; 00032 int modeExt = 0; 00033 int copy = 0; 00034 int home = 0; 00035 int emph = 0; 00036 00037 double bitrate = 0; 00038 double samplerate = 0; 00039 int framesize = 0; 00040 int count = 0; 00041 00042 int totalBytes = 0; 00043 int nonFrameCount = 0; 00044 00045 boolean started = false; 00046 int bitrateEncStart = 0; 00047 int frequencyStart = 0; 00048 00049 public Mp3FrameStream() {} 00050 00051 public void init(OutputStream frameData, OutputStream nonFrameData) { 00052 this.frameData = frameData; 00053 this.nonFrameData = nonFrameData; 00054 started = false; 00055 } 00056 00057 public void write(int b) throws IOException { 00058 totalBytes++; 00059 if (false && (totalBytes % 100000) == 99999) { 00060 msg("totalBytes: " + totalBytes + ", state: " + state + 00061 ", count: " + count + ", framesize: " + framesize); 00062 } 00063 00064 b &= 0xff; 00065 switch (state) { 00066 case 0: 00067 if (b == 0xff) { 00068 state = 1; 00069 } else { 00070 nonFrameData.write(b); 00071 nonFrameCount++; 00072 } 00073 break; 00074 case 1: 00075 if ((b & 0xe0) == 0xe0) { 00076 if (nonFrameCount > 0) { 00077 msg("" + nonFrameCount + " non frame bytes @ " + 00078 totalBytes); 00079 } 00080 nonFrameCount = 0; 00081 //msg("Frame starts at byte " + ((totalBytes) - 2)); 00082 frame.reset(); 00083 frame.write(0xff); 00084 frame.write(b); 00085 id = (b & 0x8) >> 3; 00086 layer = (b & 0x6) >> 1; 00087 protection = (b & 0x1); 00088 state = 2; 00089 } else { 00090 nonFrameData.write(0xff); 00091 nonFrameData.write(b); 00092 nonFrameCount++; 00093 state = 0; 00094 } 00095 break; 00096 case 2: 00097 frame.write(b); 00098 bitrateEnc = (b & 0xf0) >> 4; 00099 frequency = (b & 0xc) >> 2; 00100 pad = (b & 0x2) >> 1; 00101 priv = (b & 0x1); 00102 state = 3; 00103 break; 00104 case 3: 00105 frame.write(b); 00106 mode = (b & 0xc0) >> 6; 00107 modeExt = (b & 0x3) >> 4; 00108 copy = (b & 0x8) >> 3; 00109 home = (b & 0x4) >> 2; 00110 emph = (b & 0x3); 00111 bitrate = bitrates[bitrateEnc][(id << 2) | layer] * 1000; 00112 samplerate = samplerates[(id << 2) | frequency]; 00113 if (samplerate == 0) { 00114 state = 0; 00115 nonFrameData.write(frame.toByteArray()); 00116 nonFrameCount += 4; 00117 } else if (started && bitrateEnc != bitrateEncStart || 00118 frequency != frequencyStart) { 00119 nonFrameData.write(frame.toByteArray()); 00120 nonFrameCount += 4; 00121 state = 0; 00122 } else { 00123 framesize = (int) (144 * (bitrate / samplerate) + pad); 00124 if (!started) { 00125 msg("bitrate: " + bitrate + ", samplerate: " + samplerate + 00126 ", framesize: " + framesize + " brEnc: " + bitrateEnc + 00127 " id: " + id + " layer: " + layer + " freq: " + 00128 frequency); 00129 started = true; 00130 } 00131 bitrateEncStart = bitrateEnc; 00132 frequencyStart = frequency; 00133 count = 4; 00134 state = 4; 00135 } 00136 break; 00137 case 4: 00138 frame.write(b); 00139 if (++count >= framesize) { 00140 byte[] data = frame.toByteArray(); 00141 frameData.write(data); 00142 state = 0; 00143 } 00144 break; 00145 } 00146 } 00147 00148 int[] samplerates = { 00149 22050, 24000, 16000, 0, // MPEG-2 00150 44100, 48000, 32000, 0 // MPEG-1 00151 }; 00152 00153 int[][] bitrates = { 00154 // MPEG-2 MPEG-1 00155 // layer layer 00156 // I II III I II III 00157 {0, 8, 32, 32, 0, 32, 32, 32}, // 0 00158 {0, 8, 32, 32, 0, 32, 32, 32}, // 1 00159 {0, 16, 48, 64, 0, 40, 48, 64}, // 2 00160 {0, 24, 56, 96, 0, 48, 56, 96}, // 3 00161 {0, 32, 64, 128, 0, 56, 64, 128}, // 4 00162 {0, 64, 80, 160, 0, 64, 80, 160}, // 5 00163 {0, 80, 96, 192, 0, 80, 96, 192}, // 6 00164 {0, 96, 112, 224, 0, 96, 112, 224}, // 7 00165 {0, 112, 128, 256, 0, 112, 128, 256}, // 8 00166 {0, 128, 160, 288, 0, 128, 160, 288}, // 9 00167 {0, 160, 192, 320, 0, 160, 192, 320}, // 10 00168 {0, 112, 224, 352, 0, 192, 224, 352}, // 11 00169 {0, 128, 256, 384, 0, 224, 256, 384}, // 12 00170 {0, 256, 320, 416, 0, 256, 320, 416}, // 13 00171 {0, 320, 384, 448, 0, 320, 384, 448}, // 14 00172 {0, 320, 384, 448, 0, 320, 384, 448} // 15 00173 }; 00174 00175 void msg(String s) { 00176 Debug.println(s); 00177 } 00178 00179 public static void main(String[] args) { 00180 Mp3FrameStream mp = new Mp3FrameStream(); 00181 for (int i = 0; i < args.length; i++) { 00182 String s = args[i]; 00183 try { 00184 if (false) { 00185 FileInputStream fi = new FileInputStream(s); 00186 int b; 00187 int state = 0; 00188 int count = 0; 00189 while ((b = fi.read()) >= 0) { 00190 count++; 00191 switch (state) { 00192 case 0: 00193 if (b == 0xff) { 00194 state = 1; 00195 } 00196 break; 00197 case 1: 00198 if (b == 251) { 00199 state = 2; 00200 } else if (b != 0xff) { 00201 state = 0; 00202 } 00203 break; 00204 case 2: 00205 if (b == 146) { 00206 mp.msg("Sync at " + (count-3)); 00207 } 00208 state = 0; 00209 break; 00210 } 00211 } 00212 fi.close(); 00213 } 00214 FileInputStream fis = new FileInputStream(s); 00215 try { 00216 FileOutputStream raw = new FileOutputStream(s + ".out"); 00217 FileOutputStream skp = new FileOutputStream(s + ".skp"); 00218 mp.init(raw, skp); 00219 try { 00220 IO.copyStream(fis, mp); 00221 } finally { 00222 mp.close(); 00223 } 00224 } finally { 00225 fis.close(); 00226 } 00227 } catch (Throwable t) { 00228 Debug.print(t); 00229 } 00230 } 00231 } 00232 00233 public void close() throws IOException { 00234 Debug.println("close()"); 00235 frameData.close(); 00236 nonFrameData.close(); 00237 if (nonFrameCount > 0) { 00238 Debug.println("" + nonFrameCount + " trailing bytes no sync"); 00239 } 00240 } 00241 }