/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portlet.documentlibrary.util;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.xuggle.xuggler.ICodec;
import com.xuggle.xuggler.IContainer;
import com.xuggle.xuggler.IPacket;
import com.xuggle.xuggler.IStream;
import com.xuggle.xuggler.IStreamCoder;
import com.xuggle.xuggler.IVideoPicture;
import java.io.File;
/**
* @author Juan González
* @author Sergio González
* @author Brian Wing Shun Chan
*/
public class LiferayVideoThumbnailConverter extends LiferayConverter {
public LiferayVideoThumbnailConverter(
String inputURL, File outputFile, String extension, int height,
int width, int percentage) {
_inputURL = inputURL;
_outputFile = outputFile;
_extension = extension;
_height = height;
_width = width;
_percentage = percentage;
}
@Override
public void convert() throws Exception {
try {
doConvert();
}
finally {
if ((_inputIContainer != null) && _inputIContainer.isOpened()) {
_inputIContainer.close();
}
}
}
protected void doConvert() throws Exception {
_inputIContainer = IContainer.make();
openContainer(_inputIContainer, _inputURL, false);
long seekTimeStamp = -1;
if ((_percentage > 0) && (_percentage <= 100)) {
seekTimeStamp = getSeekTimeStamp(_percentage);
}
int inputStreamsCount = _inputIContainer.getNumStreams();
if (inputStreamsCount < 0) {
throw new RuntimeException("Input URL does not have any streams");
}
IVideoPicture[] inputIVideoPictures =
new IVideoPicture[inputStreamsCount];
IStreamCoder[] inputIStreamCoders = new IStreamCoder[inputStreamsCount];
for (int i = 0; i < inputStreamsCount; i++) {
IStream inputIStream = _inputIContainer.getStream(i);
IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
inputIStreamCoders[i] = inputIStreamCoder;
if (inputIStreamCoder.getCodecType() ==
ICodec.Type.CODEC_TYPE_VIDEO) {
inputIVideoPictures[i] = IVideoPicture.make(
inputIStreamCoder.getPixelType(),
inputIStreamCoder.getWidth(),
inputIStreamCoder.getHeight());
}
openStreamCoder(inputIStreamCoder);
}
boolean thumbnailGenerated = false;
try {
if (seekTimeStamp != -1) {
rewind();
seek(seekTimeStamp);
}
thumbnailGenerated = generateThumbnail(
inputIStreamCoders, inputIVideoPictures);
}
catch (Exception e) {
}
if (!thumbnailGenerated) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to create thumbnail from specified frame. Will " +
"generate thumbnail from the beginning.");
}
rewind();
generateThumbnail(inputIStreamCoders, inputIVideoPictures);
}
cleanUp(inputIVideoPictures, null);
cleanUp(inputIStreamCoders, null);
}
protected boolean generateThumbnail(
IStreamCoder[] inputIStreamCoders,
IVideoPicture[] inputIVideoPictures)
throws Exception {
boolean keyPacketFound = false;
int nonKeyAfterKeyCount = 0;
boolean onlyDecodeKeyPackets = false;
IPacket inputIPacket = IPacket.make();
while (_inputIContainer.readNextPacket(inputIPacket) == 0) {
if (_log.isDebugEnabled()) {
_log.debug("Current packet size " + inputIPacket.getSize());
}
int streamIndex = inputIPacket.getStreamIndex();
IStreamCoder inputIStreamCoder = inputIStreamCoders[streamIndex];
if (inputIStreamCoder.getCodecType() !=
ICodec.Type.CODEC_TYPE_VIDEO) {
continue;
}
keyPacketFound = isKeyPacketFound(inputIPacket, keyPacketFound);
nonKeyAfterKeyCount = countNonKeyAfterKey(
inputIPacket, keyPacketFound, nonKeyAfterKeyCount);
if (isStartDecoding(
inputIPacket, inputIStreamCoder, keyPacketFound,
nonKeyAfterKeyCount, onlyDecodeKeyPackets)) {
IStream iStream = _inputIContainer.getStream(streamIndex);
long timeStampOffset = getStreamTimeStampOffset(iStream);
int value = decodeVideo(
null, inputIVideoPictures[streamIndex], null, inputIPacket,
null, inputIStreamCoder, null, null, _outputFile,
_extension, _height, _width, timeStampOffset);
if (value <= 0) {
if (inputIPacket.isKey()) {
throw new RuntimeException(
"Unable to decode video stream " + streamIndex);
}
onlyDecodeKeyPackets = true;
continue;
}
else if (value == DECODE_VIDEO_THUMBNAIL) {
cleanUp(inputIPacket, null);
return true;
}
}
else {
if (_log.isDebugEnabled()) {
_log.debug("Do not decode video stream " + streamIndex);
}
}
}
cleanUp(inputIPacket, null);
return false;
}
@Override
protected IContainer getInputIContainer() {
return _inputIContainer;
}
private static final Log _log = LogFactoryUtil.getLog(
LiferayVideoThumbnailConverter.class);
private final String _extension;
private final int _height;
private IContainer _inputIContainer;
private final String _inputURL;
private final File _outputFile;
private final int _percentage;
private final int _width;
}