package railo.runtime.video; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.Map; import java.util.StringTokenizer; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import railo.commons.io.IOUtil; import railo.commons.io.res.Resource; import railo.loader.util.Util; import railo.runtime.config.Config; import railo.runtime.config.ConfigImpl; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.PageException; import railo.runtime.op.Caster; import railo.runtime.text.xml.XMLUtil; public class ProfileCollection { private static VideoUtil util=VideoUtilImpl.getInstance(); private Map<String,VideoProfile> profiles; public ProfileCollection(Config config) throws ApplicationException { init(config,true); } private void init(Config config, boolean initProfiles) throws ApplicationException { // get the video directory Resource dir = ((ConfigImpl)config).getVideoDirectory(); // get the video.xml Resource xml=dir.getRealResource("video.xml"); // create (if not exist) and return video xml as dom Element video; try { video = getVideoXML(xml); } catch (Exception e) { throw new ApplicationException("can not load video xml file ["+xml+"]",Caster.toClassName(e)+":"+e.getMessage()); } // translate form DOM to a List of VideoProfile if(initProfiles){ try { profiles=translateVideoXML(video); } catch (PageException e) { throw new ApplicationException("can not load profiles from video xml file ["+xml+"] a type is invalid",e.getMessage()); } } } /** * @return the qualities */ public Map<String,VideoProfile> getProfiles() { return profiles; } /** * translate form DOM to a List of VideoProfile * @param video * @return * @throws PageException */ private static Map<String,VideoProfile> translateVideoXML(Element video) throws PageException { Map<String,VideoProfile> profiles=new LinkedHashMap<String,VideoProfile>(); // quality Element qd = getChildByName(video, "profiles", false); Element[] items = getChildren(qd, "profile"); Element item; VideoProfile vq; String value; for(int i=0;i<items.length;i++) { item=items[i]; vq=new VideoProfileImpl(); // aspect-ratio value=item.getAttribute("aspect-ratio"); if(!Util.isEmpty(value))vq.setAspectRatio(value); // aspect-ratio value=item.getAttribute("audio-bitrate"); if(!Util.isEmpty(value))vq.setAudioBitrate(util.toBytes(value)); // audio-samplerate value=item.getAttribute("audio-samplerate"); if(!Util.isEmpty(value))vq.setAudioSamplerate(util.toHerz(value)); // dimension String w = item.getAttribute("width"); String h = item.getAttribute("height"); if(!Util.isEmpty(w) && !Util.isEmpty(h)) { vq.setDimension(Caster.toIntValue(w), Caster.toIntValue(h)); } // framerate value=item.getAttribute("framerate"); String value2 = item.getAttribute("fps"); if(!Util.isEmpty(value))vq.setFramerate(Caster.toDoubleValue(value)); else if(!Util.isEmpty(value2))vq.setFramerate(Caster.toDoubleValue(value2)); // video-bitrate value=item.getAttribute("video-bitrate"); if(!Util.isEmpty(value))vq.setVideoBitrate(util.toBytes(value)); // video-bitrate-max value=item.getAttribute("video-bitrate-max"); if(!Util.isEmpty(value))vq.setVideoBitrateMax(util.toBytes(value)); // video-bitrate-min value=item.getAttribute("video-bitrate-min"); if(!Util.isEmpty(value))vq.setVideoBitrateMin(util.toBytes(value)); // video-bitrate-tolerance value=item.getAttribute("video-bitrate-tolerance"); if(!Util.isEmpty(value))vq.setVideoBitrateTolerance(util.toBytes(value)); // video-codec value=item.getAttribute("video-codec"); //print.out("video-codec:"+value); if(!Util.isEmpty(value))vq.setVideoCodec(value); // audio-codec value=item.getAttribute("audio-codec"); if(!Util.isEmpty(value))vq.setAudioCodec(value); // value=item.getAttribute("label"); //print.out("label:"+value); if(!Util.isEmpty(value)) { String[] arr=toArray(value); for(int y=0;y<arr.length;y++) { profiles.put(arr[y].trim().toLowerCase(), vq); } } } return profiles; } private static Element getChildByName(Node parent, String nodeName,boolean insertBefore) { if(parent==null) return null; NodeList list=parent.getChildNodes(); int len=list.getLength(); for(int i=0;i<len;i++) { Node node=list.item(i); if(node.getNodeType()==Node.ELEMENT_NODE && node.getNodeName().equalsIgnoreCase(nodeName)) { return (Element) node; } } Element newEl = parent.getOwnerDocument().createElement(nodeName); if(insertBefore)parent.insertBefore(newEl, parent.getFirstChild()); else parent.appendChild(newEl); return newEl; } private static Element[] getChildren(Node parent, String nodeName) { if(parent==null) return new Element[0]; NodeList list=parent.getChildNodes(); int len=list.getLength(); ArrayList rtn=new ArrayList(); for(int i=0;i<len;i++) { Node node=list.item(i); if(node.getNodeType()==Node.ELEMENT_NODE && node.getNodeName().equalsIgnoreCase(nodeName)) { rtn.add(node); } } return (Element[]) rtn.toArray(new Element[rtn.size()]); } private static String[] toArray(String str) { StringTokenizer st=new StringTokenizer(str,","); ArrayList list=new ArrayList(); while(st.hasMoreTokens()) { list.add(str=st.nextToken()); } return (String[]) list.toArray(new String[list.size()]); } /** * create (if not exist) and return video xml as dom * @param xml * @return * @throws IOException * @throws SAXException */ private static Element getVideoXML(Resource xml) throws IOException, SAXException { if(!xml.exists()) { createFileFromResource("/resource/video/video.xml",xml); } Document doc = loadDocument(xml); return doc.getDocumentElement(); } public static void createFileFromResource(String path, Resource bin) throws IOException { InputStream is=null; OutputStream os=null; if(bin.exists()) return; try { Util.copy( is=new VideoInputImpl(null).getClass().getResourceAsStream(path), os=bin.getOutputStream() ); } finally { Util.closeEL(is); Util.closeEL(os); } } private static Document loadDocument(Resource xmlFile) throws SAXException, IOException { InputStream is=null; try { return loadDocument(is=xmlFile.getInputStream()); } finally { Util.closeEL(is); } } private static Document loadDocument(InputStream is) throws SAXException, IOException { try{ InputSource source = new InputSource(is); return XMLUtil.parse(source, null, false); } finally { IOUtil.closeEL(is); } } }