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