001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Thomas Roger <troger@nuxeo.com>
016 */
017
018package org.nuxeo.ecm.platform.video.convert;
019
020import static org.nuxeo.ecm.platform.video.convert.Constants.INPUT_FILE_PATH_PARAMETER;
021import static org.nuxeo.ecm.platform.video.convert.Constants.OUTPUT_FILE_NAME_PARAMETER;
022import static org.nuxeo.ecm.platform.video.convert.Constants.OUTPUT_FILE_PATH_PARAMETER;
023
024import java.io.File;
025import java.io.IOException;
026import java.io.Serializable;
027import java.util.ArrayList;
028import java.util.HashMap;
029import java.util.List;
030import java.util.Map;
031import java.util.UUID;
032
033import org.apache.commons.io.FilenameUtils;
034import org.nuxeo.common.utils.Path;
035import org.nuxeo.ecm.core.api.Blob;
036import org.nuxeo.ecm.core.api.Blobs;
037import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
038import org.nuxeo.ecm.core.api.blobholder.SimpleBlobHolderWithProperties;
039import org.nuxeo.ecm.core.convert.api.ConversionException;
040import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
041import org.nuxeo.ecm.platform.convert.plugins.CommandLineBasedConverter;
042import org.nuxeo.ecm.platform.video.VideoInfo;
043import org.nuxeo.runtime.api.Framework;
044
045/**
046 * Base class for converters doing video conversions.
047 *
048 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
049 * @since 5.5
050 */
051public abstract class BaseVideoConversionConverter extends CommandLineBasedConverter {
052
053    @Override
054    protected Map<String, Blob> getCmdBlobParameters(BlobHolder blobHolder,
055            Map<String, Serializable> stringSerializableMap) throws ConversionException {
056        Map<String, Blob> cmdBlobParams = new HashMap<String, Blob>();
057        cmdBlobParams.put(INPUT_FILE_PATH_PARAMETER, blobHolder.getBlob());
058        return cmdBlobParams;
059    }
060
061    @Override
062    protected Map<String, String> getCmdStringParameters(BlobHolder blobHolder, Map<String, Serializable> parameters)
063            throws ConversionException {
064        Map<String, String> cmdStringParams = new HashMap<String, String>();
065
066        String baseDir = getTmpDirectory(parameters);
067        Path tmpPath = new Path(baseDir).append(getTmpDirectoryPrefix() + "_" + UUID.randomUUID());
068
069        File outDir = new File(tmpPath.toString());
070        boolean dirCreated = outDir.mkdir();
071        if (!dirCreated) {
072            throw new ConversionException("Unable to create tmp dir for transformer output: " + outDir);
073        }
074
075        File outFile;
076        try {
077            outFile = File.createTempFile("videoConversion", getVideoExtension(), outDir);
078        } catch (IOException e) {
079            throw new ConversionException("Unable to get Blob for holder", e);
080        }
081        // delete the file as we need only the path for ffmpeg
082        outFile.delete();
083        Framework.trackFile(outFile, this);
084        cmdStringParams.put(OUTPUT_FILE_PATH_PARAMETER, outFile.getAbsolutePath());
085        String baseName = FilenameUtils.getBaseName(blobHolder.getBlob().getFilename());
086        cmdStringParams.put(OUTPUT_FILE_NAME_PARAMETER, baseName + getVideoExtension());
087
088        VideoInfo videoInfo = (VideoInfo) parameters.get("videoInfo");
089        if (videoInfo == null) {
090            return cmdStringParams;
091        }
092
093        long width = videoInfo.getWidth();
094        long height = videoInfo.getHeight();
095        long newHeight = (Long) parameters.get("height");
096
097        long newWidth = width * newHeight / height;
098        if (newWidth % 2 != 0) {
099            newWidth += 1;
100        }
101
102        cmdStringParams.put("width", String.valueOf(newWidth));
103        cmdStringParams.put("height", String.valueOf(newHeight));
104        return cmdStringParams;
105    }
106
107    @Override
108    protected BlobHolder buildResult(List<String> cmdOutput, CmdParameters cmdParameters) throws ConversionException {
109        String outputPath = cmdParameters.getParameter(OUTPUT_FILE_PATH_PARAMETER);
110        File outputFile = new File(outputPath);
111        List<Blob> blobs = new ArrayList<Blob>();
112        String outFileName = cmdParameters.getParameter(OUTPUT_FILE_NAME_PARAMETER);
113        if (outFileName == null) {
114            outFileName = outputFile.getName();
115        } else {
116            outFileName = unquoteValue(outFileName);
117        }
118
119        try {
120            Blob blob = Blobs.createBlob(outputFile, getVideoMimeType(), null, outFileName);
121            blobs.add(blob);
122        } catch (IOException e) {
123            throw new ConversionException("Cannot create blob", e);
124        }
125
126        Map<String, Serializable> properties = new HashMap<String, Serializable>();
127        properties.put("cmdOutput", (Serializable) cmdOutput);
128        return new SimpleBlobHolderWithProperties(blobs, properties);
129    }
130
131    /**
132     * @since 5.6
133     */
134    protected String unquoteValue(String value) {
135        if (value.startsWith("\"") && value.endsWith("\"")) {
136            return value.substring(1, value.length() - 1);
137        }
138        return value;
139    }
140
141    /**
142     * Returns the video mime type to use for this converter.
143     */
144    protected abstract String getVideoMimeType();
145
146    /**
147     * Returns the video extension, always prefixed by '.'.
148     */
149    protected abstract String getVideoExtension();
150
151    /**
152     * Returns the temporary directory prefix to use for this converter.
153     */
154    protected abstract String getTmpDirectoryPrefix();
155
156}