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.Collections;
031import java.util.HashMap;
032import java.util.List;
033import java.util.Map;
034import java.util.UUID;
035
036import org.apache.commons.io.FileUtils;
037import org.apache.commons.io.FilenameUtils;
038import org.nuxeo.common.utils.Path;
039import org.nuxeo.ecm.core.api.Blob;
040import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
041import org.nuxeo.ecm.core.api.blobholder.SimpleBlobHolderWithProperties;
042import org.nuxeo.ecm.core.convert.api.ConversionException;
043import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
044import org.nuxeo.ecm.platform.convert.plugins.CommandLineBasedConverter;
045import org.nuxeo.ecm.platform.video.VideoInfo;
046import org.nuxeo.ecm.platform.video.tools.VideoTool;
047import org.nuxeo.runtime.api.Framework;
048
049/**
050 * Base class for converters doing video conversions.
051 *
052 * @author <a href="mailto:troger@nuxeo.com">Thomas Roger</a>
053 * @since 5.5
054 */
055public abstract class BaseVideoConversionConverter extends CommandLineBasedConverter {
056
057    protected final String OUTPUT_TMP_PATH = "converterTmpPath";
058
059    @Override
060    protected Map<String, Blob> getCmdBlobParameters(BlobHolder blobHolder,
061            Map<String, Serializable> stringSerializableMap) throws ConversionException {
062        Map<String, Blob> cmdBlobParams = new HashMap<>();
063        cmdBlobParams.put(INPUT_FILE_PATH_PARAMETER, blobHolder.getBlob());
064        return cmdBlobParams;
065    }
066
067    @Override
068    protected Map<String, String> getCmdStringParameters(BlobHolder blobHolder, Map<String, Serializable> parameters)
069            throws ConversionException {
070        Map<String, String> cmdStringParams = new HashMap<>();
071
072        String baseDir = getTmpDirectory(parameters);
073        Path tmpPath = new Path(baseDir).append(getTmpDirectoryPrefix() + "_" + UUID.randomUUID());
074
075        File outDir = new File(tmpPath.toString());
076        boolean dirCreated = outDir.mkdir();
077        if (!dirCreated) {
078            throw new ConversionException("Unable to create tmp dir for transformer output: " + outDir);
079        }
080
081        File outFile;
082        try {
083            outFile = File.createTempFile("videoConversion", getVideoExtension(), outDir);
084        } catch (IOException e) {
085            throw new ConversionException("Unable to get Blob for holder", e);
086        }
087        // delete the file as we need only the path for ffmpeg
088        outFile.delete();
089        cmdStringParams.put(OUTPUT_FILE_PATH_PARAMETER, outFile.getAbsolutePath());
090        String baseName = FilenameUtils.getBaseName(blobHolder.getBlob().getFilename());
091        cmdStringParams.put(OUTPUT_FILE_NAME_PARAMETER, baseName + getVideoExtension());
092
093        VideoInfo videoInfo = (VideoInfo) parameters.get("videoInfo");
094        if (videoInfo == null) {
095            return cmdStringParams;
096        }
097
098        long width = videoInfo.getWidth();
099        long height = videoInfo.getHeight();
100        long newHeight = (Long) parameters.get("height");
101
102        long newWidth = width * newHeight / height;
103        if (newWidth % 2 != 0) {
104            newWidth += 1;
105        }
106
107        cmdStringParams.put(OUTPUT_TMP_PATH, outDir.getAbsolutePath());
108        cmdStringParams.put("width", String.valueOf(newWidth));
109        cmdStringParams.put("height", String.valueOf(newHeight));
110        return cmdStringParams;
111    }
112
113    @Override
114    protected BlobHolder buildResult(List<String> cmdOutput, CmdParameters cmdParameters) throws ConversionException {
115        String outputPath = cmdParameters.getParameter(OUTPUT_FILE_PATH_PARAMETER);
116        Blob blob = VideoTool.getTemporaryBlob(outputPath, getVideoMimeType());
117        String outFileName = cmdParameters.getParameter(OUTPUT_FILE_NAME_PARAMETER);
118        if (outFileName != null) {
119            blob.setFilename(unquoteValue(outFileName));
120        }
121        List<Blob> blobs = new ArrayList<>(Collections.singletonList(blob));
122        Map<String, Serializable> properties = new HashMap<>();
123        properties.put("cmdOutput", (Serializable) cmdOutput);
124
125        // remove the temp output directory
126        File outDir = new File(cmdParameters.getParameter(OUTPUT_TMP_PATH));
127        FileUtils.deleteQuietly(outDir);
128
129        return new SimpleBlobHolderWithProperties(blobs, properties);
130    }
131
132    /**
133     * @since 5.6
134     */
135    protected String unquoteValue(String value) {
136        if (value.startsWith("\"") && value.endsWith("\"")) {
137            return value.substring(1, value.length() - 1);
138        }
139        return value;
140    }
141
142    /**
143     * Returns the video mime type to use for this converter.
144     */
145    protected abstract String getVideoMimeType();
146
147    /**
148     * Returns the video extension, always prefixed by '.'.
149     */
150    protected abstract String getVideoExtension();
151
152    /**
153     * Returns the temporary directory prefix to use for this converter.
154     */
155    protected abstract String getTmpDirectoryPrefix();
156
157}