AbstractFFMpegProcess.java 9.41 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.dam.api.Asset
 *  com.day.cq.dam.api.Rendition
 *  com.day.cq.dam.commons.process.AbstractAssetWorkflowProcess
 *  com.day.cq.workflow.WorkflowException
 *  com.day.cq.workflow.WorkflowSession
 *  com.day.cq.workflow.exec.WorkItem
 *  com.day.cq.workflow.exec.WorkflowData
 *  com.day.cq.workflow.metadata.MetaDataMap
 *  javax.jcr.Node
 *  javax.jcr.Property
 *  javax.jcr.RepositoryException
 *  javax.jcr.Session
 *  org.apache.commons.io.FileUtils
 *  org.apache.commons.io.IOUtils
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.ReferencePolicy
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.commons.mime.MimeTypeService
 *  org.osgi.framework.BundleContext
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.dam.video;

import com.day.cq.dam.api.Asset;
import com.day.cq.dam.api.Rendition;
import com.day.cq.dam.commons.process.AbstractAssetWorkflowProcess;
import com.day.cq.dam.handler.ffmpeg.ExecutableLocator;
import com.day.cq.dam.handler.ffmpeg.FFMpegWrapper;
import com.day.cq.dam.handler.ffmpeg.FfmpegNotFoundException;
import com.day.cq.workflow.WorkflowException;
import com.day.cq.workflow.WorkflowSession;
import com.day.cq.workflow.exec.WorkItem;
import com.day.cq.workflow.exec.WorkflowData;
import com.day.cq.workflow.metadata.MetaDataMap;
import java.awt.Dimension;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Dictionary;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.mime.MimeTypeService;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(componentAbstract=1, metatype=1)
public abstract class AbstractFFMpegProcess
extends AbstractAssetWorkflowProcess {
    protected final Logger log;
    @Property(value={"./logs/ffmpeg"})
    public static final String PROP_WORKING_DIR = "ffmpeg.workingdir";
    @Reference(policy=ReferencePolicy.STATIC)
    protected MimeTypeService mimeTypeService;
    @Reference(policy=ReferencePolicy.STATIC)
    protected ExecutableLocator locator;
    private File workingDir;

    public AbstractFFMpegProcess() {
        this.log = LoggerFactory.getLogger(this.getClass());
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    public void execute(WorkItem workItem, WorkflowSession wfSession, MetaDataMap metaData) throws WorkflowException {
        block25 : {
            Asset asset = this.getAssetFromPayload(workItem, wfSession.getSession());
            if (asset == null) {
                String wfPayload = workItem.getWorkflowData().getPayload().toString();
                String message = "execute: cannot process video, asset [{" + wfPayload + "}] in payload doesn't exist for workflow [{" + workItem.getId() + "}].";
                throw new WorkflowException(message);
            }
            String assetMimeType = asset.getMimeType();
            if (!(assetMimeType != null && assetMimeType.startsWith("video/") || asset.getName().endsWith(".mov") && asset.getName().endsWith(".m4v") && asset.getName().endsWith(".avi") && asset.getName().endsWith(".flv"))) {
                this.log.info("execute: asset [{}] is not of a video mime type, asset ignored.", (Object)asset.getPath());
                return;
            }
            File tmpDir = null;
            File tmpWorkingDir = null;
            FileOutputStream fos = null;
            InputStream is = null;
            FFMpegWrapper wrapper = null;
            try {
                tmpDir = File.createTempFile("cqdam", null);
                tmpDir.delete();
                tmpDir.mkdir();
                tmpWorkingDir = this.createTempDir(this.getWorkingDir());
                File tmpFile = new File(tmpDir, asset.getName().replace(' ', '_'));
                fos = new FileOutputStream(tmpFile);
                is = asset.getOriginal().getStream();
                IOUtils.copy((InputStream)is, (OutputStream)fos);
                this.processVideo(metaData, asset, tmpFile, wfSession);
                wrapper = new FFMpegWrapper(tmpFile, tmpWorkingDir);
                wrapper.setExecutableLocator(this.locator);
                ResourceResolver resolver = this.getResourceResolver(wfSession.getSession());
                Resource assetResource = (Resource)asset.adaptTo(Resource.class);
                Resource metadata = resolver.getResource(assetResource, "jcr:content/metadata");
                if (null != metadata) {
                    double height;
                    Node metadataNode = (Node)metadata.adaptTo(Node.class);
                    metadataNode.setProperty("dc:extent", wrapper.getInputDuration());
                    double width = null != wrapper.getInputSize() ? wrapper.getInputSize().getWidth() : 0.0;
                    double d = height = null != wrapper.getInputSize() ? wrapper.getInputSize().getHeight() : 0.0;
                    if (width > 0.0 && height > 0.0) {
                        metadataNode.setProperty("tiff:ImageWidth", (long)wrapper.getInputSize().width);
                        metadataNode.setProperty("tiff:ImageLength", (long)wrapper.getInputSize().height);
                    }
                    metadataNode.getSession().save();
                    break block25;
                }
                this.log.warn("execute: failed setting metdata for asset [{}] in workflow [{}], no metdata node found.", (Object)asset.getPath(), (Object)workItem.getId());
            }
            catch (IOException e) {
                throw new WorkflowException((Throwable)e);
            }
            catch (RepositoryException e) {
                throw new WorkflowException((Throwable)e);
            }
            catch (FfmpegNotFoundException e) {
                this.log.error(e.getMessage(), (Throwable)e);
            }
            finally {
                IOUtils.closeQuietly((InputStream)is);
                IOUtils.closeQuietly((OutputStream)fos);
                try {
                    if (tmpDir != null) {
                        FileUtils.deleteDirectory((File)tmpDir);
                    }
                }
                catch (IOException e) {
                    this.log.error("Could not delete temp directory: {}", (Object)tmpDir.getPath());
                    throw new WorkflowException((Throwable)e);
                }
                try {
                    if (tmpWorkingDir != null) {
                        FileUtils.deleteDirectory((File)tmpWorkingDir);
                    }
                }
                catch (IOException e) {
                    this.log.warn("Could not delete ffmpeg's temporary working directory: {}", (Object)tmpWorkingDir.getPath());
                }
            }
        }
    }

    public File getWorkingDir() {
        this.workingDir.mkdir();
        return this.workingDir;
    }

    private File resolveWorkingDir(String slingHome, String path) {
        File workingDir;
        if (path == null) {
            path = "";
        }
        if (!(workingDir = new File(path = path.replace('/', File.separatorChar))).isAbsolute()) {
            File baseDir = new File(slingHome == null ? "" : slingHome).getAbsoluteFile();
            workingDir = new File(baseDir, path).getAbsoluteFile();
        }
        try {
            this.log.info("ffmpeg working directory: {}", (Object)workingDir.getCanonicalPath());
        }
        catch (IOException e) {
            this.log.info("ffmpeg working directory: {}", (Object)workingDir.getAbsolutePath());
        }
        return workingDir;
    }

    protected void activate(ComponentContext ctx) {
        String slingHome = ctx.getBundleContext().getProperty("sling.home");
        this.workingDir = this.resolveWorkingDir(slingHome, (String)ctx.getProperties().get("ffmpeg.workingdir"));
    }

    protected File createTempDir(File parentDir) {
        File tempDir = null;
        try {
            tempDir = File.createTempFile("cqdam", null, parentDir);
            tempDir.delete();
            tempDir.mkdir();
        }
        catch (IOException e) {
            this.log.warn("could not create temp directory in the [{}] with the exception", (Object)parentDir, (Object)e);
        }
        return tempDir;
    }

    abstract String[] buildArguments(MetaDataMap var1);

    abstract void processVideo(MetaDataMap var1, Asset var2, File var3, WorkflowSession var4) throws IOException, RepositoryException;

    protected void bindLocator(ExecutableLocator executableLocator) {
        this.locator = executableLocator;
    }

    protected void unbindLocator(ExecutableLocator executableLocator) {
        if (this.locator == executableLocator) {
            this.locator = null;
        }
    }
}