package ca.carleton.gcrc.olkit.multimedia.converter.impl;
import java.io.File;
import org.apache.log4j.Logger;
import ca.carleton.gcrc.olkit.multimedia.converter.MultimediaConversionProgress;
import ca.carleton.gcrc.olkit.multimedia.converter.MultimediaConversionRequest;
import ca.carleton.gcrc.olkit.multimedia.converter.MultimediaConverter;
import ca.carleton.gcrc.olkit.multimedia.ffmpeg.FFmpeg;
import ca.carleton.gcrc.olkit.multimedia.ffmpeg.VideoInfo;
import ca.carleton.gcrc.olkit.multimedia.imageMagick.ImageInfo;
import ca.carleton.gcrc.olkit.multimedia.imageMagick.ImageMagick;
import ca.carleton.gcrc.olkit.multimedia.imageMagick.ImageMagickInfo;
import ca.carleton.gcrc.olkit.multimedia.imageMagick.ImageMagickProcessor;
public class MultimediaConverterImpl implements MultimediaConverter {
static final public int IMAGE_MAX_WIDTH = 500;
static final public int IMAGE_MAX_HEIGHT = 500;
static final public int IMAGE_THUMB_HEIGHT = 60;
static final public int IMAGE_THUMB_WIDTH = 60;
final protected Logger logger = Logger.getLogger(this.getClass());
@Override
public void convertVideo(MultimediaConversionRequest request) throws Exception {
request.setConversionPerformed(false);
request.setThumbnailCreated(false);
File inFile = request.getInFile();
if( null == inFile ) {
throw new Exception("Must provide a file for video conversion");
}
MultimediaConversionProgress progress = request.getProgress();
if( null == progress ) {
progress = MultimediaConversionProgressNull.getSingleton();
}
// Get information about video
VideoInfo videoInfo = null;
{
FFmpeg ffmpeg = new FFmpeg();
videoInfo = ffmpeg.getVideoInfo( inFile );
}
// Check if conversion is required
boolean conversionRequired = false;
if( null == videoInfo.bitRate ) {
conversionRequired = true;
} else if( videoInfo.bitRate.intValue() > 250000 ) {
conversionRequired = true;
}
if( false == "h264".equals( videoInfo.videoCodec ) ) {
conversionRequired = true;
}
if( false == "mpeg4aac".equals( videoInfo.audioCodec ) ) {
conversionRequired = true;
}
// Report length and dimensions
request.setInDurationInSec( videoInfo.durationInSec );
request.setInHeight(videoInfo.height);
request.setInWidth(videoInfo.width);
if( false == conversionRequired ) {
// Conversion not required, converted file is the uploaded file
request.setOutFile(inFile);
progress.updateProgress(100);
} else {
File outFile = request.getOutFile();
if( null == outFile ) {
File parentDir = inFile.getParentFile();
outFile = File.createTempFile("conv", ".mp4", parentDir);
}
FFmpeg ffmpeg = new FFmpeg(progress);
ffmpeg.convertVideo(videoInfo, outFile);
request.setOutFile(outFile);
request.setConversionPerformed(true);
VideoInfo outVideoInfo = ffmpeg.getVideoInfo( outFile );
request.setOutDurationInSec( outVideoInfo.durationInSec );
request.setOutHeight(outVideoInfo.height);
request.setOutWidth(outVideoInfo.width);
}
// Create thumbnail
if( request.isThumbnailRequested() ){
File thumbnailFile = request.getThumbnailFile();
if( null == thumbnailFile ) {
File parentDir = inFile.getParentFile();
String name = inFile.getName();
int index = name.lastIndexOf('.');
if( index > 0 ) {
name = name.substring(0, index);
}
name = name+"_thumb.png";
thumbnailFile = new File(parentDir, name);
}
FFmpeg ffmpeg = new FFmpeg();
ffmpeg.createThumbnail(videoInfo, thumbnailFile);
request.setThumbnailFile(thumbnailFile);
request.setThumbnailCreated(true);
ImageMagickInfo imInfo = ImageMagick.getInfo();
ImageMagickProcessor im = imInfo.getProcessor(progress);
ImageInfo thumbImageInfo = im.getImageInfo( thumbnailFile );
request.setThumbnailHeight( thumbImageInfo.height );
request.setThumbnailWidth( thumbImageInfo.width );
}
}
@Override
public void convertAudio(MultimediaConversionRequest request) throws Exception {
request.setConversionPerformed(false);
request.setThumbnailCreated(false);
File inFile = request.getInFile();
if( null == inFile ) {
throw new Exception("Must provide a file for audio conversion");
}
MultimediaConversionProgress progress = request.getProgress();
if( null == progress ) {
progress = MultimediaConversionProgressNull.getSingleton();
}
// Get information about audio
VideoInfo audioInfo = null;
{
FFmpeg ffmpeg = new FFmpeg();
audioInfo = ffmpeg.getVideoInfo( inFile );
}
// Check if conversion is required
boolean conversionRequired = false;
if( null == audioInfo.bitRate ) {
conversionRequired = true;
} else if( audioInfo.bitRate.intValue() > 250000 ) {
conversionRequired = true;
}
if( false == "mpeg4aac".equals( audioInfo.audioCodec ) ) {
conversionRequired = true;
}
// Report length and dimensions
request.setInDurationInSec( audioInfo.durationInSec );
if( false == conversionRequired ) {
// Conversion not required, converted file is the uploaded file
request.setOutFile(inFile);
progress.updateProgress(100);
} else {
File outFile = request.getOutFile();
if( null == outFile ) {
File parentDir = inFile.getParentFile();
outFile = File.createTempFile("conv", ".mp4", parentDir);
}
FFmpeg ffmpeg = new FFmpeg(progress);
ffmpeg.convertAudio(audioInfo, outFile);
request.setOutFile(outFile);
request.setConversionPerformed(true);
VideoInfo outAudioInfo = ffmpeg.getVideoInfo( outFile );
request.setOutDurationInSec( outAudioInfo.durationInSec );
request.setOutHeight(0);
request.setOutWidth(0);
}
}
@Override
public void convertImage(MultimediaConversionRequest request) throws Exception {
request.setConversionPerformed(false);
request.setThumbnailCreated(false);
File inFile = request.getInFile();
if( null == inFile ) {
throw new Exception("Must provide a file for image conversion");
}
MultimediaConversionProgress progress = request.getProgress();
if( null == progress ) {
progress = MultimediaConversionProgressNull.getSingleton();
}
ImageMagickInfo imInfo = ImageMagick.getInfo();
// Get information about image
ImageInfo imageInfo = null;
if( imInfo.isAvailable ){
ImageMagickProcessor imageMagick = imInfo.getProcessor();
imageInfo = imageMagick.getImageInfo( inFile );
}
// Check if conversion is required
boolean conversionRequired = false;
boolean resizeRequired = false;
if( null != imageInfo ) {
request.setInHeight( imageInfo.height );
request.setInWidth( imageInfo.width );
if( imageInfo.width > IMAGE_MAX_WIDTH ) {
resizeRequired = true;
} else if( imageInfo.height > IMAGE_MAX_HEIGHT ) {
resizeRequired = true;
}
if( false == "JPEG".equals( imageInfo.format ) ) {
conversionRequired = true;
}
}
if( false == conversionRequired && false == resizeRequired ) {
// Conversion not required, converted file is the uploaded file
// Same applies if conversion is impossible because ImageMagick
// is not present.
request.setOutFile(inFile);
progress.updateProgress(100);
} else {
File outFile = request.getOutFile();
if( null == outFile ) {
File parentDir = inFile.getParentFile();
outFile = File.createTempFile("conv", ".jpg", parentDir);
}
ImageMagickProcessor im = imInfo.getProcessor(progress);
if( resizeRequired ) {
im.resizeImage(imageInfo, outFile, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT);
} else {
im.convertImage(imageInfo, outFile);
}
request.setOutFile(outFile);
request.setConversionPerformed(true);
ImageInfo outImageInfo = im.getImageInfo( outFile );
request.setOutHeight( outImageInfo.height );
request.setOutWidth( outImageInfo.width );
}
// Create thumbnail
if( null != imageInfo && request.isThumbnailRequested() ){
File thumbnailFile = request.getThumbnailFile();
if( null == thumbnailFile ) {
File parentDir = inFile.getParentFile();
String name = inFile.getName();
int index = name.lastIndexOf('.');
if( index > 0 ) {
name = name.substring(0, index);
}
name = name+"_thumb.png";
thumbnailFile = new File(parentDir, name);
}
ImageMagickProcessor im = imInfo.getProcessor(progress);
im.resizeImage(imageInfo, thumbnailFile, IMAGE_THUMB_WIDTH, IMAGE_THUMB_HEIGHT);
request.setThumbnailFile(thumbnailFile);
request.setThumbnailCreated(true);
ImageInfo thumbImageInfo = im.getImageInfo( thumbnailFile );
request.setThumbnailHeight( thumbImageInfo.height );
request.setThumbnailWidth( thumbImageInfo.width );
}
}
}