001 package railo.runtime.video; 002 003 import java.util.Map; 004 005 import org.apache.commons.collections.map.ReferenceMap; 006 007 import railo.commons.io.res.Resource; 008 import railo.commons.io.res.type.file.FileResource; 009 import railo.commons.io.res.type.http.HTTPResource; 010 import railo.commons.lang.ClassException; 011 import railo.commons.lang.ClassUtil; 012 import railo.commons.lang.StringUtil; 013 import railo.runtime.PageContext; 014 import railo.runtime.config.Config; 015 import railo.runtime.exp.ApplicationException; 016 import railo.runtime.exp.ExpressionException; 017 import railo.runtime.exp.PageException; 018 import railo.runtime.functions.string.Hash; 019 import railo.runtime.op.Caster; 020 021 public class VideoUtilImpl implements VideoUtil { 022 023 024 private static Map sizes=new ReferenceMap(ReferenceMap.SOFT,ReferenceMap.SOFT); 025 private static VideoUtilImpl instance=new VideoUtilImpl(); 026 027 private VideoUtilImpl(){ } 028 029 public static VideoUtilImpl getInstance() { 030 return instance; 031 } 032 033 /** 034 * @see railo.runtime.video.VideoUtil#createVideoInput(railo.commons.io.res.Resource) 035 */ 036 public VideoInput createVideoInput(Resource input) { 037 return new VideoInputImpl(input); 038 } 039 040 /** 041 * @see railo.runtime.video.VideoUtil#createVideoOutput(railo.commons.io.res.Resource) 042 */ 043 public VideoOutput createVideoOutput(Resource output) { 044 return new VideoOutputImpl(output); 045 } 046 047 /** 048 * @see railo.runtime.video.VideoUtil#createVideoProfile() 049 */ 050 public VideoProfile createVideoProfile() { 051 return new VideoProfileImpl(); 052 } 053 054 055 public long toBytes(String byt) throws PageException { 056 byt=byt.trim().toLowerCase(); 057 if(byt.endsWith("kb/s") || byt.endsWith("kbps")) { 058 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-4).trim())*1024); 059 } 060 if(byt.endsWith("mb/s") || byt.endsWith("mbps")) { 061 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-4).trim())*1024*1024); 062 } 063 if(byt.endsWith("gb/s") || byt.endsWith("gbps")) { 064 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-4).trim())*1024*1024*1024); 065 } 066 if(byt.endsWith("b/s") || byt.endsWith("bps")) { 067 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-3).trim())); 068 } 069 070 if(byt.endsWith("kbit/s")) { 071 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-6).trim())*1024); 072 } 073 if(byt.endsWith("mbit/s")) { 074 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-6).trim())*1024*1024); 075 } 076 if(byt.endsWith("gbit/s")) { 077 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-6).trim())*1024*1024*1024); 078 } 079 if(byt.endsWith("bit/s")) { 080 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-5).trim())); 081 } 082 083 084 if(byt.endsWith("kb")) { 085 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())*1024); 086 } 087 if(byt.endsWith("mb")) { 088 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())*1024*1024); 089 } 090 if(byt.endsWith("gb")) { 091 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())*1024*1024*1024); 092 } 093 094 if(byt.endsWith("g")) { 095 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())*1024*1024*1024); 096 } 097 if(byt.endsWith("m")) { 098 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())*1024*1024); 099 } 100 if(byt.endsWith("k")) { 101 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())*1024); 102 } 103 if(byt.endsWith("b")) { 104 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-1).trim())); 105 } 106 return Caster.toLongValue(byt); 107 } 108 109 public long toHerz(String byt) throws PageException { 110 byt=byt.trim().toLowerCase(); 111 if(byt.endsWith("mhz")) { 112 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-3).trim())*1000*1000); 113 } 114 if(byt.endsWith("khz")) { 115 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-3).trim())*1000); 116 } 117 if(byt.endsWith("hz")) { 118 return (long)(Caster.toDoubleValue(byt.substring(0,byt.length()-2).trim())); 119 } 120 return Caster.toLongValue(byt); 121 } 122 123 public long toMillis(String time) throws PageException { 124 int last=0,index=time.indexOf(':'); 125 long hour=Caster.toIntValue(time.substring(last,index).trim()); 126 last=index+1; 127 128 index=time.indexOf(':',last); 129 long minute=Caster.toIntValue(time.substring(last,index).trim()); 130 131 double seconds=Caster.toDoubleValue(time.substring(index+1).trim()); 132 return (hour*60L*60L*1000L)+(minute*60L*1000L)+((int)(seconds*1000F)); 133 } 134 135 public static VideoExecuter createVideoExecuter(Config config) throws ClassException { 136 Class clazz = config.getVideoExecuterClass(); 137 return (VideoExecuter) ClassUtil.loadInstance(clazz); 138 } 139 140 public int[] calculateDimension(PageContext pc,VideoInput[] sources,int width, String strWidth,int height, String strHeight) throws PageException { 141 int[] rtn; 142 143 if(width!=-1 && height!=-1) { 144 return new int[]{width,height}; 145 } 146 147 // video component not installed 148 try { 149 if(VideoUtilImpl.createVideoExecuter(pc.getConfig()) instanceof VideoExecuterNotSupported){ 150 throw new ApplicationException("attributes width/height are required when no video analyser is installed"); 151 } 152 } catch (ClassException e) { 153 154 } 155 156 157 VideoInput source; 158 159 // hash 160 StringBuffer sb=new StringBuffer(strHeight+"-"+strWidth); 161 for(int i=0;i<sources.length;i++) { 162 sb.append(sources[i].getResource().toString()); 163 } 164 165 // get from casche 166 String key = Hash.call(pc, sb.toString()); 167 168 int[] ci=(int[]) sizes.get(key); 169 if(ci!=null) { 170 return ci; 171 } 172 // getSize 173 int w=0,h=0; 174 try { 175 for(int i=0;i<sources.length;i++) { 176 source = sources[i]; 177 checkResource(source.getResource()); 178 179 180 VideoInfo info = VideoUtilImpl.createVideoExecuter(pc.getConfig()).info(pc.getConfig(),source); 181 182 if(w<info.getWidth()) { 183 h=info.getHeight(); 184 w=info.getWidth(); 185 } 186 187 188 } 189 } 190 catch(Exception ve) { 191 throw Caster.toPageException(ve); 192 } 193 194 // calculate only height 195 if(width!=-1) { 196 height=calculateSingle(w,width,strHeight,h); 197 } 198 // calculate only height 199 else if(height!=-1) { 200 width=calculateSingle(h,height,strWidth,w); 201 } 202 else { 203 width=procent2pixel(strWidth,w); 204 height=procent2pixel(strHeight,h); 205 if(width!=-1 && height!=-1) {} 206 else if(width==-1 && height==-1) { 207 width=w; 208 height=h; 209 } 210 else if(width!=-1) 211 height=calucalteFromOther(h,w,width); 212 else 213 width=calucalteFromOther(w,h,height); 214 215 216 } 217 sizes.put(key, rtn=new int[]{width,height}); 218 return rtn; 219 } 220 221 private static int procent2pixel(String str, int source) throws ExpressionException { 222 if(!StringUtil.isEmpty(str)) { 223 if(StringUtil.endsWith(str, '%')) { 224 str=str.substring(0,str.length()-1).trim(); 225 double procent = Caster.toDoubleValue(str); 226 if(procent<0 ) 227 throw new ExpressionException("procent has to be positive number (now "+str+")"); 228 return (int)(source*(procent/100D)); 229 } 230 return Caster.toIntValue(str); 231 } 232 return -1; 233 } 234 235 private static int calculateSingle(int srcOther,int destOther, String strDim, int srcDim) throws ExpressionException { 236 int res = procent2pixel(strDim, srcDim); 237 if(res!=-1) return res; 238 return calucalteFromOther(srcDim,srcOther,destOther);//(int)(Caster.toDoubleValue(srcDim)*Caster.toDoubleValue(destOther)/Caster.toDoubleValue(srcOther)); 239 } 240 241 private static int calucalteFromOther(int srcDim,int srcOther,int destOther) { 242 return (int)(Caster.toDoubleValue(srcDim)*Caster.toDoubleValue(destOther)/Caster.toDoubleValue(srcOther)); 243 } 244 245 246 private static void checkResource(Resource resource) throws ApplicationException { 247 if(resource instanceof FileResource)return; 248 if(resource instanceof HTTPResource) 249 throw new ApplicationException("attribute width and height are required when external sources are invoked"); 250 251 throw new ApplicationException("the resource type ["+resource.getResourceProvider().getScheme()+"] is not supported"); 252 } 253 }