Author: seba.wagner
Date: Mon Dec 29 08:43:01 2008
New Revision: 1743
Modified:
trunk/webapp/filetest.keystore
trunk/webapp/src/app/org/openmeetings/app/data/record/WhiteboardConvertionJobManager.java
trunk/webapp/src/app/org/openmeetings/app/documents/GenerateSWF.java
Log:
Fixes:
Generate Whiteboard-SWF with FFmpeg - Issue 550
Modified: trunk/webapp/filetest.keystore
==============================================================================
Binary files. No diff available.
Modified:
trunk/webapp/src/app/org/openmeetings/app/data/record/WhiteboardConvertionJobManager.java
==============================================================================
---
trunk/webapp/src/app/org/openmeetings/app/data/record/WhiteboardConvertionJobManager.java
(original)
+++
trunk/webapp/src/app/org/openmeetings/app/data/record/WhiteboardConvertionJobManager.java
Mon Dec 29 08:43:01 2008
@@ -15,6 +15,7 @@
import org.apache.batik.svggen.SVGGraphics2D;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.commons.transaction.util.FileHelper;
import org.openmeetings.app.data.record.dao.RecordingConversionJobDaoImpl;
import org.openmeetings.app.data.record.dao.RecordingDaoImpl;
import org.openmeetings.app.data.record.dao.RoomRecordingDaoImpl;
@@ -56,6 +57,9 @@
//quartz scheduler run
private static int svgBatchProcessByQuery = 100;
+ private static int defaultWidth = 660;
+ private static int defaultHeight = 620;
+
private static boolean isRunning = false;
//in JUnit tests you have to change that to true
@@ -105,14 +109,16 @@
//Do SVG Conversion for next 100 SVG Images,
that should fill one
Folder
for (int i=0;i<svgBatchProcessByQuery;i++) {
- this.processJobs();
+ if (!this.processJobs()) {
+ break;
+ }
}
//Do SVG to PNG Batch Conversion
this.processConvertionJobs();
- //Do PNG to SWF Conversion
- this.processConvertionSWFJobs();
+ //Do Batch FFMPEG Conversion
+ this.processFFmpegJob();
isRunning = false;
} else {
@@ -125,7 +131,7 @@
}
}
- public synchronized void processJobs() {
+ public synchronized boolean processJobs() {
try {
List<RecordingConversionJob> listOfConversionJobs =
RecordingConversionJobDaoImpl.getInstance().getRecordingConversionJobs();
@@ -222,6 +228,7 @@
this.generateFileAsSVG(whiteBoardObjects, roomRecordingInXMLToSave,
recordingConversionJob);
+ return true;
} else {
log.debug("THIS FILE IS
PROCESSED
UPDATE: "+recordingConversionJob.getRecordingConversionJobId());
@@ -233,6 +240,7 @@
recordingConversionJob.setBatchProcessCounter(0L);
RecordingConversionJobDaoImpl.getInstance().updateRecordingConversionJobs(recordingConversionJob);
+ return false;
}
}
@@ -240,8 +248,9 @@
} catch (Exception err) {
log.error("[processJobs]",err);
+ return false;
}
-
+ return false;
}
public synchronized void processConvertionJobs() {
@@ -273,7 +282,7 @@
GenerateImage.getInstance().convertImageByTypeAndSizeAndDepth(
outputFileNames.get("input"),
outputFileNames.get("output"),
- 660, 580, depth);
+ defaultWidth, 580,
depth);
//Add Count For next Round
RecordingConversionJob
recordingConversionJobUpdate =
RecordingConversionJobDaoImpl.getInstance().
@@ -301,11 +310,13 @@
}
}
- public synchronized void processConvertionSWFJobs() {
+
+ private synchronized void processFFmpegJob() {
try {
List<RecordingConversionJob> listOfSWFConversionJobs =
RecordingConversionJobDaoImpl.getInstance().getRecordingConversionSWFConversionJobs();
+
log.debug("processSWFJobs SIZE:
"+listOfSWFConversionJobs.size());
for (RecordingConversionJob recordingConversionJob :
listOfSWFConversionJobs) {
@@ -326,9 +337,6 @@
//three times to simulate a FPS
of 30 while we only generate
//an image every 200
milliseconds (would be fps of 10)
images.add(folderName+k+".png");
- images.add(folderName+k+".png");
- images.add(folderName+k+".png");
-
}
}
@@ -345,9 +353,6 @@
//three times to simulate a FPS of 30
while we only generate
//an image every 200 milliseconds
(would be fps of 10)
images.add(folderName+k+".png");
- images.add(folderName+k+".png");
- images.add(folderName+k+".png");
-
}
log.debug("images: "+images);
@@ -356,50 +361,52 @@
String output =
this.getSWFFileForResult(recordingConversionJob.getRecordingConversionJobId());
String outputFolder =
this.getSWFFolderForResult(recordingConversionJob.getRecordingConversionJobId());
+ String pngOutputFolder = outputFolder +
File.separatorChar + "PNG";
+ File pngFolder = new File(pngOutputFolder);
+ if (!pngFolder.exists()) {
+ pngFolder.mkdir();
+ }
- //Generate that SWF only by 1000 Files as
png2swf.c has a
MAX_INPUT_FILE of 1024
-
- //This workaround is just to workaround the
1024 File LIMIT of
SWFTools!!!
-
- List<String> outputfiles = new
LinkedList<String>();
+ //Move Files to result folder and reflect that
we need 30 FPS instead
of 5 FPS in the initial Break Down
+ int i = 0;
+ for (Iterator<String>
iter=images.iterator();iter.hasNext();) {
+ String fileToMove = iter.next();
+ log.debug("fileToMove: "+fileToMove);
+ File fileTo = new File(fileToMove);
+ log.debug("fileTo: "+fileTo);
+ if (fileTo.exists()) {
+ log.debug("InputFile Does
exist");
+ }
+ FileHelper.copy(
+ new File(fileToMove),
+ new File(pngOutputFolder +
File.separatorChar + "" + i + ".png"));
+ i++;
+ FileHelper.copy(
+ new File(fileToMove),
+ new
File(pngOutputFolder + File.separatorChar + "" + i + ".png"));
+ i++;
+ FileHelper.copy(
+ new File(fileToMove),
+ new
File(pngOutputFolder + File.separatorChar + "" + i + ".png"));
+ i++;
+ FileHelper.copy(
+ new File(fileToMove),
+ new
File(pngOutputFolder + File.separatorChar + "" + i + ".png"));
+ i++;
+ FileHelper.copy(
+ new File(fileToMove),
+ new
File(pngOutputFolder + File.separatorChar + "" + i + ".png"));
+ i++;
+ FileHelper.copy(
+ new File(fileToMove),
+ new
File(pngOutputFolder + File.separatorChar + "" + i + ".png"));
+ i++;
+ }
- int maxnumber =
Double.valueOf(Math.floor(images.size() /
1000)).intValue();
+ String pngOutputFolderWildCard =
pngOutputFolder + File.separatorChar
+ "%d.png";
- log.debug("maxnumber: "+maxnumber);
+
GenerateSWF.getInstance().generateSWFByFFMpeg(pngOutputFolderWildCard,
output, 30,defaultWidth,defaultHeight);
- if (maxnumber > 0) {
- for (int i=0;i<=maxnumber;i++) {
-
- log.debug("Generate SWF for
Items: "+i+" TO : "+(i*1000));
- String fileName = outputFolder
+ File.separatorChar
+ "whiteboard"+i+".swf";
- outputfiles.add(fileName);
-
- List<String> imageForConvert =
new LinkedList<String>();
- for (int k=0;k<1000;k++) {
- int index = k+(i*1000);
- log.debug("index Number
"+index+" size: "+images.size());
- if (index <
images.size()) {
-
imageForConvert.add(images.get(index));
- } else {
- break;
- }
- }
-
-
GenerateSWF.getInstance().generateSWFByImages(imageForConvert,
fileName, 30);
- }
-
- //Combine Resulting SWFs to one SWF
-
- //FIXME: IT SEEMS LIKE SWFCOMBINE DOES
PRODUCE INVALID Files!!
-
GenerateSWF.getInstance().generateSWFByCombine(outputfiles, output,
30);
-
- } else {
-
- //Directly write to SWF
-
GenerateSWF.getInstance().generateSWFByImages(images, output, 30);
-
-
- }
RecordingConversionJob
recordingConversionJobUpdate =
RecordingConversionJobDaoImpl.getInstance().
getRecordingConversionJobsByRecordingConversionJobsId(recordingConversionJob.getRecordingConversionJobId());
@@ -409,9 +416,9 @@
}
} catch (Exception err) {
- log.error("[processConvertionSWFJobs]",err);
+ log.error("[processFFmpegJob]",err);
}
- }
+ }
private void generateFileAsSVG(Map whiteBoardObjects, String
roomRecordingInXML, RecordingConversionJob recordingConversionJob) throws
Exception {
@@ -430,8 +437,8 @@
// Set the width and height attributes on the root 'svg' element.
- svgRoot.setAttributeNS(null, "width", ""+660);
- svgRoot.setAttributeNS(null, "height", ""+620);
+ svgRoot.setAttributeNS(null, "width", ""+defaultWidth);
+ svgRoot.setAttributeNS(null, "height", ""+defaultHeight);
// Create an instance of the SVG Generator.
@@ -483,7 +490,7 @@
recordingConversionJobToStore.setCurrentWhiteBoardAsXml(roomRecordingInXML);
recordingConversionJobToStore.setImageNumber(recordingConversionJob.getImageNumber()+1);
- log.debug("updateRecordingConversionJobs: generateFileAsSVG");
+ log.debug("updateRecordingConversionJobs:
generateFileAsSVG: "+recordingConversionJobToStore.getEnded());
RecordingConversionJobDaoImpl.getInstance().updateRecordingConversionJobs(recordingConversionJobToStore);
}
Modified:
trunk/webapp/src/app/org/openmeetings/app/documents/GenerateSWF.java
==============================================================================
--- trunk/webapp/src/app/org/openmeetings/app/documents/GenerateSWF.java
(original)
+++ trunk/webapp/src/app/org/openmeetings/app/documents/GenerateSWF.java
Mon Dec 29 08:43:01 2008
@@ -299,5 +299,91 @@
return returnMap;
}
}
+
+
+ public HashMap<String,Object> generateSWFByFFMpeg(String inputWildCard,
String outputswf, int fps, int width, int height) {
+ HashMap<String,Object> returnMap = new HashMap<String,Object>();
+ returnMap.put("process", "generateSWFByFFMpeg");
+ try {
+
+ //Init variables
+ String[] cmd;
+ String executable_fileName = "";
+ String pathToSWFTools =
Configurationmanagement.getInstance().getConfKey(3,"swftools_path").getConf_value();
+ //If SWFTools Path is not blank a File.seperator at the
end of the path
is needed
+ if(!pathToSWFTools.equals("")
&& !pathToSWFTools.endsWith(File.separator)){
+ pathToSWFTools = pathToSWFTools +
File.separator;
+ }
+
+
+ //If no Windows Platform
+ if
(System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") ==
-1) {
+ String runtimeFile = "swfconverter.sh";
+ executable_fileName =
Application.batchFileFir+"FFMPEGSWF_"
+ +
CalendarPatterns.getTimeForStreamId(new Date()) +"_"+ runtimeFile;
+
+ cmd = new String[1];
+ cmd[0] = executable_fileName;
+ } else {
+ String runtimeFile = "swfconverter.bat";
+ executable_fileName =
Application.batchFileFir+"FFMPEGSWF_"
+ +
CalendarPatterns.getTimeForStreamId(new Date()) +"_"+ runtimeFile;
+
+ cmd = new String[4];
+ cmd[0] = "cmd.exe";
+ cmd[1] = "/C";
+ cmd[2] = "start";
+ cmd[3] = executable_fileName;
+ }
+ log.debug("executable_fileName: "+executable_fileName);
+
+ //Create the Content of the Converter Script (.bat or
.sh File)
+ //FIXME: pathToSWFTools + MUST BE PATH_TO_FFMPEG!!
+ String fileContent = "ffmpeg"
+ + " -r " + fps
+ + " -i " + "\"" + inputWildCard + "\""
+ + " -s " + width + "x" + height
+ + " -b 750k -ar 44100"
+ + " -y "+outputswf;
+
+ fileContent += Application.lineSeperator + "exit";
+
+ //execute the Script
+ FileOutputStream fos = new
FileOutputStream(executable_fileName);
+ fos.write(fileContent.getBytes());
+ fos.close();
+
+ //make new shell script executable
+ //in JAVA6 this can be done directly through the api
+ if
(System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") ==
-1) {
+
MakeExectuable.getInstance().setExecutable(executable_fileName);
+ }
+
+ Runtime rt = Runtime.getRuntime();
+
+ for (int i=0;i<cmd.length;i++){
+ log.debug("cmd: "+cmd[i]);
+ }
+
+ returnMap.put("command", cmd.toString());
+ Process proc = rt.exec(cmd);
+ InputStream stderr = proc.getErrorStream();
+ InputStreamReader isr = new InputStreamReader(stderr);
+ BufferedReader br = new BufferedReader(isr);
+ String line = null;
+ String error = "";
+ while ((line = br.readLine()) != null)
+ error += line;
+ returnMap.put("error", error);
+ int exitVal = proc.waitFor();
+ returnMap.put("exitValue", exitVal);
+ return returnMap;
+ } catch (Throwable t) {
+ t.printStackTrace();
+ returnMap.put("error", t.getMessage());
+ returnMap.put("exitValue", -1);
+ return returnMap;
+ }
+ }
}
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"OpenMeetings developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/openmeetings-dev?hl=en
-~----------~----~----~----~------~----~------~--~---