Skip to content

Commit

Permalink
- Implemented a new logic for detecting heavy converted swf files fro…
Browse files Browse the repository at this point in the history
…m PDF, using obejct placements, text and bitmap count.

- pdf2swf conversion fallback to 'bitmap' instead of 'poly2bitmap' to garantee that file can be opened fast with flash player.
  • Loading branch information
GhaziTriki committed Dec 10, 2015
1 parent b50badc commit febc7ca
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 167 deletions.
10 changes: 8 additions & 2 deletions bigbluebutton-web/grails-app/conf/bigbluebutton.properties
Expand Up @@ -69,8 +69,14 @@ maxNumPages=200
MAX_SWF_FILE_SIZE=500000

#----------------------------------------------------
# Maximum the number of shapes inside the converted SWF, if exceeded the conversion will fallback to full BMP (default 20000)
maxSwfShapes=20000
# Maximum allowed number of place object tags in the converted SWF, if exceeded the conversion will fallback to full BMP (default 8000)
placementsThreshold=8000

# Maximum allowed number of bitmap images in the converted SWF, if exceeded the conversion will fallback to full BMP (default 8000)
imageTagThreshold=8000

# Maximum allowed number of define text tags in the converted SWF, if exceeded the conversion will fallback to full BMP (default 2500)
defineTextThreshold=2500

#----------------------------------------------------
# Additional conversion of the presentation slides to SVG
Expand Down
9 changes: 3 additions & 6 deletions bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml
Expand Up @@ -62,12 +62,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<bean id="pdf2SwfPageConverter" class="org.bigbluebutton.presentation.imp.Pdf2SwfPageConverter">
<property name="swfToolsDir" value="${swfToolsDir}"/>
<property name="fontsDir" value="${fontsDir}"/>
<property name="swfAnalyser" ref="swfAnalyser"/>
</bean>

<bean id="swfAnalyser" class="org.bigbluebutton.presentation.imp.SwfAnalyser">
<property name="swfToolsDir" value="${swfToolsDir}"/>
<property name="maxSwfShapes" value="${maxSwfShapes}"/>
<property name="placementsThreshold" value="${placementsThreshold}"/>
<property name="defineTextThreshold" value="${defineTextThreshold}"/>
<property name="imageTagThreshold" value="${imageTagThreshold}"/>
</bean>

<bean id="imageConvSvc" class="org.bigbluebutton.presentation.imp.PdfPageToImageConversionService">
Expand Down
Expand Up @@ -18,17 +18,92 @@
*/
package org.bigbluebutton.presentation.handlers;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
*
* The default command output the anlayse looks like the following: </br> 20
* DEBUG Using</br> 60 VERBOSE Updating font</br> 80 VERBOSE Drawing
*
*/
public class Pdf2SwfPageConverterHandler extends AbstractPageConverterHandler {

private static Logger log = LoggerFactory
.getLogger(Pdf2SwfPageConverterHandler.class);

private static String PLACEMENT_OUTPUT = "DEBUG Using";
private static String TEXT_TAG_OUTPUT = "VERBOSE Updating";
private static String IMAGE_TAG_OUTPUT = "VERBOSE Drawing";
private static String PLACEMENT_PATTERN = "\\d+\\s" + PLACEMENT_OUTPUT;
private static String TEXT_TAG_PATTERN = "\\d+\\s" + TEXT_TAG_OUTPUT;
private static String IMAGE_TAG_PATTERN = "\\d+\\s" + IMAGE_TAG_OUTPUT;

@Override
public Boolean isConversionSuccessfull() {
return true;
return !exitedWithError();
}

/**
*
* @return The number of PlaceObject2 tags in the generated SWF
*/
public long numberOfPlacements() {
if (stdoutContains(PLACEMENT_OUTPUT)) {
try {
String out = stdoutBuilder.toString();
Pattern r = Pattern.compile(PLACEMENT_PATTERN);
Matcher m = r.matcher(out);
m.find();
return Integer
.parseInt(m.group(0).replace(PLACEMENT_OUTPUT, "").trim());
} catch (Exception e) {
return 0;
}
}
return 0;
}

/**
*
* @return The number of text tags in the generated SWF.
*/
public long numberOfTextTags() {
if (stdoutContains(TEXT_TAG_OUTPUT)) {
try {
String out = stdoutBuilder.toString();
Pattern r = Pattern.compile(TEXT_TAG_PATTERN);
Matcher m = r.matcher(out);
m.find();
return Integer.parseInt(m.group(0).replace(TEXT_TAG_OUTPUT, "").trim());
} catch (Exception e) {
return 0;
}
}
return 0;
}

/**
*
* @return The number of image tags in the generated SWF.
*/
public long numberOfImageTags() {
if (stdoutContains(IMAGE_TAG_OUTPUT)) {
try {
String out = stdoutBuilder.toString();
Pattern r = Pattern.compile(IMAGE_TAG_PATTERN);
Matcher m = r.matcher(out);
m.find();
return Integer
.parseInt(m.group(0).replace(IMAGE_TAG_OUTPUT, "").trim());
} catch (Exception e) {
return 0;
}
}
return 0;
}

}

