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