package railo.runtime.tag;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.Random;
import railo.commons.io.res.Resource;
import railo.commons.io.res.util.ResourceUtil;
import railo.commons.lang.ClassException;
import railo.commons.lang.StringUtil;
import railo.loader.util.Util;
import railo.runtime.PageContext;
import railo.runtime.exp.ApplicationException;
import railo.runtime.exp.PageException;
import railo.runtime.ext.tag.TagSupport;
import railo.runtime.op.Caster;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.util.KeyConstants;
import railo.runtime.video.ProfileCollection;
import railo.runtime.video.VideoExecuter;
import railo.runtime.video.VideoInfo;
import railo.runtime.video.VideoInput;
import railo.runtime.video.VideoInputImpl;
import railo.runtime.video.VideoOutput;
import railo.runtime.video.VideoOutputImpl;
import railo.runtime.video.VideoProfile;
import railo.runtime.video.VideoProfileImpl;
import railo.runtime.video.VideoUtilImpl;
/**
* implementation of the tag Compiler
*/
public class Video extends TagSupport {
private static final int ACTION_CONVERT=0;
private static final int ACTION_INFO=1;
private static final int ACTION_CONCAT=2;
private static final int ACTION_CUT_IMAGE=4;
private static final int ACTION_INSTALL=8;
private static final int ACTION_UNINSTALL=16;
public static final int NAMECONFLICT_UNDEFINED=0;
public static final int NAMECONFLICT_ERROR=1;
public static final int NAMECONFLICT_SKIP=2;
public static final int NAMECONFLICT_OVERWRITE=3;
public static final int NAMECONFLICT_MAKEUNIQUE=4;
public static final int EXECUTION_QUALITY=0;
public static final int EXECUTION_PERFORMANCE=1;
private static final Key SOURCE = KeyConstants._source;
private static final Key SOURCE1 = KeyImpl.intern("source1");
private static final Key SOURCE2 = KeyImpl.intern("source2");
private static final Key AUDIO = KeyImpl.intern("audio");
private static final Key VIDEO = KeyImpl.intern("video");
private static VideoUtilImpl util=VideoUtilImpl.getInstance();
private String result="cfvideo";
private int action;
private String strAction;
private VideoInput source;
private VideoInput source1;
private VideoInput source2;
private VideoOutput destination;
private int nameconflict=NAMECONFLICT_UNDEFINED;
private String name;
private int width=-1;
private int height=-1;
private String strWidth;
private String strHeight;
private Struct data;
private long audiosamplerate=0;
private long audioBitrate=0;
private double startTime=0;
private long startFrame=0;
private double maxTime=0;
private long maxFrame=0;
private VideoProfile profile=null;
private int aspectRatio;
private int framerate;
private long videoBitrate;
private long videoBitrateMin;
private long videoBitrateMax;
private long videoBitrateTolerance;
private String debug=null;
private String author;
private String title;
private String comment;
private String copyright;
private String videoCodec;
private String audioCodec;
private long buffersize;
private int execution=EXECUTION_PERFORMANCE;
private static ProfileCollection _profileCollection;
public Video(){
}
@Override
public void release() {
super.release();
result="cfvideo";
execution=EXECUTION_PERFORMANCE;
source=null;
source1=null;
source2=null;
destination=null;
nameconflict=NAMECONFLICT_UNDEFINED;
name=null;
width=-1;
height=-1;
profile=null;
audioBitrate=0;
videoCodec=null;
audioCodec=null;
audiosamplerate=0;
aspectRatio=0;
framerate=0;
videoBitrate=0;
videoBitrateMin=0;
videoBitrateMax=0;
videoBitrateTolerance=0;
buffersize=0;
author=null;
title=null;
comment=null;
copyright=null;
debug=null;
maxTime=0;
maxFrame=0;
startTime=0;
startFrame=0;
strWidth=null;
strHeight=null;
data=null;
}
/**
* @param action the action to set
* @throws PageException
*/
public void setAction(String action) throws PageException {
strAction=action;
action=action.toLowerCase().trim();
if(action.equals("concat")) this.action=ACTION_CONCAT;
else if(action.equals("merge")) this.action=ACTION_CONCAT;
else if(action.equals("convert")) this.action=ACTION_CONVERT;
//else if(action.equals("cut")) this.action=ACTION_CUT;
else if(action.equals("cut image")) this.action=ACTION_CUT_IMAGE;
else if(action.equals("cutimage")) this.action=ACTION_CUT_IMAGE;
else if(action.equals("cut_image")) this.action=ACTION_CUT_IMAGE;
else if(action.equals("cut-image")) this.action=ACTION_CUT_IMAGE;
else if(action.equals("info")) this.action=ACTION_INFO;
else if(action.equals("install")) this.action=ACTION_INSTALL;
else if(action.equals("uninstall")) this.action=ACTION_UNINSTALL;
else throw doThrow("invalid value for attribute action for tag video ["+action+"], " +
"valid actions are [concat, convert, cutImage, info,install,uninstall]");
}
/**
* @param source the source to set
* @throws PageException
*/
public void setSource(String source) throws PageException {
this.source = new VideoInputImpl(ResourceUtil.toResourceExisting(pageContext, source));
}
public void setData(Struct data){
this.data=data;
}
/**
* @param destination the destination to set
* @throws PageException
*/
public void setDestination(String destination) {
this.destination = new VideoOutputImpl(ResourceUtil.toResourceNotExisting(pageContext, destination));
}
/** set the value nameconflict
* Action to take if filename is the same as that of a file in the directory.
* @param nameconflict value to set
* @throws ApplicationException
**/
public void setNameconflict(String nameconflict) throws PageException {
nameconflict=nameconflict.toLowerCase().trim();
if("error".equals(nameconflict)) this.nameconflict=NAMECONFLICT_ERROR;
else if("skip".equals(nameconflict)) this.nameconflict=NAMECONFLICT_SKIP;
else if("overwrite".equals(nameconflict)) this.nameconflict=NAMECONFLICT_OVERWRITE;
else if("makeunique".equals(nameconflict)) this.nameconflict=NAMECONFLICT_MAKEUNIQUE;
else throw doThrow("invalid value for attribute nameconflict ["+nameconflict+"]",
"valid values are [error,skip,overwrite,makeunique]");
}
public void setProfile(String strProfile) throws PageException {
VideoProfile p = getProfile(strProfile);
if(p!=null)profile=p.duplicate();
else throw doThrow("invalid profile defintion ["+strProfile+"], valid profiles are ["+getProfileKeyList()+"]");
}
public void setExecution(String execution) throws PageException {
execution=execution.toLowerCase().trim();
if("quality".equals(execution)) this.execution=EXECUTION_QUALITY;
else if("q".equals(execution)) this.execution=EXECUTION_QUALITY;
else if("performance".equals(execution)) this.execution=EXECUTION_PERFORMANCE;
else if("p".equals(execution)) this.execution=EXECUTION_PERFORMANCE;
else throw doThrow("invalid value for attribute execution ["+execution+"]",
"valid values are [quality,performance]");
}
public void setQuality(String strQuality) throws PageException {
setProfile(strQuality);
}
@Override
public int doStartTag() throws PageException {
try {
if(action==ACTION_CONVERT) doActionConvert();
else if(action==ACTION_CONCAT) doActionConcat();
else if(action==ACTION_CUT_IMAGE) doActionCutImage();
else if(action==ACTION_INFO) doActionInfo();
else if(action==ACTION_INSTALL) doActionInstall();
else if(action==ACTION_UNINSTALL) doActionUninstall();
}
catch(Throwable t) {
throw Caster.toPageException(t);
}
return SKIP_BODY;
}
private void doActionInstall() throws ClassException, IOException {
if(data==null)data=new StructImpl();
getVideoExecuter().install(pageContext.getConfig(),data);
}
private void doActionUninstall() throws ClassException, IOException {
getVideoExecuter().uninstall(pageContext.getConfig());
}
public Struct doActionInfo() throws PageException, IOException {
return doActionInfo(source);
}
private Struct doActionInfo(VideoInput source) throws PageException, IOException {
// precheck settings
checkFile(source,"source", true, true, false);
//VideoConfig vc = getConfig();
debug(source);
Struct info = toStruct(getVideoExecuter().info(pageContext.getConfig(), source));
pageContext.setVariable(result,info);
return info;
}
private VideoExecuter getVideoExecuter() throws ClassException {
return VideoUtilImpl.createVideoExecuter(pageContext.getConfig());
}
private VideoInfo getInfo(VideoInput source) throws PageException, IOException {
// precheck settings
checkFile(source,"source", true, true, false);
// execute
return getVideoExecuter().info(pageContext.getConfig(),source);
//print.out(raw);
// write cfvideo
//return new Info(raw,true,startTime,maxTime);
}
private void doActionCutImage() throws PageException, IOException {
// precheck settings
checkFile(source,"source", true, true, false);
if(!checkDestination(source,destination,name,nameconflict)) return;
// input
if(profile==null)profile=new VideoProfileImpl();
// settings
settings(destination,profile);
destination.setMaxFrames(1);
destination.setFormat("image2");
// execute
Struct info=toStruct(getVideoExecuter().convert(pageContext.getConfig(),new VideoInput[]{source},destination,profile));
// write cfvideo
debug(source);
pageContext.setVariable(result,info);
//setResult(raw,false);
}
private void doActionConcat() throws PageException, IOException {
// precheck settings
checkFile(source1,"source1", true, true, false);
checkFile(source2,"source2", true, true, false);
if(!checkDestination(source1,destination,name,nameconflict)) return;
Pair s1 =toMpeg(source1);
Pair s2 =toMpeg(source2);
source = new VideoInputImpl(pageContext.getConfig().getTempDirectory().getRealResource("tmp-"+new Random().nextInt()+".mpg"));
try {
merge(s1.res,s2.res,source.getResource());
Struct sct = doActionConvert();
sct.setEL(SOURCE1, s1.sct);
sct.setEL(SOURCE2, s2.sct);
sct.removeEL(SOURCE);
}
finally {
source.getResource().delete();
if(!s1.res.equals(source1.getResource()))s1.res.delete();
if(!s2.res.equals(source2.getResource()))s2.res.delete();
}
}
private void merge(Resource in1, Resource in2, Resource out) throws IOException {
InputStream is1=null;
InputStream is2=null;
OutputStream os=null;
try {
is1=in1.getInputStream();
is2=in2.getInputStream();
os=out.getOutputStream();
}
catch(IOException ioe) {
Util.closeEL(is1);
Util.closeEL(is2);
Util.closeEL(os);
throw ioe;
}
try {
copy(is1, os);
copy(is2, os);
}
finally {
Util.closeEL(is1);
Util.closeEL(is2);
Util.closeEL(os);
}
}
public final static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[0xffff];
int len;
while((len = in.read(buffer)) !=-1)
out.write(buffer, 0, len);
}
private Pair toMpeg(VideoInput vi) throws PageException, IOException {
VideoInfo info = getInfo(vi);
//Struct sct = _doActionInfo(vi);
if("mpeg1video".equals(info.getVideoCodec()))
return new Pair(vi.getResource(),toStruct(info));
VideoOutput tmp = new VideoOutputImpl(pageContext.getConfig().getTempDirectory().getRealResource("tmp-"+new Random().nextInt()+".mpg"));
try {
doActionConvert(vi,tmp,null,null,NAMECONFLICT_ERROR);
return new Pair(tmp.getResource(),toStruct(info));
}
catch(PageException pe) {
tmp.getResource().delete();
throw pe;
}
catch(IOException ioe) {
tmp.getResource().delete();
throw ioe;
}
}
private Struct doActionConvert() throws PageException, IOException {
return doActionConvert(source,destination,profile,name,nameconflict);
}
private Struct doActionConvert(VideoInput source,VideoOutput destination, VideoProfile quality,String name, int nameconflict) throws PageException, IOException {
// precheck settings
checkFile(source,"source", true, true, false);
if(!checkDestination(source,destination,name,nameconflict)) return new StructImpl();
// input
if(quality==null)quality=new VideoProfileImpl();
// settings
settings(destination,quality);
// execute
Struct info = toStruct(getVideoExecuter().convert(pageContext.getConfig(),new VideoInput[]{source},destination,quality));
// write cfvideo
debug(source);
pageContext.setVariable(result,info);
return info;
//return setResult(raw,false);
}
private void debug(VideoInput vi) throws PageException {
if(!StringUtil.isEmpty(debug))pageContext.setVariable(debug, vi.getCommandAsString());
}
private void settings(VideoOutput vo,VideoProfile vq) throws PageException, IOException {
defineSize(vq,new VideoInput[]{source});
if(audioBitrate>0)vq.setAudioBitrate(audioBitrate);
if(aspectRatio>0)vq.setAspectRatio(aspectRatio);
if(framerate>0)vq.setFramerate(framerate);
if(videoBitrate>0)vq.setVideoBitrate(videoBitrate);
if(videoBitrateMin>0)vq.setVideoBitrateMin(videoBitrateMin);
if(videoBitrateMax>0)vq.setVideoBitrateMax(videoBitrateMax);
if(videoBitrateTolerance>0)vq.setVideoBitrateTolerance(videoBitrateTolerance);
if(audiosamplerate>0)vq.setAudioSamplerate(audiosamplerate);
if(buffersize>0)vq.setBufferSize(buffersize);
if(execution==EXECUTION_QUALITY)vq.setPass(2);
if(!StringUtil.isEmpty(title))vo.setTitle(title);
if(!StringUtil.isEmpty(author))vo.setAuthor(author);
if(!StringUtil.isEmpty(comment))vo.setComment(comment);
if(!StringUtil.isEmpty(copyright))vo.setCopyright(copyright);
if(!StringUtil.isEmpty(videoCodec))vq.setVideoCodec(videoCodec);
if(!StringUtil.isEmpty(audioCodec))vq.setAudioCodec(audioCodec);
if(framerate==0 && (startFrame>0 || maxTime>0)) {
framerate=(int)getInfo(source).getFramerate();
}
// start
if(startFrame>0) {
if(framerate>0) startTime=(startFrame/framerate);
}
if(startTime>0)destination.setOffset(startTime);
// max
if(maxTime>0) {
if(framerate>0) maxFrame=(long)(maxTime*framerate);
}
if(maxTime>0)vo.setMaxFrames(maxFrame);
// maxtime (only for cfvideo struct)
if(maxFrame>0 && maxTime==0) {
if(framerate!=-1) maxTime=maxFrame/framerate;
}
destination.setFrameRate(framerate);
}
private ProfileCollection getProfileCollection() throws PageException {
return getProfileCollection(pageContext);
}
public static ProfileCollection getProfileCollection(PageContext pc) throws PageException {
if(_profileCollection==null) {
try {
_profileCollection=new ProfileCollection(pc.getConfig());
}
catch (Exception e) {
throw Caster.toPageException(e);
}
}
return _profileCollection;
}
private void defineSize(VideoProfile quality, VideoInput[] sources) throws PageException {
if(strWidth!=null || strHeight!=null) {
int[] dim = VideoUtilImpl.getInstance().calculateDimension(pageContext, sources, width, strWidth, height, strHeight);
quality.setDimension(dim[0], dim[1]);
}
}
private void checkFile(VideoInput vi, String label, boolean exist, boolean canRead, boolean canWrite) throws PageException {
if(vi==null) {
throw doThrow("attribute "+label+" is required for tag video action "+strAction);
}
checkFile(vi.getResource(), label, exist, canRead, canWrite);
}
private void checkFile(VideoOutput vo, String label, boolean exist, boolean canRead, boolean canWrite) throws PageException {
if(vo==null) {
throw doThrow("attribute "+label+" is required for tag video action "+strAction);
}
checkFile(vo.getResource(), label, exist, canRead, canWrite);
}
private void checkFile(Resource res, String label, boolean exist, boolean canRead, boolean canWrite) throws PageException {
if(res==null) {
throw doThrow("attribute "+label+" is required for tag video action "+strAction);
}
if(!res.exists()) {
if(exist)throw doThrow(""+label+" file does not exist");
}
else {
if(!res.isFile())
throw doThrow(label+" ["+res.toString()+"] is not a file");
else if(canRead &&!res.canRead())
throw doThrow("no read access to "+label+" ["+res.toString()+"]");
else if(canWrite && !res.canWrite())
throw doThrow("no write access to "+label+" ["+res.toString()+"]");
}
}
private boolean checkDestination(VideoInput vi, VideoOutput destination, String name, int nameconflict) throws PageException {
checkFile(destination,"destination", false, false, false);
// destination
if(!Util.isEmpty(name))destination.setResource(destination.getResource().getRealResource(name));
else if(destination.getResource().isDirectory()) {
destination.setResource(destination.getResource().getRealResource(vi.getResource().getName()));
}
// escape %d
String _name=destination.getResource().getName();
if(_name.indexOf("%d")!=-1) {
destination.setResource(destination.getResource().getParentResource().getRealResource(_name.replaceAll("%d", "%%d")));
}
if(destination.getResource().exists() && nameconflict!=NAMECONFLICT_OVERWRITE) {
// SKIP
if(nameconflict==NAMECONFLICT_SKIP) return false;
// MAKEUNIQUE
else if(nameconflict==NAMECONFLICT_MAKEUNIQUE) destination.setResource(makeUnique(destination.getResource()));
// ERROR
else doThrow("destiniation file ["+destination.toString()+"] already exist");
}
return true;
}
private Resource makeUnique(Resource res) {
String ext=getFileExtension(res);
String name=getFileName(res);
ext=(ext==null)?"":"."+ext;
int count=0;
while(res.exists()) {
res=res.getParentResource().getRealResource(name+(++count)+ext);
}
return res;
}
/**
* get file extension of a file object
* @param file file object
* @return extnesion
*/
private static String getFileExtension(Resource file) {
String name=file.getName();
int index = name.lastIndexOf('.');
if(index==-1) return null;
return name.substring(index+1).trim();
}
/**
* get file name of a file object without extension
* @param file file object
* @return name of the file
*/
private static String getFileName(Resource file) {
String name=file.getName();
int pos=name.lastIndexOf(".");
if(pos==-1)return name;
return name.substring(0,pos);
}
private VideoProfile getProfile(String strProfile) throws PageException {
strProfile=strProfile.trim().toLowerCase();
return getProfileCollection().getProfiles().get(strProfile);
}
private String getProfileKeyList() throws PageException {
Iterator<String> it = getProfileCollection().getProfiles().keySet().iterator();
StringBuffer sb=new StringBuffer();
boolean doDel=false;
while(it.hasNext()) {
if(doDel)sb.append(", ");
sb.append(it.next());
doDel=true;
}
return sb.toString();
}
private PageException doThrow(String message) {
return doThrow(message,null);
}
private PageException doThrow(String message, String detail) {
if(detail==null)return new ApplicationException(message);
return new ApplicationException(message,detail);
}
/**
* @param width the width to set
*/
public void setWidth(String strWidth) {
this.width = Caster.toIntValue(strWidth,-1);
this.strWidth = strWidth;
}
/**
* @param height the height to set
*/
public void setHeight(String strHeight) {
this.height = Caster.toIntValue(strHeight,-1);
this.strHeight = strHeight;
}
/**
* @param audioBitrate the audioBitrate to set
* @throws PageException
*/
public void setAudiobitrate(String audioBitrate) throws PageException {
this.audioBitrate = util.toBytes(audioBitrate);
}
/**
* @param aspectRatio the aspectRatio to set
* @throws PageException
*/
public void setAspectratio(String strAspectRatio) throws PageException {
strAspectRatio=strAspectRatio.trim().toLowerCase();
if("16:9".equals(strAspectRatio)) aspectRatio=VideoProfile.ASPECT_RATIO_16_9;
else if("4:3".equals(strAspectRatio)) aspectRatio=VideoProfile.ASPECT_RATIO_4_3;
else throw doThrow("invalid aspect ratio definition ["+strAspectRatio+"], valid values are [16:9, 4:3]");
}
/**
* @param framerate the framerate to set
*/
public void setFramerate(double framerate) {
setFps(framerate);
}
public void setFps(double framerate) {
this.framerate = (int) framerate;
}
/**
* @param videoBitrate the videoBitrate to set
* @throws PageException
*/
public void setVideobitrate(String videoBitrate) throws PageException {
this.videoBitrate = util.toBytes(videoBitrate);
}
/**
* @param videoBitrateMin the videoBitrateMin to set
* @throws PageException
*/
public void setVideobitratemin(String videoBitrateMin) throws PageException {
this.videoBitrateMin = util.toBytes(videoBitrateMin);
}
/**
* @param videoBitrateMax the videoBitrateMax to set
* @throws PageException
*/
public void setVideobitratemax(String videoBitrateMax) throws PageException {
this.videoBitrateMax = util.toBytes(videoBitrateMax);
}
/**
* @param videoBitrateTolerance the videoBitrateTolerance to set
* @throws PageException
*/
public void setVideobitratetolerance(String videoBitrateTolerance) throws PageException {
this.videoBitrateTolerance = util.toBytes(videoBitrateTolerance);
}
/**
* @param author the author to set
*/
public void setAuthor(String author) {
this.author = author;
}
/**
* @param title the title to set
*/
public void setTitle(String title) {
this.title = title;
}
/**
* @param comment the comment to set
*/
public void setComment(String comment) {
this.comment = comment;
}
/**
* @param copyright the copyright to set
*/
public void setCopyright(String copyright) {
this.copyright = copyright;
}
/**
* @param max the maxFrames to set
* @throws PageException
*/
public void setMax(String strMax) throws PageException {
strMax=strMax.trim().toLowerCase();
if(strMax.endsWith("f")) this.maxFrame=Caster.toLongValue(strMax.substring(0,strMax.length()-1));
else if(strMax.endsWith("ms")) this.maxTime=Caster.toDoubleValue(strMax.substring(0,strMax.length()-2))/1000F;
else if(strMax.endsWith("s")) this.maxTime=Caster.toDoubleValue(strMax.substring(0,strMax.length()-1));
else setStart(strMax+" ms");
}
/**
* @param result the result to set
*/
public void setResult(String result) {
this.result = result;
}
/**
* @param source1 the source1 to set
* @throws PageException
*/
public void setSource1(String source1) throws PageException {
this.source1 = new VideoInputImpl(ResourceUtil.toResourceExisting(pageContext, source1));
}
/**
* @param source2 the source2 to set
* @throws PageException
*/
public void setSource2(String source2) throws PageException {
this.source2 = new VideoInputImpl(ResourceUtil.toResourceExisting(pageContext, source2));
}
/**
* @param strStart the position to set
* @throws PageException
*/
public void setStart(String strStart) throws PageException {
strStart=strStart.trim().toLowerCase();
if(strStart.endsWith("f")) this.startFrame=Caster.toLongValue(strStart.substring(0,strStart.length()-1));
else if(strStart.endsWith("ms")) this.startTime=Caster.toDoubleValue(strStart.substring(0,strStart.length()-2))/1000F;
else if(strStart.endsWith("s")) this.startTime=Caster.toDoubleValue(strStart.substring(0,strStart.length()-1));
else setStart(strStart+" ms");
}
/**
* @param videoCodec the videoCodec to set
*/
public void setVideocodec(String videoCodec) {
this.videoCodec = videoCodec;
}
public void setAudiocodec(String audioCodec) {
this.audioCodec = audioCodec;
}
class Pair {
Resource res;
Struct sct;
public Pair(Resource res, Struct sct) {
this.res = res;
this.sct = sct;
}
}
/**
* @param audiosamplerate the audiosamplerate to set
* @throws PageException
*/
public void setAudiosamplerate(String sAudiosamplerate) throws PageException {
this.audiosamplerate = util.toHerz(sAudiosamplerate);
}
public static void checkRestriction() {
}
/**
* @param debug the debug to set
*/
public void setDebug(String debug) {
this.debug = debug;
}
/**
* @param buffersize the buffersize to set
*/
public void setBuffersize(double buffersize) {
this.buffersize = (long) buffersize;
}
public Struct toStruct(VideoInfo[] infos) {
Struct sct=new StructImpl();
sct.setEL(KeyConstants._source, toStruct(infos[0]));
sct.setEL(KeyConstants._destination, toStruct(infos[1]));
return sct;
}
private Struct toStruct(VideoInfo info) {
Struct sct=info.toStruct();
// audio
Struct audio=Caster.toStruct(sct.get(AUDIO,null),null);
if(audio==null) {
audio=new StructImpl();
sct.setEL(AUDIO, audio);
}
// video
Struct video=Caster.toStruct(sct.get(VIDEO,null),null);
if(video==null) {
video=new StructImpl();
sct.setEL(VIDEO, video);
}
// Audio
audio.setEL("channels", info.getAudioChannels());
audio.setEL(KeyConstants._codec, info.getAudioCodec());
if(info.getAudioBitrate()!=-1)audio.setEL("bitrate", new Double(info.getAudioBitrate()));
if(info.getAudioSamplerate()!=-1)audio.setEL("samplerate", new Double(info.getAudioSamplerate()));
// Video
video.setEL(KeyConstants._codec, info.getVideoCodec());
video.setEL(KeyConstants._format, info.getVideoFormat());
if(info.getVideoBitrate()!=-1)video.setEL("bitrate", new Double(info.getVideoBitrate()));
if(info.getFramerate()!=-1)video.setEL("framerate", new Double(info.getFramerate()));
// Allgemein
if(info.getDuration()!=-1)sct.setEL("duration", new Double(info.getDuration()));
if(info.getHeight()!=-1)sct.setEL(KeyConstants._height, new Double(info.getHeight()));
if(info.getWidth()!=-1)sct.setEL(KeyConstants._width, new Double(info.getWidth()));
return sct;
}
}