This file was deleted.

Expand Up @@ -37,16 +37,36 @@ public class Pdf2SwfPageConverter implements PageConverter {

private String SWFTOOLS_DIR;
private String fontsDir;
private SwfAnalyser swfAnalyser;
private long placementsThreshold;
private long defineTextThreshold;
private long imageTagThreshold;

public boolean convert(File presentation, File output, int page) {
String source = presentation.getAbsolutePath();
String dest = output.getAbsolutePath();
String AVM2SWF = "-T9";

NuProcessBuilder pb = new NuProcessBuilder(Arrays.asList(SWFTOOLS_DIR
+ File.separator + "pdf2swf", AVM2SWF, "-F", fontsDir, "-p",
String.valueOf(page), source, "-o", dest));
// Building the command line wrapped in shell to be able to use shell
// feature like the pipe
NuProcessBuilder pb = new NuProcessBuilder(
Arrays.asList(
"/bin/sh",
"-c",
SWFTOOLS_DIR
+ File.separator
+ "pdf2swf"
+ " -vv "
+ AVM2SWF
+ " -F "
+ fontsDir
+ " -p "
+ String.valueOf(page)
+ " "
+ source
+ " -o "
+ dest
+ " | egrep 'shape id|Updating font|Drawing' | sed 's/ / /g' | cut -d' ' -f 1-3 | sort | uniq -cw 15"));

Pdf2SwfPageConverterHandler pHandler = new Pdf2SwfPageConverterHandler();
pb.setProcessListener(pHandler);
NuProcess process = pb.start();
Expand All @@ -55,16 +75,20 @@ public boolean convert(File presentation, File output, int page) {
} catch (InterruptedException e) {
log.error(e.getMessage());
}
boolean done = pHandler.isConversionSuccessfull();
boolean swfIntegritySuccess = swfAnalyser.analyse(output);

File destFile = new File(dest);
if (done && swfIntegritySuccess && destFile.exists()) {
if (pHandler.isConversionSuccessfull() && destFile.exists()
&& pHandler.numberOfPlacements() < placementsThreshold
&& pHandler.numberOfTextTags() < defineTextThreshold
&& pHandler.numberOfImageTags() < imageTagThreshold) {
return true;
} else {
log.debug("Falling back to 'poly2bitmap' option for pdf2swf");
log.debug(
"Previous conversion generated {} PlaceObject tags, {} DefineText tags and {} Images. Falling back to 'bitmap' option for pdf2swf.",
pHandler.numberOfPlacements(), pHandler.numberOfTextTags(),
pHandler.numberOfImageTags());
NuProcessBuilder pbBmp = new NuProcessBuilder(Arrays.asList(SWFTOOLS_DIR
+ File.separator + "pdf2swf", AVM2SWF, "-s", "poly2bitmap", "-F",
+ File.separator + "pdf2swf", AVM2SWF, "-s", "bitmap", "-F",
fontsDir, "-p", String.valueOf(page), source, "-o", dest));
Pdf2SwfPageConverterHandler pBmpHandler = new Pdf2SwfPageConverterHandler();
pbBmp.setProcessListener(pBmpHandler);
Expand All @@ -85,10 +109,6 @@ public boolean convert(File presentation, File output, int page) {
}
}

public void setSwfAnalyser(SwfAnalyser swfAnalyser) {
this.swfAnalyser = swfAnalyser;
}

public void setSwfToolsDir(String dir) {
SWFTOOLS_DIR = dir;
}
Expand All @@ -97,4 +117,16 @@ public void setFontsDir(String dir) {
fontsDir = dir;
}

public void setPlacementsThreshold(long threshold) {
placementsThreshold = threshold;
}

public void setDefineTextThreshold(long threshold) {
defineTextThreshold = threshold;
}

public void setImageTagThreshold(long threshold) {
imageTagThreshold = threshold;
}

}

This file was deleted.

0 comments on commit febc7ca

Please sign in to comment.