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.FilenameUtils;
037import org.nuxeo.common.utils.Path;
038import org.nuxeo.ecm.core.api.Blob;
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.ecm.platform.video.tools.VideoTool;
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        cmdStringParams.put(OUTPUT_FILE_PATH_PARAMETER, outFile.getAbsolutePath());
086        String baseName = FilenameUtils.getBaseName(blobHolder.getBlob().getFilename());
087        cmdStringParams.put(OUTPUT_FILE_NAME_PARAMETER, baseName + getVideoExtension());
088
089        VideoInfo videoInfo = (VideoInfo) parameters.get("videoInfo");
090        if (videoInfo == null) {
091            return cmdStringParams;
092        }
093
094        long width = videoInfo.getWidth();
095        long height = videoInfo.getHeight();
096        long newHeight = (Long) parameters.get("height");
097
098        long newWidth = width * newHeight / height;
099        if (newWidth % 2 != 0) {
100            newWidth += 1;
101        }
102
103        cmdStringParams.put("width", String.valueOf(newWidth));
104        cmdStringParams.put("height", String.valueOf(newHeight));
105        return cmdStringParams;
106    }
107
108    @Override
109    protected BlobHolder buildResult(List<String> cmdOutput, CmdParameters cmdParameters) throws ConversionException {
110        String outputPath = cmdParameters.getParameter(OUTPUT_FILE_PATH_PARAMETER);
111        Blob blob = VideoTool.getTemporaryBlob(outputPath, getVideoMimeType());
112        String outFileName = cmdParameters.getParameter(OUTPUT_FILE_NAME_PARAMETER);
113        if (outFileName != null) {
114            blob.setFilename(unquoteValue(outFileName));
115        }
116        List<Blob> blobs = new ArrayList<>(Collections.singletonList(blob));
117        Map<String, Serializable> properties = new HashMap<>();
118        properties.put("cmdOutput", (Serializable) cmdOutput);
119        return new SimpleBlobHolderWithProperties(blobs, properties);
120    }
121
122    /**
123     * @since 5.6
124     */
125    protected String unquoteValue(String value) {
126        if (value.startsWith("\"") && value.endsWith("\"")) {
127            return value.substring(1, value.length() - 1);
128        }
129        return value;
130    }
131
132    /**
133     * Returns the video mime type to use for this converter.
134     */
135    protected abstract String getVideoMimeType();
136
137    /**
138     * Returns the video extension, always prefixed by '.'.
139     */
140    protected abstract String getVideoExtension();
141
142    /**
143     * Returns the temporary directory prefix to use for this converter.
144     */
145    protected abstract String getTmpDirectoryPrefix();
146
147}