001    package railo.runtime.tag;
002    
003    
004    import java.io.IOException;
005    import java.io.InputStream;
006    import java.io.OutputStream;
007    import java.util.Iterator;
008    import java.util.Random;
009    
010    import railo.commons.io.res.Resource;
011    import railo.commons.io.res.util.ResourceUtil;
012    import railo.commons.lang.ClassException;
013    import railo.commons.lang.StringUtil;
014    import railo.loader.util.Util;
015    import railo.runtime.PageContext;
016    import railo.runtime.exp.ApplicationException;
017    import railo.runtime.exp.PageException;
018    import railo.runtime.ext.tag.TagSupport;
019    import railo.runtime.op.Caster;
020    import railo.runtime.type.Collection.Key;
021    import railo.runtime.type.KeyImpl;
022    import railo.runtime.type.Struct;
023    import railo.runtime.type.StructImpl;
024    import railo.runtime.type.util.KeyConstants;
025    import railo.runtime.video.ProfileCollection;
026    import railo.runtime.video.VideoExecuter;
027    import railo.runtime.video.VideoInfo;
028    import railo.runtime.video.VideoInput;
029    import railo.runtime.video.VideoInputImpl;
030    import railo.runtime.video.VideoOutput;
031    import railo.runtime.video.VideoOutputImpl;
032    import railo.runtime.video.VideoProfile;
033    import railo.runtime.video.VideoProfileImpl;
034    import railo.runtime.video.VideoUtilImpl;
035    
036    /**
037     * implementation of the tag Compiler
038     */
039    public class Video extends TagSupport {
040    
041            private static final int ACTION_CONVERT=0;
042            private static final int ACTION_INFO=1;
043            private static final int ACTION_CONCAT=2;
044            private static final int ACTION_CUT_IMAGE=4;
045            private static final int ACTION_INSTALL=8;
046            private static final int ACTION_UNINSTALL=16;
047            
048            public static final int NAMECONFLICT_UNDEFINED=0;
049            public static final int NAMECONFLICT_ERROR=1;
050            public static final int NAMECONFLICT_SKIP=2;
051            public static final int NAMECONFLICT_OVERWRITE=3;
052            public static final int NAMECONFLICT_MAKEUNIQUE=4;
053    
054            public static final int EXECUTION_QUALITY=0;
055            public static final int EXECUTION_PERFORMANCE=1;
056            private static final Key SOURCE = KeyConstants._source;
057            private static final Key SOURCE1 = KeyImpl.intern("source1");
058            private static final Key SOURCE2 = KeyImpl.intern("source2");
059            private static final Key AUDIO = KeyImpl.intern("audio");
060            private static final Key VIDEO = KeyImpl.intern("video");
061            
062            private static VideoUtilImpl util=VideoUtilImpl.getInstance();
063            
064            
065            private String result="cfvideo";
066            private int action;
067            private String strAction;
068            private VideoInput source;
069            private VideoInput source1;
070            private VideoInput source2;
071            private VideoOutput destination;
072            private int nameconflict=NAMECONFLICT_UNDEFINED;
073            private String name;
074            private int width=-1;
075            private int height=-1;
076            private String strWidth;
077            private String strHeight;
078            private Struct data;
079            
080    
081            private long audiosamplerate=0;
082            private long audioBitrate=0;
083            private double startTime=0;
084            private long startFrame=0;
085            private double maxTime=0;
086            private long maxFrame=0;
087            
088            private VideoProfile profile=null;
089            
090            private int aspectRatio;
091            private int framerate;
092            private long videoBitrate;
093            private long videoBitrateMin;
094            private long videoBitrateMax;
095            private long videoBitrateTolerance;
096            private String debug=null;
097            
098            private String author;
099            private String title;
100            private String comment;
101            private String copyright;
102            private String videoCodec;
103            private String audioCodec;
104            private long buffersize;
105            private int execution=EXECUTION_PERFORMANCE;
106            private static ProfileCollection _profileCollection;
107            
108            public Video(){
109                    
110            }
111            
112            @Override
113            public void release() {
114                    super.release();
115                    result="cfvideo";
116                    execution=EXECUTION_PERFORMANCE;
117                    source=null;
118                    source1=null;
119                    source2=null;
120                    destination=null;
121                    nameconflict=NAMECONFLICT_UNDEFINED;
122                    name=null;
123                    width=-1;
124                    height=-1;
125                    profile=null;
126                    audioBitrate=0;
127                    videoCodec=null;
128                    audioCodec=null;
129                    
130                    audiosamplerate=0;
131                    aspectRatio=0;
132                    framerate=0;
133                    videoBitrate=0;
134                    videoBitrateMin=0;
135                    videoBitrateMax=0;
136                    videoBitrateTolerance=0;
137                    buffersize=0;
138                    author=null;
139                    title=null;
140                    comment=null;
141                    copyright=null;
142                    debug=null;
143    
144                    maxTime=0;
145                    maxFrame=0;
146                    startTime=0;
147                    startFrame=0;
148                    strWidth=null;
149                    strHeight=null;
150                    data=null;
151            }
152            
153    
154    
155            /**
156             * @param action the action to set
157             * @throws PageException 
158             */
159            public void setAction(String action) throws PageException {
160                    strAction=action;
161                    action=action.toLowerCase().trim();
162            if(action.equals("concat"))                     this.action=ACTION_CONCAT; 
163            else if(action.equals("merge"))                 this.action=ACTION_CONCAT; 
164            else if(action.equals("convert"))       this.action=ACTION_CONVERT;
165            //else if(action.equals("cut"))         this.action=ACTION_CUT;
166            else if(action.equals("cut image"))     this.action=ACTION_CUT_IMAGE;
167            else if(action.equals("cutimage"))      this.action=ACTION_CUT_IMAGE;
168            else if(action.equals("cut_image"))     this.action=ACTION_CUT_IMAGE;
169            else if(action.equals("cut-image"))     this.action=ACTION_CUT_IMAGE;
170            else if(action.equals("info"))          this.action=ACTION_INFO;
171            
172            else if(action.equals("install"))               this.action=ACTION_INSTALL;
173            else if(action.equals("uninstall"))             this.action=ACTION_UNINSTALL;
174            
175            else throw doThrow("invalid value for attribute action for tag video ["+action+"], " +
176                            "valid actions are [concat, convert, cutImage, info]");
177                    
178            }
179    
180            /**
181             * @param source the source to set
182             * @throws PageException 
183             */
184            public void setSource(String source) throws PageException {
185                    this.source = new VideoInputImpl(ResourceUtil.toResourceExisting(pageContext, source));
186            }
187            
188            public void setData(Struct data){
189                    this.data=data;
190            }
191    
192            /**
193             * @param destination the destination to set
194             * @throws PageException 
195             */
196            public void setDestination(String destination) {
197                    this.destination = new VideoOutputImpl(ResourceUtil.toResourceNotExisting(pageContext, destination));
198            }
199    
200            /** set the value nameconflict
201            *  Action to take if filename is the same as that of a file in the directory.
202            * @param nameconflict value to set
203             * @throws ApplicationException 
204            **/
205            public void setNameconflict(String nameconflict) throws PageException   {
206                    nameconflict=nameconflict.toLowerCase().trim();
207                    if("error".equals(nameconflict))                        this.nameconflict=NAMECONFLICT_ERROR;
208                    else if("skip".equals(nameconflict))            this.nameconflict=NAMECONFLICT_SKIP;
209                    else if("overwrite".equals(nameconflict))       this.nameconflict=NAMECONFLICT_OVERWRITE;
210                    else if("makeunique".equals(nameconflict))      this.nameconflict=NAMECONFLICT_MAKEUNIQUE;
211                    else throw doThrow("invalid value for attribute nameconflict ["+nameconflict+"]",
212                                    "valid values are [error,skip,overwrite,makeunique]");
213            }
214    
215            public void setProfile(String strProfile) throws PageException {
216                    VideoProfile p = getProfile(strProfile);
217                    if(p!=null)profile=p.duplicate();
218                    else throw doThrow("invalid profile defintion ["+strProfile+"], valid profiles are ["+getProfileKeyList()+"]");
219            }
220    
221            public void setExecution(String execution) throws PageException {
222    
223                    execution=execution.toLowerCase().trim();
224                    if("quality".equals(execution))                         this.execution=EXECUTION_QUALITY;
225                    else if("q".equals(execution))                          this.execution=EXECUTION_QUALITY;
226                    else if("performance".equals(execution))        this.execution=EXECUTION_PERFORMANCE;
227                    else if("p".equals(execution))                          this.execution=EXECUTION_PERFORMANCE;
228                    else throw doThrow("invalid value for attribute execution ["+execution+"]",
229                                    "valid values are [quality,performance]");
230            }
231    
232            public void setQuality(String strQuality) throws PageException {
233                    setProfile(strQuality);
234            }
235                    
236            @Override
237            public int doStartTag() throws PageException    {
238                    
239                    try {
240                            if(action==ACTION_CONVERT) doActionConvert();
241                            else if(action==ACTION_CONCAT) doActionConcat();
242                            else if(action==ACTION_CUT_IMAGE) doActionCutImage();
243                            else if(action==ACTION_INFO) doActionInfo();
244                            else if(action==ACTION_INSTALL) doActionInstall();
245                            else if(action==ACTION_UNINSTALL) doActionUninstall();
246                    }
247                    catch(Throwable t) {
248                            throw Caster.toPageException(t);
249                    }
250                    return SKIP_BODY;
251            }
252    
253    
254    
255            private void doActionInstall() throws ClassException, IOException {
256                    if(data==null)data=new StructImpl();
257                    getVideoExecuter().install(pageContext.getConfig(),data);  
258            }
259            private void doActionUninstall() throws ClassException, IOException {
260                    getVideoExecuter().uninstall(pageContext.getConfig());  
261            }
262    
263            public Struct doActionInfo() throws PageException, IOException {
264                    return doActionInfo(source);
265                    
266            }
267            
268            private Struct doActionInfo(VideoInput source) throws PageException, IOException {
269    
270                    // precheck settings
271                    checkFile(source,"source", true, true, false);
272                    
273                    //VideoConfig vc = getConfig();
274                    debug(source);
275                    Struct info = toStruct(getVideoExecuter().info(pageContext.getConfig(), source));
276                    pageContext.setVariable(result,info);
277                    return info;
278                    
279            }
280    
281            private VideoExecuter getVideoExecuter() throws ClassException {
282                    return VideoUtilImpl.createVideoExecuter(pageContext.getConfig());
283            }
284    
285    
286    
287            private VideoInfo getInfo(VideoInput source) throws PageException, IOException {
288    
289                    // precheck settings
290                    checkFile(source,"source", true, true, false);
291                    
292                    // execute
293                    return getVideoExecuter().info(pageContext.getConfig(),source);
294                    //print.out(raw);
295    
296                    // write cfvideo                
297                    //return new Info(raw,true,startTime,maxTime);  
298            }
299    
300    
301            private void doActionCutImage() throws PageException, IOException {
302    
303                    // precheck settings
304                    checkFile(source,"source", true, true, false);
305                    if(!checkDestination(source,destination,name,nameconflict)) return;
306                    
307                    // input
308                    if(profile==null)profile=new VideoProfileImpl();
309                    
310                    // settings
311                    settings(destination,profile);
312                    
313                    destination.setMaxFrames(1);
314                    destination.setFormat("image2");
315                    // execute
316                    Struct info=toStruct(getVideoExecuter().convert(pageContext.getConfig(),new VideoInput[]{source},destination,profile));
317                    
318                    // write cfvideo
319                    debug(source);
320                    pageContext.setVariable(result,info);
321                    
322                    //setResult(raw,false);
323                    
324            }
325    
326    
327    
328            private void doActionConcat() throws PageException, IOException {
329                    // precheck settings
330                    checkFile(source1,"source1", true, true, false);
331                    checkFile(source2,"source2", true, true, false);
332                    if(!checkDestination(source1,destination,name,nameconflict)) return;
333    
334                    Pair s1 =toMpeg(source1);
335                    Pair s2 =toMpeg(source2);
336                    source = new VideoInputImpl(pageContext.getConfig().getTempDirectory().getRealResource("tmp-"+new Random().nextInt()+".mpg"));
337                    try {
338                            merge(s1.res,s2.res,source.getResource());
339                            Struct sct = doActionConvert();
340                            sct.setEL(SOURCE1, s1.sct);
341                            sct.setEL(SOURCE2, s2.sct);
342                            sct.removeEL(SOURCE);
343                            
344                    }
345                    finally {
346                            source.getResource().delete();
347                            if(!s1.res.equals(source1.getResource()))s1.res.delete();
348                            if(!s2.res.equals(source2.getResource()))s2.res.delete();
349                    }
350                    
351            }
352    
353    
354    
355            private void merge(Resource in1, Resource in2, Resource out) throws IOException {
356                    InputStream is1=null;
357                    InputStream is2=null;
358                    OutputStream os=null;
359                    try {
360                            is1=in1.getInputStream();
361                            is2=in2.getInputStream();
362                            os=out.getOutputStream();
363                    }
364                    catch(IOException ioe) {
365                            Util.closeEL(is1);
366                            Util.closeEL(is2);
367                            Util.closeEL(os);
368                            throw ioe;
369                    }
370    
371                    try {
372                            copy(is1, os);
373                            copy(is2, os);
374                    } 
375                    finally {
376                            Util.closeEL(is1);
377                            Util.closeEL(is2);
378                            Util.closeEL(os);
379                    }
380            }
381    
382    
383            public final static void copy(InputStream in, OutputStream out) throws IOException {
384            byte[] buffer = new byte[0xffff];
385            int len;
386            while((len = in.read(buffer)) !=-1)
387              out.write(buffer, 0, len);
388        }
389        
390    
391    
392    
393            private Pair toMpeg(VideoInput vi) throws PageException, IOException {
394                    VideoInfo info = getInfo(vi);
395                    //Struct sct = _doActionInfo(vi);
396                    
397                    
398                    if("mpeg1video".equals(info.getVideoCodec()))
399                            return new Pair(vi.getResource(),toStruct(info));
400                    
401                    VideoOutput tmp = new VideoOutputImpl(pageContext.getConfig().getTempDirectory().getRealResource("tmp-"+new Random().nextInt()+".mpg"));
402                    try {
403                            doActionConvert(vi,tmp,null,null,NAMECONFLICT_ERROR);
404                            return new Pair(tmp.getResource(),toStruct(info));
405                    }
406                    catch(PageException pe) {
407                            tmp.getResource().delete();
408                            throw pe;
409                    }
410                    catch(IOException ioe) {
411                            tmp.getResource().delete();
412                            throw ioe;
413                    }
414                    
415            }
416    
417    
418    
419            private Struct doActionConvert() throws PageException, IOException {
420                    return doActionConvert(source,destination,profile,name,nameconflict);
421            }
422            private Struct doActionConvert(VideoInput source,VideoOutput destination, VideoProfile quality,String name, int nameconflict) throws PageException, IOException {
423                                    
424                    // precheck settings
425                    checkFile(source,"source", true, true, false);
426                    if(!checkDestination(source,destination,name,nameconflict)) return new StructImpl();
427                    
428                    // input
429                    if(quality==null)quality=new VideoProfileImpl();
430                    
431                    // settings
432                    settings(destination,quality);
433                    
434                    // execute
435                    Struct info = toStruct(getVideoExecuter().convert(pageContext.getConfig(),new VideoInput[]{source},destination,quality));
436                    
437                    // write cfvideo
438                    debug(source);
439                    
440                    pageContext.setVariable(result,info);
441                    return info;
442                    //return setResult(raw,false);
443            }    
444            
445    
446            private void debug(VideoInput vi) throws PageException {
447                    if(!StringUtil.isEmpty(debug))pageContext.setVariable(debug, vi.getCommandAsString());
448            }
449    
450            private void settings(VideoOutput vo,VideoProfile vq) throws PageException, IOException {
451                    defineSize(vq,new VideoInput[]{source});
452                    if(audioBitrate>0)vq.setAudioBitrate(audioBitrate);
453                    if(aspectRatio>0)vq.setAspectRatio(aspectRatio);
454                    if(framerate>0)vq.setFramerate(framerate);
455                    if(videoBitrate>0)vq.setVideoBitrate(videoBitrate);
456                    if(videoBitrateMin>0)vq.setVideoBitrateMin(videoBitrateMin);
457                    if(videoBitrateMax>0)vq.setVideoBitrateMax(videoBitrateMax);
458                    if(videoBitrateTolerance>0)vq.setVideoBitrateTolerance(videoBitrateTolerance);
459                    if(audiosamplerate>0)vq.setAudioSamplerate(audiosamplerate);
460                    if(buffersize>0)vq.setBufferSize(buffersize);
461                    if(execution==EXECUTION_QUALITY)vq.setPass(2);
462    
463                    if(!StringUtil.isEmpty(title))vo.setTitle(title);
464                    if(!StringUtil.isEmpty(author))vo.setAuthor(author);
465                    if(!StringUtil.isEmpty(comment))vo.setComment(comment);
466                    if(!StringUtil.isEmpty(copyright))vo.setCopyright(copyright);
467                    if(!StringUtil.isEmpty(videoCodec))vq.setVideoCodec(videoCodec);
468                    if(!StringUtil.isEmpty(audioCodec))vq.setAudioCodec(audioCodec);
469                    
470                    
471                    
472                    if(framerate==0 && (startFrame>0 || maxTime>0)) {
473                            framerate=(int)getInfo(source).getFramerate();
474                    }
475                    
476                    // start
477                    if(startFrame>0) {
478                            if(framerate>0) startTime=(startFrame/framerate);
479                    }
480                    if(startTime>0)destination.setOffset(startTime);
481                    
482                    // max
483                    if(maxTime>0) {
484                            if(framerate>0) maxFrame=(long)(maxTime*framerate);
485                    }
486                    if(maxTime>0)vo.setMaxFrames(maxFrame);
487                    
488                    // maxtime (only for cfvideo struct)
489                    if(maxFrame>0 && maxTime==0) {
490                            if(framerate!=-1) maxTime=maxFrame/framerate;
491                    }
492                    destination.setFrameRate(framerate);
493                    
494            }
495    
496            private ProfileCollection getProfileCollection() throws PageException {
497                    return getProfileCollection(pageContext);
498            }
499            
500            public static ProfileCollection getProfileCollection(PageContext pc) throws PageException {
501                    if(_profileCollection==null) {
502                            try {
503                                    _profileCollection=new ProfileCollection(pc.getConfig());
504                            } 
505                            catch (Exception e) {
506                                    throw Caster.toPageException(e);
507                            }
508                    }
509                    return _profileCollection;
510            }
511    
512            private void defineSize(VideoProfile quality, VideoInput[] sources) throws PageException {
513                    if(strWidth!=null || strHeight!=null) {
514                            int[] dim = VideoUtilImpl.getInstance().calculateDimension(pageContext, sources, width, strWidth, height, strHeight);
515                            quality.setDimension(dim[0], dim[1]);
516                    }
517            }
518    
519            private void checkFile(VideoInput vi, String label, boolean exist, boolean canRead, boolean canWrite) throws PageException {
520                    if(vi==null) {
521                            throw doThrow("attribute "+label+" is required for tag video action "+strAction);
522                    }
523                    checkFile(vi.getResource(), label, exist, canRead, canWrite);
524            }
525    
526            private void checkFile(VideoOutput vo, String label, boolean exist, boolean canRead, boolean canWrite) throws PageException {
527                    if(vo==null) {
528                            throw doThrow("attribute "+label+" is required for tag video action "+strAction);
529                    }
530                    checkFile(vo.getResource(), label, exist, canRead, canWrite);
531            }
532            
533            
534            private void checkFile(Resource res, String label, boolean exist, boolean canRead, boolean canWrite) throws PageException {
535                    
536                    if(res==null) {
537                            throw doThrow("attribute "+label+" is required for tag video action "+strAction);
538                    }
539                    
540                    
541                    if(!res.exists()) {
542                            if(exist)throw doThrow(""+label+" file does not exist");
543                    }
544                    else {
545                             if(!res.isFile())
546                                    throw doThrow(label+" ["+res.toString()+"] is not a file");
547                    else if(canRead &&!res.canRead())
548                        throw doThrow("no read access to "+label+" ["+res.toString()+"]");
549                    else if(canWrite && !res.canWrite())
550                        throw doThrow("no write access to "+label+" ["+res.toString()+"]");
551                    }
552            }
553            
554            private boolean checkDestination(VideoInput vi, VideoOutput destination, String name, int nameconflict) throws PageException {
555                    checkFile(destination,"destination", false, false, false);
556                    
557                    // destination
558                    if(!Util.isEmpty(name))destination.setResource(destination.getResource().getRealResource(name));
559                    else if(destination.getResource().isDirectory()) {
560                            destination.setResource(destination.getResource().getRealResource(vi.getResource().getName()));
561                    }
562                    
563                    // escape %d
564                    String _name=destination.getResource().getName();
565                    if(_name.indexOf("%d")!=-1) {
566                            destination.setResource(destination.getResource().getParentResource().getRealResource(_name.replaceAll("%d", "%%d")));
567                    }
568                    
569                    
570                    if(destination.getResource().exists() && nameconflict!=NAMECONFLICT_OVERWRITE) {
571                            // SKIP
572                            if(nameconflict==NAMECONFLICT_SKIP) return false;
573                            // MAKEUNIQUE
574                            else if(nameconflict==NAMECONFLICT_MAKEUNIQUE) destination.setResource(makeUnique(destination.getResource()));
575                            // ERROR
576                            else doThrow("destiniation file ["+destination.toString()+"] already exist");
577                    }
578            return true;
579            }
580            
581            private Resource makeUnique(Resource res) {
582    
583                    String ext=getFileExtension(res);
584                    String name=getFileName(res);
585                    ext=(ext==null)?"":"."+ext;
586                    int count=0;
587                    while(res.exists()) {
588                            res=res.getParentResource().getRealResource(name+(++count)+ext);
589                    }
590                    return res;
591            }
592            
593            /**
594             * get file extension of a file object
595             * @param file file object
596             * @return extnesion
597             */
598            private static String getFileExtension(Resource file) {
599                    String name=file.getName();
600                    int index = name.lastIndexOf('.');
601                    if(index==-1) return null;
602                    return name.substring(index+1).trim();
603            }
604            
605            /**
606             * get file name of a file object without extension
607             * @param file file object
608             * @return name of the file 
609             */
610            private static String getFileName(Resource file) {
611                    String name=file.getName();
612                    int pos=name.lastIndexOf(".");
613                    
614                    if(pos==-1)return name;
615                    return name.substring(0,pos);
616            }
617    
618            private VideoProfile getProfile(String strProfile) throws PageException {
619                    strProfile=strProfile.trim().toLowerCase();
620                    return getProfileCollection().getProfiles().get(strProfile);
621            }
622            
623            private String getProfileKeyList() throws PageException {
624                    Iterator<String> it = getProfileCollection().getProfiles().keySet().iterator();
625                    StringBuffer sb=new StringBuffer();
626                    boolean doDel=false;
627                    while(it.hasNext()) {
628                            if(doDel)sb.append(", ");
629                            sb.append(it.next());
630                            doDel=true;
631                    }
632                    
633                    return sb.toString();
634            }
635            
636            private PageException doThrow(String message) {
637                    return doThrow(message,null);
638            }
639            
640            private PageException doThrow(String message, String detail) {
641                    if(detail==null)return new ApplicationException(message);
642                    return new ApplicationException(message,detail);
643            }
644            
645    
646    
647    
648    
649            /**
650             * @param width the width to set
651             */
652            public void setWidth(String strWidth) {
653                    this.width = Caster.toIntValue(strWidth,-1);
654                    this.strWidth = strWidth;
655            }
656    
657            /**
658             * @param height the height to set
659             */
660            public void setHeight(String strHeight) {
661                    this.height = Caster.toIntValue(strHeight,-1);
662                    this.strHeight = strHeight;
663            }
664    
665            /**
666             * @param audioBitrate the audioBitrate to set
667             * @throws PageException 
668             */
669            public void setAudiobitrate(String audioBitrate) throws PageException {
670                    this.audioBitrate = util.toBytes(audioBitrate);
671            }
672    
673            /**
674             * @param aspectRatio the aspectRatio to set
675             * @throws PageException 
676             */
677            public void setAspectratio(String strAspectRatio) throws PageException {
678                    strAspectRatio=strAspectRatio.trim().toLowerCase();
679                    if("16:9".equals(strAspectRatio)) aspectRatio=VideoProfile.ASPECT_RATIO_16_9;
680                    else if("4:3".equals(strAspectRatio)) aspectRatio=VideoProfile.ASPECT_RATIO_4_3;
681                    else throw doThrow("invalid aspect ratio definition ["+strAspectRatio+"], valid values are [16:9, 4:3]");
682            }
683    
684            /**
685             * @param framerate the framerate to set
686             */
687            public void setFramerate(double framerate) {
688                    setFps(framerate);
689            }
690            public void setFps(double framerate) {
691                    this.framerate = (int) framerate;
692            }
693    
694            /**
695             * @param videoBitrate the videoBitrate to set
696             * @throws PageException 
697             */
698            public void setVideobitrate(String videoBitrate) throws PageException {
699                    this.videoBitrate = util.toBytes(videoBitrate);
700            }
701    
702            /**
703             * @param videoBitrateMin the videoBitrateMin to set
704             * @throws PageException 
705             */
706            public void setVideobitratemin(String videoBitrateMin) throws PageException {
707                    this.videoBitrateMin = util.toBytes(videoBitrateMin);
708            }
709    
710            /**
711             * @param videoBitrateMax the videoBitrateMax to set
712             * @throws PageException 
713             */
714            public void setVideobitratemax(String videoBitrateMax) throws PageException {
715                    this.videoBitrateMax = util.toBytes(videoBitrateMax);
716            }
717    
718            /**
719             * @param videoBitrateTolerance the videoBitrateTolerance to set
720             * @throws PageException 
721             */
722            public void setVideobitratetolerance(String videoBitrateTolerance) throws PageException {
723                    this.videoBitrateTolerance = util.toBytes(videoBitrateTolerance);
724            }
725    
726            /**
727             * @param author the author to set
728             */
729            public void setAuthor(String author) {
730                    this.author = author;
731            }
732    
733            /**
734             * @param title the title to set
735             */
736            public void setTitle(String title) {
737                    this.title = title;
738            }
739    
740            /**
741             * @param comment the comment to set
742             */
743            public void setComment(String comment) {
744                    this.comment = comment;
745            }
746    
747            /**
748             * @param copyright the copyright to set
749             */
750            public void setCopyright(String copyright) {
751                    this.copyright = copyright;
752            }
753    
754            /**
755             * @param max the maxFrames to set
756             * @throws PageException 
757             */
758            public void setMax(String strMax) throws PageException {
759                    strMax=strMax.trim().toLowerCase();
760                    if(strMax.endsWith("f"))                        this.maxFrame=Caster.toLongValue(strMax.substring(0,strMax.length()-1));
761                    else if(strMax.endsWith("ms"))  this.maxTime=Caster.toDoubleValue(strMax.substring(0,strMax.length()-2))/1000F;
762                    else if(strMax.endsWith("s"))           this.maxTime=Caster.toDoubleValue(strMax.substring(0,strMax.length()-1));
763                    else setStart(strMax+" ms");
764            }
765    
766            /**
767             * @param result the result to set
768             */
769            public void setResult(String result) {
770                    this.result = result;
771            }
772    
773    
774    
775            /**
776             * @param source1 the source1 to set
777             * @throws PageException 
778             */
779            public void setSource1(String source1) throws PageException {
780                    this.source1 = new VideoInputImpl(ResourceUtil.toResourceExisting(pageContext, source1));
781            }
782    
783    
784    
785            /**
786             * @param source2 the source2 to set
787             * @throws PageException 
788             */
789            public void setSource2(String source2) throws PageException {
790                    this.source2 = new VideoInputImpl(ResourceUtil.toResourceExisting(pageContext, source2));
791            }
792    
793    
794    
795            /**
796             * @param strStart the position to set
797             * @throws PageException 
798             */
799            public void setStart(String strStart) throws PageException {
800                    strStart=strStart.trim().toLowerCase();
801                    if(strStart.endsWith("f"))                      this.startFrame=Caster.toLongValue(strStart.substring(0,strStart.length()-1));
802                    else if(strStart.endsWith("ms"))        this.startTime=Caster.toDoubleValue(strStart.substring(0,strStart.length()-2))/1000F;
803                    else if(strStart.endsWith("s"))         this.startTime=Caster.toDoubleValue(strStart.substring(0,strStart.length()-1));
804                    else setStart(strStart+" ms");
805            }
806    
807            /**
808             * @param videoCodec the videoCodec to set
809             */
810            public void setVideocodec(String videoCodec) {
811                    this.videoCodec = videoCodec;
812            }
813            public void setAudiocodec(String audioCodec) {
814                    this.audioCodec = audioCodec;
815            }
816            
817            class Pair {
818                    Resource res;
819                    Struct sct;
820                    public Pair(Resource res, Struct sct) {
821                            this.res = res;
822                            this.sct = sct;
823                    }
824            }
825    
826            /**
827             * @param audiosamplerate the audiosamplerate to set
828             * @throws PageException 
829             */
830            public void setAudiosamplerate(String sAudiosamplerate) throws PageException {
831                    this.audiosamplerate = util.toHerz(sAudiosamplerate);
832            }
833    
834            public static void checkRestriction() {
835                    
836            }
837            
838            /**
839             * @param debug the debug to set
840             */
841            public void setDebug(String debug) {
842                    this.debug = debug;
843            }
844    
845            /**
846             * @param buffersize the buffersize to set
847             */
848            public void setBuffersize(double buffersize) {
849                    this.buffersize = (long) buffersize;
850            }
851            
852    
853            public Struct toStruct(VideoInfo[] infos) {
854                    Struct sct=new StructImpl();
855                    sct.setEL(KeyConstants._source, toStruct(infos[0]));
856                    sct.setEL(KeyConstants._destination, toStruct(infos[1]));
857                    return sct;
858            }
859            
860            private Struct toStruct(VideoInfo info) {
861                    
862                    Struct sct=info.toStruct();
863                    
864                    // audio
865                    Struct audio=Caster.toStruct(sct.get(AUDIO,null),null);
866                    if(audio==null) {
867                            audio=new StructImpl();
868                            sct.setEL(AUDIO, audio);
869                    }
870                    
871                    // video
872                    Struct video=Caster.toStruct(sct.get(VIDEO,null),null);
873                    if(video==null) {
874                            video=new StructImpl();
875                            sct.setEL(VIDEO, video);
876                    }
877                    
878                    // Audio
879                    audio.setEL("channels", info.getAudioChannels());
880                    audio.setEL(KeyConstants._codec, info.getAudioCodec());
881                    if(info.getAudioBitrate()!=-1)audio.setEL("bitrate", new Double(info.getAudioBitrate()));
882                    if(info.getAudioSamplerate()!=-1)audio.setEL("samplerate", new Double(info.getAudioSamplerate()));
883                    
884                    // Video
885                    video.setEL(KeyConstants._codec, info.getVideoCodec());
886                    video.setEL(KeyConstants._format, info.getVideoFormat());
887                    if(info.getVideoBitrate()!=-1)video.setEL("bitrate", new Double(info.getVideoBitrate()));
888                    if(info.getFramerate()!=-1)video.setEL("framerate", new Double(info.getFramerate()));
889                    
890                    // Allgemein
891                    if(info.getDuration()!=-1)sct.setEL("duration", new Double(info.getDuration()));
892                    if(info.getHeight()!=-1)sct.setEL(KeyConstants._height, new Double(info.getHeight()));
893                    if(info.getWidth()!=-1)sct.setEL(KeyConstants._width, new Double(info.getWidth()));
894                    
895                    
896                    
897                    return sct;
898            }
899    }