1 4 5 9 10 package org.openlaszlo.media; 11 12 import java.io.InputStream ; 13 import java.io.FileInputStream ; 14 import java.io.IOException ; 15 import java.io.BufferedInputStream ; 16 import java.io.FileNotFoundException ; 17 import java.io.File ; 18 import java.awt.geom.Rectangle2D ; 19 import java.util.Properties ; 20 21 import org.openlaszlo.iv.flash.api.*; 23 import org.openlaszlo.iv.flash.api.action.*; 24 import org.openlaszlo.iv.flash.api.sound.*; 25 import org.openlaszlo.iv.flash.api.image.*; 26 import org.openlaszlo.iv.flash.util.*; 27 28 import org.openlaszlo.utils.SWFUtils; 29 import org.openlaszlo.utils.FileUtils; 30 import org.openlaszlo.server.LPS; 31 32 import org.openlaszlo.sc.ScriptCompiler; 33 34 import org.apache.log4j.*; 36 37 42 public class Transcoder { 43 44 45 private static Logger mLogger = Logger.getLogger(Transcoder.class); 46 47 52 public static boolean canTranscode(String in, String out) { 53 54 if (!out.equalsIgnoreCase(MimeType.SWF)) { 55 56 if (out.equalsIgnoreCase(FontType.FFT) && 57 in.equalsIgnoreCase(FontType.TTF)) { 58 return true; 59 } 60 return false; 61 } 62 63 if (in.equalsIgnoreCase(MimeType.JPEG) || 64 in.equalsIgnoreCase(MimeType.PNG) || 65 in.equalsIgnoreCase(MimeType.GIF) || 66 in.equalsIgnoreCase(MimeType.MP3) || 67 in.equalsIgnoreCase(MimeType.XMP3) || 68 in.equalsIgnoreCase(MimeType.SWF)) { 69 return true; 70 } 71 return false; 72 } 73 74 83 public static InputStream transcode(InputStream stream, 84 String from, String to, boolean doStream) 85 throws TranscoderException, IOException { 86 87 if (!to.equalsIgnoreCase(MimeType.SWF)) { 88 throw new TranscoderException("Unknown output mime-type: " + to); 89 } 90 91 mLogger.debug("Transcoding from " + from + " to " + to); 92 93 if (from.equalsIgnoreCase(MimeType.SWF)) { 97 return stream; 98 } 99 100 if (from.equalsIgnoreCase(MimeType.JPEG) || 102 from.equalsIgnoreCase(MimeType.PNG) || 103 from.equalsIgnoreCase(MimeType.GIF) || 104 from.indexOf("image") != -1 ) { 105 return convertImageToSWF(stream); 106 } else if (from.equalsIgnoreCase(MimeType.MP3) || 107 from.equalsIgnoreCase(MimeType.XMP3) || 108 from.indexOf("audio") != -1) { 109 return convertAudioToSWF(stream, doStream); 111 } 112 113 BufferedInputStream bis = null; 114 try { 115 if (!stream.markSupported()) { 116 bis = new BufferedInputStream (stream); 117 stream = bis; 118 } 119 String mime = guessSupportedMimeTypeFromContent(stream); 120 if (mime != null) { 121 InputStream out = null; 122 if (mime.equals(MimeType.SWF)) { 123 out = bis; 124 } else { 125 out = transcode(bis, mime, to, doStream); 126 } 127 if (bis == out) { 129 bis = null; 130 } 131 return out; 132 } else { 133 throw new TranscoderException("can't guess a supported mime-type from content"); 134 } 135 } finally { 136 FileUtils.close(bis); 137 } 138 } 139 140 143 public static String guessSupportedMimeTypeFromContent(String fileName) 144 throws IOException { 145 InputStream is = null; 146 try { 147 is = new BufferedInputStream (new FileInputStream (fileName)); 148 return guessSupportedMimeTypeFromContent(is); 149 } finally { 150 FileUtils.close(is); 151 } 152 } 153 154 158 public static String guessSupportedMimeTypeFromContent(InputStream stream) 159 throws IOException { 160 if (!stream.markSupported()) { 161 return null; 162 } 163 164 try { 165 stream.mark(stream.available()); 166 167 mLogger.debug("trying swf"); 168 if (SWFUtils.hasSWFHeader(stream)) { 169 return MimeType.SWF; 170 } 171 172 stream.reset(); 173 if (GIF.is(stream)) { 174 return MimeType.GIF; 175 } 176 177 stream.reset(); 178 if (JPEG.is(stream)) { 179 return MimeType.JPEG; 180 } 181 182 stream.reset(); 183 if (PNG.is(stream)) { 184 return MimeType.PNG; 185 } 186 187 stream.reset(); 188 if (MP3.is(stream)) { 189 return MimeType.MP3; 190 } 191 } finally { 192 stream.reset(); 193 } 194 195 return null; 196 } 197 198 205 public static InputStream transcode(File input, String from, String to) 206 throws TranscoderException, IOException { 207 208 if (to.equalsIgnoreCase(FontType.FFT)) { 209 if (from.equalsIgnoreCase(FontType.TTF)) { 210 return TTF2FFT.convert(input); 211 } else { 212 throw new TranscoderException("Unknown input font type: " 213 + from); 214 } 215 } else { 216 InputStream fis = new FileInputStream (input); 217 InputStream out = null; 218 try { 219 out = transcode(fis, from , to, 220 false); 221 return out; 222 } finally { 223 if (fis != null && fis != out) { 224 fis.close(); 225 } 226 } 227 } 228 } 229 230 233 private static final InputStream convertImageToSWF(InputStream stream) 234 throws IOException , TranscoderException { 235 236 try { 237 mLogger.debug("converting image to SWF"); 238 239 Bitmap bitmap = Bitmap.newBitmap(new FlashBuffer(stream)); 240 if (bitmap == null) { 241 String msg = "corrupt image or unknown image type"; 242 throw new TranscoderException(msg); 243 } 244 mLogger.debug("done bitmap file"); 245 Instance inst = bitmap.newInstance(); 246 Script script; 247 script = new Script(1); 248 script.setMain(); 249 script.newFrame().addInstance(inst, 1); 250 FlashFile file = FlashFile.newFlashFile(); 251 file.setVersion(5); 252 file.setFrameSize(inst.getBounds()); 253 file.setMainScript(script); 254 mLogger.debug("starting generate"); 255 FlashOutput out = file.generate(); 256 mLogger.debug("ending generate"); 257 return out.getInputStream(); 258 } catch (IVException e) { 259 throw new TranscoderException("iv exception:" + e.getMessage()); 260 } 261 } 262 263 267 private static final InputStream convertAudioToSWF(InputStream stream, boolean doStream) 268 throws IOException , TranscoderException { 269 270 try { 272 return convertAudioToSWF(stream, doStream, true, 0, 0); 273 } catch (IVException e) { 274 throw new TranscoderException("iv exception:" + e.getMessage()); 275 } 276 } 277 278 281 private static final InputStream convertAudioToSWF(InputStream in, boolean stream, boolean stopAction, int delay, int startframe) 282 throws IOException , IVException { 283 284 Script script; 285 script = new Script(1); 286 287 FlashFile file = FlashFile.newFlashFile(); 288 289 final int MAX_SWF_FRAMES = 16000; 291 int mFrameRate = 30; 292 try { 293 String f = LPS.getProperty("lps.swf.audio.framerate", "30"); 294 mFrameRate = Integer.parseInt(f); 295 } catch (Exception e) { 296 mLogger.error("Can't read property file for lps.swf.audio.framerate"); 297 } 298 299 file.setFrameRate(mFrameRate << 8); 300 301 Frame stopFrame = null; 302 303 FlashBuffer fib = new FlashBuffer(in); 304 305 if( stream ) { 306 mLogger.debug("transcoding streaming mp3"); 307 SoundStreamBuilder ssb = SoundStreamBuilder.newSoundStreamBuilder(fib, file.getFrameRate()); 308 SoundStreamHead head = ssb.getSoundStreamHead(); 309 310 script.getFrameAt( startframe ).addFlashObject( head ); 312 313 int frameCount = script.getFrameCount(); 314 int f = startframe; 315 SoundStreamBlock block; 316 317 while( ( block = ssb.getNextSoundStreamBlock() ) != null ) { 318 if( f >= frameCount ) { 319 script.newFrame().addFlashObject( block ); 320 } else { 321 script.getFrameAt( f ).addFlashObject( block ); 322 } 323 324 f++; 325 if (f >= MAX_SWF_FRAMES) { 326 String msg = 327 "LPS hit max SWF frame count when converting this clip" 328 + "; truncating it at " + MAX_SWF_FRAMES + " frames"; 329 mLogger.warn(msg); 330 script.getFrameAt(0).addFlashObject(WarningProgram(msg)); 331 break; 332 } 333 } 334 335 stopFrame = script.getFrameAt( f - 1 ); 336 } else { 337 mLogger.debug("transcoding non-streaming mp3"); 338 MP3Sound sound = MP3Sound.newMP3Sound(fib); 339 if( delay != 0 ) { 341 sound.setDelaySeek( delay ); 342 } 343 344 SoundInfo soundInfo = SoundInfo.newSoundInfo( 0 ); 345 StartSound startSound = StartSound.newStartSound( sound, soundInfo ); 346 347 Frame newFrame = script.newFrame(); 348 newFrame.addFlashObject( startSound ); 349 350 stopFrame = newFrame; 351 } 352 353 if( stopAction ) { 354 stopFrame.addStopAction(); 355 } 356 357 file.setVersion(5); 358 file.setFrameSize(GeomHelper.newRectangle(0,0,0,0)); 359 file.setMainScript(script); 360 FlashOutput out = file.generate(); 361 return out.getInputStream(); 362 } 363 364 368 private static FlashObject WarningProgram(String msg) { 369 String p = "_root.debug.write('" + msg + "');"; 370 byte[] action = ScriptCompiler.compileToByteArray(p, new Properties ()); 371 return new DoAction(new Program(action, 0, action.length)); 372 } 373 } 374 | Popular Tags |