/** * 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.liferay.portal.kernel.util.PropsKeys; import com.xuggle.xuggler.IAudioResampler; import com.xuggle.xuggler.IAudioSamples; 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 java.util.Properties; /** * @author Juan González * @author Sergio González * @author Brian Wing Shun Chan * @author Alexander Chow */ public class LiferayAudioConverter extends LiferayConverter { public LiferayAudioConverter( String inputURL, String outputURL, String audioContainer, Properties audioProperties) { _inputURL = inputURL; _outputURL = outputURL; _audioContainer = audioContainer; initAudioBitRate(audioProperties); initAudioSampleRate(audioProperties); } @Override public void convert() throws Exception { try { doConvert(); } finally { if ((_inputIContainer != null) && _inputIContainer.isOpened()) { _inputIContainer.close(); } if ((_outputIContainer != null) && _outputIContainer.isOpened()) { _outputIContainer.close(); } } } protected void doConvert() throws Exception { _inputIContainer = IContainer.make(); _outputIContainer = IContainer.make(); openContainer(_inputIContainer, _inputURL, false); openContainer(_outputIContainer, _outputURL, true); int inputStreamsCount = _inputIContainer.getNumStreams(); if (inputStreamsCount < 0) { throw new RuntimeException("Input URL does not have any streams"); } IAudioResampler[] iAudioResamplers = new IAudioResampler[inputStreamsCount]; IAudioSamples[] inputIAudioSamples = new IAudioSamples[inputStreamsCount]; IAudioSamples[] outputIAudioSamples = new IAudioSamples[inputStreamsCount]; IStream[] outputIStreams = new IStream[inputStreamsCount]; IStreamCoder[] inputIStreamCoders = new IStreamCoder[inputStreamsCount]; IStreamCoder[] outputIStreamCoders = new IStreamCoder[inputStreamsCount]; for (int i = 0; i < inputStreamsCount; i++) { IStream inputIStream = _inputIContainer.getStream(i); IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder(); inputIStreamCoders[i] = inputIStreamCoder; ICodec.Type inputICodecType = inputIStreamCoder.getCodecType(); if (inputICodecType == ICodec.Type.CODEC_TYPE_AUDIO) { prepareAudio( iAudioResamplers, inputIAudioSamples, outputIAudioSamples, inputIStreamCoder, outputIStreamCoders, _outputIContainer, outputIStreams, inputICodecType, _outputURL, i); } openStreamCoder(inputIStreamCoders[i]); openStreamCoder(outputIStreamCoders[i]); } if (_outputIContainer.writeHeader() < 0) { throw new RuntimeException("Unable to write container header"); } IPacket inputIPacket = IPacket.make(); IPacket outputIPacket = IPacket.make(); int previousPacketSize = -1; _inputIContainer.readNextPacket(inputIPacket); while (_inputIContainer.readNextPacket(inputIPacket) == 0) { if (_log.isDebugEnabled()) { _log.debug("Current packet size " + inputIPacket.getSize()); } int streamIndex = inputIPacket.getStreamIndex(); IStreamCoder inputIStreamCoder = inputIStreamCoders[streamIndex]; IStreamCoder outputIStreamCoder = outputIStreamCoders[streamIndex]; if (outputIStreamCoder == null) { continue; } if (inputIStreamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) { IStream iStream = _inputIContainer.getStream(streamIndex); long timeStampOffset = getStreamTimeStampOffset(iStream); decodeAudio( iAudioResamplers[streamIndex], inputIAudioSamples[streamIndex], outputIAudioSamples[streamIndex], inputIPacket, outputIPacket, inputIStreamCoder, outputIStreamCoder, _outputIContainer, inputIPacket.getSize(), previousPacketSize, streamIndex, timeStampOffset); } previousPacketSize = inputIPacket.getSize(); } flush(outputIStreamCoders, _outputIContainer); if (_outputIContainer.writeTrailer() < 0) { throw new RuntimeException( "Unable to write trailer to output file"); } cleanUp(iAudioResamplers, null); cleanUp(inputIAudioSamples, outputIAudioSamples); cleanUp(inputIStreamCoders, outputIStreamCoders); cleanUp(inputIPacket, outputIPacket); } @Override protected int getAudioBitRate(ICodec outputICodec, int originalBitRate) { return getCodecBitRate( outputICodec, getProperty(originalBitRate, _audioBitRate, AUDIO_BIT_RATE_MAX)); } @Override protected int getAudioSampleRate() { return _audioSampleRate; } @Override protected IContainer getInputIContainer() { return _inputIContainer; } protected void initAudioBitRate(Properties audioProperties) { _audioBitRate = getProperty( audioProperties, PropsKeys.DL_FILE_ENTRY_PREVIEW_AUDIO_BIT_RATE, "audio bit rate", _audioContainer, AUDIO_BIT_RATE_DEFAULT, AUDIO_BIT_RATE_MAX); } protected void initAudioSampleRate(Properties audioProperties) { _audioSampleRate = getProperty( audioProperties, PropsKeys.DL_FILE_ENTRY_PREVIEW_AUDIO_SAMPLE_RATE, "audio sample rate", _audioContainer, AUDIO_SAMPLE_RATE_DEFAULT, AUDIO_SAMPLE_RATE_MAX); } private static final Log _log = LogFactoryUtil.getLog( LiferayAudioConverter.class); private int _audioBitRate; private final String _audioContainer; private int _audioSampleRate; private IContainer _inputIContainer; private final String _inputURL; private IContainer _outputIContainer; private final String _outputURL; }