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