001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.documentlibrary.util;
016    
017    import com.liferay.portal.image.ImageToolImpl;
018    import com.liferay.portal.kernel.image.ImageTool;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    
023    import com.xuggle.ferry.RefCounted;
024    import com.xuggle.xuggler.Global;
025    import com.xuggle.xuggler.IAudioResampler;
026    import com.xuggle.xuggler.IAudioSamples.Format;
027    import com.xuggle.xuggler.IAudioSamples;
028    import com.xuggle.xuggler.ICodec;
029    import com.xuggle.xuggler.IContainer;
030    import com.xuggle.xuggler.IContainerFormat;
031    import com.xuggle.xuggler.IPacket;
032    import com.xuggle.xuggler.IPixelFormat;
033    import com.xuggle.xuggler.IRational;
034    import com.xuggle.xuggler.IStream;
035    import com.xuggle.xuggler.IStreamCoder;
036    import com.xuggle.xuggler.IVideoPicture;
037    import com.xuggle.xuggler.IVideoResampler;
038    import com.xuggle.xuggler.video.ConverterFactory;
039    import com.xuggle.xuggler.video.IConverter;
040    
041    import java.awt.image.BufferedImage;
042    import java.awt.image.RenderedImage;
043    
044    import java.io.File;
045    import java.io.FileOutputStream;
046    
047    import java.util.List;
048    import java.util.Properties;
049    
050    import javax.imageio.ImageIO;
051    
052    /**
053     * @author Juan Gonz??lez
054     * @author Sergio Gonz??lez
055     * @author Brian Wing Shun Chan
056     * @author Alexander Chow
057     */
058    public abstract class LiferayConverter {
059    
060            public abstract void convert() throws Exception;
061    
062            protected void cleanUp(IPacket inputIPacket, IPacket outputIPacket) {
063                    if (inputIPacket != null) {
064                            inputIPacket.delete();
065                    }
066    
067                    if (outputIPacket != null) {
068                            outputIPacket.delete();
069                    }
070            }
071    
072            protected void cleanUp(
073                    IStreamCoder[] inputIStreamCoders, IStreamCoder[] outputIStreamCoders) {
074    
075                    if (inputIStreamCoders != null) {
076                            for (IStreamCoder iStreamCoder : inputIStreamCoders) {
077                                    if (iStreamCoder != null) {
078                                            iStreamCoder.close();
079                                    }
080                            }
081                    }
082    
083                    if (outputIStreamCoders != null) {
084                            for (IStreamCoder iStreamCoder : outputIStreamCoders) {
085                                    if (iStreamCoder != null) {
086                                            iStreamCoder.close();
087                                    }
088                            }
089                    }
090            }
091    
092            protected void cleanUp(
093                    RefCounted[] inputRefCountedArray, RefCounted[] outputRefCountedArray) {
094    
095                    if (inputRefCountedArray != null) {
096                            for (RefCounted refCounted : inputRefCountedArray) {
097                                    if (refCounted != null) {
098                                            refCounted.delete();
099                                    }
100                            }
101                    }
102    
103                    if (outputRefCountedArray != null) {
104                            for (RefCounted refCounted : outputRefCountedArray) {
105                                    if (refCounted != null) {
106                                            refCounted.delete();
107                                    }
108                            }
109                    }
110            }
111    
112            protected int countNonKeyAfterKey(
113                    IPacket inputIPacket, Boolean keyPacketFound, int nonKeyAfterKeyCount) {
114    
115                    if (inputIPacket.isKey()) {
116                            nonKeyAfterKeyCount = 0;
117                    }
118                    else if (keyPacketFound) {
119                            nonKeyAfterKeyCount++;
120                    }
121    
122                    return nonKeyAfterKeyCount;
123            }
124    
125            protected IAudioResampler createIAudioResampler(
126                            IStreamCoder inputIStreamCoder, IStreamCoder outputIStreamCoder)
127                    throws Exception {
128    
129                    IAudioResampler iAudioResampler = null;
130    
131                    Format inputSampleFormat = inputIStreamCoder.getSampleFormat();
132                    Format outputSampleFormat = outputIStreamCoder.getSampleFormat();
133    
134                    if ((inputIStreamCoder.getChannels() ==
135                                    outputIStreamCoder.getChannels()) &&
136                            (inputIStreamCoder.getSampleRate() ==
137                                    outputIStreamCoder.getSampleRate()) &&
138                            inputSampleFormat.equals(outputSampleFormat)) {
139    
140                            return iAudioResampler;
141                    }
142    
143                    iAudioResampler = IAudioResampler.make(
144                            outputIStreamCoder.getChannels(), inputIStreamCoder.getChannels(),
145                            outputIStreamCoder.getSampleRate(),
146                            inputIStreamCoder.getSampleRate(),
147                            outputIStreamCoder.getSampleFormat(),
148                            inputIStreamCoder.getSampleFormat());
149    
150                    if (iAudioResampler == null) {
151                            throw new RuntimeException("Audio resampling is not supported");
152                    }
153    
154                    return iAudioResampler;
155            }
156    
157            protected IVideoResampler createIVideoResampler(
158                            IStreamCoder inputIStreamCoder, IStreamCoder outputIStreamCoder,
159                            int height, int width)
160                    throws Exception {
161    
162                    IVideoResampler iVideoResampler = null;
163    
164                    IPixelFormat.Type inputIPixelFormatType =
165                            inputIStreamCoder.getPixelType();
166                    IPixelFormat.Type outputIPixelFormatType =
167                            outputIStreamCoder.getPixelType();
168    
169                    if ((height == inputIStreamCoder.getHeight()) &&
170                            (width == inputIStreamCoder.getWidth()) &&
171                            inputIPixelFormatType.equals(outputIPixelFormatType)) {
172    
173                            return iVideoResampler;
174                    }
175    
176                    iVideoResampler = IVideoResampler.make(
177                            width, height, outputIStreamCoder.getPixelType(),
178                            inputIStreamCoder.getWidth(), inputIStreamCoder.getHeight(),
179                            inputIStreamCoder.getPixelType());
180    
181                    if (iVideoResampler == null) {
182                            throw new RuntimeException("Video resampling is not supported");
183                    }
184    
185                    return iVideoResampler;
186            }
187    
188            protected void decodeAudio(
189                            IAudioResampler iAudioResampler, IAudioSamples inputIAudioSample,
190                            IAudioSamples resampledIAudioSample, IPacket inputIPacket,
191                            IPacket outputIPacket, IStreamCoder inputIStreamCoder,
192                            IStreamCoder outputIStreamCoder, IContainer outputIContainer,
193                            int currentPacketSize, int previousPacketSize, int streamIndex,
194                            long timeStampOffset)
195                    throws Exception {
196    
197                    int offset = 0;
198    
199                    while (offset < inputIPacket.getSize()) {
200                            boolean stopDecoding = false;
201    
202                            int value = inputIStreamCoder.decodeAudio(
203                                    inputIAudioSample, inputIPacket, offset);
204    
205                            if (value <= 0) {
206                                    if ((previousPacketSize == currentPacketSize) &&
207                                            (previousPacketSize != -1)) {
208    
209                                            throw new RuntimeException(
210                                                    "Unable to decode audio stream " + streamIndex);
211                                    }
212                                    else {
213                                            stopDecoding = true;
214                                    }
215                            }
216    
217                            updateAudioTimeStamp(inputIAudioSample, timeStampOffset);
218    
219                            offset += value;
220    
221                            IAudioSamples outputIAudioSample = resampleAudio(
222                                    iAudioResampler, inputIAudioSample, resampledIAudioSample);
223    
224                            encodeAudio(
225                                    outputIStreamCoder, outputIPacket, outputIAudioSample,
226                                    outputIContainer);
227    
228                            if (stopDecoding) {
229                                    if (_log.isDebugEnabled()) {
230                                            _log.debug("Stop decoding audio stream " + streamIndex);
231                                    }
232    
233                                    break;
234                            }
235                    }
236            }
237    
238            protected int decodeVideo(
239                            IVideoResampler iVideoResampler, IVideoPicture inputIVideoPicture,
240                            IVideoPicture resampledIVideoPicture, IPacket inputIPacket,
241                            IPacket outputIPacket, IStreamCoder inputIStreamCoder,
242                            IStreamCoder outputIStreamCoder, IContainer outputIContainer,
243                            File thumbnailFile, String thumbnailExtension, int thumbnailHeight,
244                            int thumbnailWidth, long timeStampOffset)
245                    throws Exception {
246    
247                    int offset = 0;
248    
249                    boolean stopDecoding = false;
250    
251                    while (offset < inputIPacket.getSize()) {
252                            int value = inputIStreamCoder.decodeVideo(
253                                    inputIVideoPicture, inputIPacket, offset);
254    
255                            if (value <= 0) {
256                                    return value;
257                            }
258    
259                            updateVideoTimeStamp(inputIVideoPicture, timeStampOffset);
260    
261                            offset += value;
262    
263                            // Workaround for FFmpeg bug. See
264                            // http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/135657
265    
266                            ICodec.ID iCodecID = inputIStreamCoder.getCodecID();
267    
268                            if (iCodecID.equals(ICodec.ID.CODEC_ID_MJPEG)) {
269                                    stopDecoding = true;
270                            }
271    
272                            if (!inputIVideoPicture.isComplete()) {
273                                    if (stopDecoding) {
274                                            return 1;
275                                    }
276                                    else {
277                                            continue;
278                                    }
279                            }
280    
281                            if (thumbnailFile != null) {
282                                    BufferedImage bufferedImage = null;
283    
284                                    if (_converterFactoryType == null) {
285                                            _converterFactoryType =
286                                                    ConverterFactory.findRegisteredConverter(
287                                                            ConverterFactory.XUGGLER_BGR_24);
288                                    }
289    
290                                    if (_converterFactoryType == null) {
291                                            throw new UnsupportedOperationException(
292                                                    "No converter found for " +
293                                                            ConverterFactory.XUGGLER_BGR_24);
294                                    }
295    
296                                    if (_videoIConverter == null) {
297                                            _videoIConverter = ConverterFactory.createConverter(
298                                                    _converterFactoryType.getDescriptor(),
299                                                    inputIVideoPicture);
300                                    }
301    
302                                    bufferedImage = _videoIConverter.toImage(inputIVideoPicture);
303    
304                                    thumbnailFile.createNewFile();
305    
306                                    ImageTool imageTool = ImageToolImpl.getInstance();
307    
308                                    RenderedImage renderedImage = imageTool.scale(
309                                            bufferedImage, thumbnailHeight, thumbnailWidth);
310    
311                                    ImageIO.write(
312                                            renderedImage, thumbnailExtension,
313                                            new FileOutputStream(thumbnailFile));
314    
315                                    return DECODE_VIDEO_THUMBNAIL;
316                            }
317    
318                            if ((outputIStreamCoder != null) && (outputIContainer != null)) {
319                                    IVideoPicture outputIVideoPicture = resampleVideo(
320                                            iVideoResampler, inputIVideoPicture,
321                                            resampledIVideoPicture);
322    
323                                    outputIVideoPicture.setQuality(0);
324    
325                                    encodeVideo(
326                                            outputIStreamCoder, outputIVideoPicture, outputIPacket,
327                                            outputIContainer);
328                            }
329    
330                            if (stopDecoding) {
331                                    break;
332                            }
333                    }
334    
335                    return 1;
336            }
337    
338            protected void encodeAudio(
339                            IStreamCoder outputIStreamCoder, IPacket outputIPacket,
340                            IAudioSamples outputIAudioSample, IContainer outputIContainer)
341                    throws Exception {
342    
343                    int consumedSamplesCount = 0;
344    
345                    while (consumedSamplesCount < outputIAudioSample.getNumSamples()) {
346                            int value = outputIStreamCoder.encodeAudio(
347                                    outputIPacket, outputIAudioSample, consumedSamplesCount);
348    
349                            if (value <= 0) {
350                                    throw new RuntimeException("Unable to encode audio");
351                            }
352    
353                            consumedSamplesCount += value;
354    
355                            if (outputIPacket.isComplete()) {
356                                    value = outputIContainer.writePacket(outputIPacket, true);
357    
358                                    if (value < 0) {
359                                            throw new RuntimeException("Unable to write audio packet");
360                                    }
361                            }
362                    }
363            }
364    
365            protected void encodeVideo(
366                            IStreamCoder outputIStreamCoder, IVideoPicture outputIVideoPicture,
367                            IPacket outputIPacket, IContainer outputIContainer)
368                    throws Exception {
369    
370                    int value = outputIStreamCoder.encodeVideo(
371                            outputIPacket, outputIVideoPicture, 0);
372    
373                    if (value < 0) {
374                            throw new RuntimeException("Unable to encode video");
375                    }
376    
377                    if (outputIPacket.isComplete()) {
378                            value = outputIContainer.writePacket(outputIPacket, true);
379    
380                            if (value < 0) {
381                                    throw new RuntimeException("Unable to write video packet");
382                            }
383                    }
384            }
385    
386            protected void flush(
387                    IStreamCoder outputIStreamCoder, IContainer outputIContainer,
388                    IPacket iPacket) {
389    
390                    if (outputIStreamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
391                            outputIStreamCoder.encodeAudio(iPacket, null, 0);
392                    }
393                    else {
394                            outputIStreamCoder.encodeVideo(iPacket, null, 0);
395                    }
396    
397                    if (iPacket.isComplete()) {
398                            outputIContainer.writePacket(iPacket, true);
399                    }
400            }
401    
402            protected void flush(
403                    IStreamCoder[] outputIStreamCoders, IContainer outputIContainer) {
404    
405                    for (IStreamCoder outputIStreamCoder : outputIStreamCoders) {
406                            if (outputIStreamCoder == null) {
407                                    continue;
408                            }
409    
410                            IPacket iPacket = IPacket.make();
411    
412                            flush(outputIStreamCoder, outputIContainer, iPacket);
413    
414                            while (iPacket.isComplete()) {
415                                    flush(outputIStreamCoder, outputIContainer, iPacket);
416                            }
417                    }
418            }
419    
420            protected int getAudioBitRate(ICodec outputICodec, int originalBitRate) {
421                    if ((originalBitRate == 0) || (originalBitRate > AUDIO_BIT_RATE_MAX)) {
422                            originalBitRate = AUDIO_BIT_RATE_DEFAULT;
423                    }
424    
425                    ICodec.ID iCodecID = outputICodec.getID();
426    
427                    if (iCodecID.equals(ICodec.ID.CODEC_ID_VORBIS)) {
428                            if (originalBitRate < 64000) {
429                                    originalBitRate = 64000;
430                            }
431                    }
432    
433                    return originalBitRate;
434            }
435    
436            protected int getAudioEncodingChannels(
437                    IContainer outputIContainer, int channels) {
438    
439                    IContainerFormat iContainerFormat =
440                            outputIContainer.getContainerFormat();
441    
442                    String outputFormat = iContainerFormat.getOutputFormatShortName();
443    
444                    if (outputFormat.equals("ogg")) {
445                            return 2;
446                    }
447    
448                    if ((channels == 0) || (channels > 2)) {
449                            channels = 2;
450                    }
451    
452                    return channels;
453            }
454    
455            protected ICodec getAudioEncodingICodec(IContainer outputIContainer) {
456                    IContainerFormat iContainerFormat =
457                            outputIContainer.getContainerFormat();
458    
459                    String outputFormat = iContainerFormat.getOutputFormatShortName();
460    
461                    if (outputFormat.equals("ogg")) {
462                            return ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_VORBIS);
463                    }
464    
465                    return null;
466            }
467    
468            protected Format getAudioSampleFormat(
469                    ICodec outputICodec, Format originalSampleFormat) {
470    
471                    Format sampleFormat = null;
472    
473                    List<Format> supportedSampleFormats =
474                            outputICodec.getSupportedAudioSampleFormats();
475    
476                    for (Format supportedSampleFormat : supportedSampleFormats) {
477                            sampleFormat = supportedSampleFormat;
478    
479                            if (supportedSampleFormat == originalSampleFormat) {
480                                    break;
481                            }
482                    }
483    
484                    return sampleFormat;
485            }
486    
487            protected int getAudioSampleRate() {
488                    return AUDIO_SAMPLE_RATE_DEFAULT;
489            }
490    
491            protected abstract IContainer getInputIContainer();
492    
493            protected int getProperty(
494                    int originalValue, int defaultValue, int maxValue) {
495    
496                    if (originalValue <= 0) {
497                            originalValue = defaultValue;
498                    }
499                    else if (originalValue > maxValue) {
500                            originalValue = maxValue;
501                    }
502    
503                    return originalValue;
504            }
505    
506            protected int getProperty(
507                    Properties properties, String propertyName, String prettyPropertyName,
508                    String container, int defaultValue, int maxValue) {
509    
510                    int property = GetterUtil.getInteger(
511                            properties.getProperty(propertyName + "[" + container + "]"),
512                            defaultValue);
513    
514                    if (property > maxValue) {
515                            property = maxValue;
516                    }
517    
518                    if (_log.isInfoEnabled()) {
519                            _log.info(
520                                    "Default " + prettyPropertyName + " for " + container +
521                                            " configured to " + property);
522                    }
523    
524                    return property;
525            }
526    
527            protected long getSeekTimeStamp(int percentage) throws Exception {
528                    IContainer inputIContainer = getInputIContainer();
529    
530                    long seekTimeStamp = -1;
531    
532                    long videoSeconds = inputIContainer.getDuration() / 1000000L;
533    
534                    long seekSeconds = ((videoSeconds * percentage) / 100L);
535    
536                    for (int i = 0; i < inputIContainer.getNumStreams(); i++) {
537                            IStream inputIStream = inputIContainer.getStream(i);
538    
539                            IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
540    
541                            if (inputIStreamCoder.getCodecType() !=
542                                            ICodec.Type.CODEC_TYPE_VIDEO) {
543    
544                                    continue;
545                            }
546    
547                            IRational iRational = inputIStream.getTimeBase();
548    
549                            long timeStampOffset =
550                                    iRational.getDenominator() / iRational.getNumerator() *
551                                            seekSeconds;
552    
553                            seekTimeStamp = inputIContainer.getStartTime() + timeStampOffset;
554    
555                            break;
556                    }
557    
558                    return seekTimeStamp;
559            }
560    
561            protected long getStreamTimeStampOffset(IStream iStream) {
562                    long timeStampOffset = 0;
563    
564                    if ((iStream.getStartTime() != Global.NO_PTS) &&
565                            (iStream.getStartTime() > 0) && (iStream.getTimeBase() != null)) {
566    
567                            IRational iRational = IRational.make(
568                                    1, (int)Global.DEFAULT_PTS_PER_SECOND);
569    
570                            timeStampOffset = iRational.rescale(
571                                    iStream.getStartTime(), iStream.getTimeBase());
572                    }
573    
574                    return timeStampOffset;
575            }
576    
577            protected boolean isKeyPacketFound(
578                    IPacket inputIPacket, boolean keyPacketFound) {
579    
580                    if (inputIPacket.isKey() && !keyPacketFound) {
581                            return true;
582                    }
583    
584                    return keyPacketFound;
585            }
586    
587            protected boolean isStartDecoding(
588                    IPacket inputIPacket, IStreamCoder inputIStreamCoder,
589                    boolean keyPacketFound, int nonKeyAfterKeyCount,
590                    boolean onlyDecodeKeyPackets) {
591    
592                    if (onlyDecodeKeyPackets && !inputIPacket.isKey()) {
593                            return false;
594                    }
595    
596                    ICodec.ID iCodecID = inputIStreamCoder.getCodecID();
597    
598                    if (iCodecID.equals(ICodec.ID.CODEC_ID_MJPEG)) {
599                            return true;
600                    }
601                    else if (iCodecID.equals(ICodec.ID.CODEC_ID_MPEG2VIDEO) ||
602                                     iCodecID.equals(ICodec.ID.CODEC_ID_THEORA)) {
603    
604                            if (nonKeyAfterKeyCount != 1) {
605                                    return true;
606                            }
607    
608                            return false;
609                    }
610    
611                    return keyPacketFound;
612            }
613    
614            protected void openContainer(
615                            IContainer iContainer, String url, boolean writeContainer)
616                    throws Exception {
617    
618                    int value = 0;
619    
620                    if (writeContainer) {
621                            value = iContainer.open(url, IContainer.Type.WRITE, null);
622                    }
623                    else {
624                            value = iContainer.open(url, IContainer.Type.READ, null);
625                    }
626    
627                    if (value < 0) {
628                            if (writeContainer) {
629                                    throw new RuntimeException("Unable to open output URL");
630                            }
631                            else {
632                                    throw new RuntimeException("Unable to open input URL");
633                            }
634                    }
635            }
636    
637            protected void openStreamCoder(IStreamCoder iStreamCoder) throws Exception {
638                    if ((iStreamCoder != null) &&
639                            (iStreamCoder.getCodecType() != ICodec.Type.CODEC_TYPE_UNKNOWN)) {
640    
641                            int result = iStreamCoder.setStandardsCompliance(
642                                    IStreamCoder.CodecStandardsCompliance.COMPLIANCE_EXPERIMENTAL);
643    
644                            if (result < 0) {
645                                    throw new RuntimeException(
646                                            "Unable to set compliance mode to experimental");
647                            }
648    
649                            if (iStreamCoder.open(null, null) < 0) {
650                                    throw new RuntimeException("Unable to open coder");
651                            }
652                    }
653            }
654    
655            protected void prepareAudio(
656                            IAudioResampler[] iAudioResamplers,
657                            IAudioSamples[] inputIAudioSamples,
658                            IAudioSamples[] outputIAudioSamples, IStreamCoder inputIStreamCoder,
659                            IStreamCoder[] outputIStreamCoders, IContainer outputIContainer,
660                            IStream[] outputIStreams, ICodec.Type inputICodecType,
661                            String outputURL, int index)
662                    throws Exception {
663    
664                    ICodec iCodec = getAudioEncodingICodec(outputIContainer);
665    
666                    if (iCodec == null) {
667                            iCodec = ICodec.guessEncodingCodec(
668                                    null, null, outputURL, null, inputICodecType);
669                    }
670    
671                    if (iCodec == null) {
672                            throw new RuntimeException(
673                                    "Unable to determine " + inputICodecType + " encoder for " +
674                                            outputURL);
675                    }
676    
677                    IStream outputIStream = outputIContainer.addNewStream(iCodec);
678    
679                    outputIStreams[index] = outputIStream;
680    
681                    IStreamCoder outputIStreamCoder = outputIStream.getStreamCoder();
682    
683                    outputIStreamCoders[index] = outputIStreamCoder;
684    
685                    int bitRate = inputIStreamCoder.getBitRate();
686    
687                    if (_log.isInfoEnabled()) {
688                            _log.info("Original audio bitrate " + bitRate);
689                    }
690    
691                    bitRate = getAudioBitRate(iCodec, bitRate);
692    
693                    if (_log.isInfoEnabled()) {
694                            _log.info("Modified audio bitrate " + bitRate);
695                    }
696    
697                    outputIStreamCoder.setBitRate(bitRate);
698    
699                    int channels = getAudioEncodingChannels(
700                            outputIContainer, inputIStreamCoder.getChannels());
701    
702                    outputIStreamCoder.setChannels(channels);
703    
704                    outputIStreamCoder.setGlobalQuality(0);
705    
706                    Format sampleFormat = inputIStreamCoder.getSampleFormat();
707    
708                    if (_log.isInfoEnabled()) {
709                            _log.info(
710                                    "Original audio sample format " + sampleFormat.toString());
711                    }
712    
713                    sampleFormat = getAudioSampleFormat(iCodec, sampleFormat);
714    
715                    if (_log.isInfoEnabled()) {
716                            _log.info(
717                                    "Modified audio sample format " + sampleFormat.toString());
718                    }
719    
720                    outputIStreamCoder.setSampleFormat(sampleFormat);
721    
722                    outputIStreamCoder.setSampleRate(getAudioSampleRate());
723    
724                    iAudioResamplers[index] = createIAudioResampler(
725                            inputIStreamCoder, outputIStreamCoder);
726    
727                    inputIAudioSamples[index] = IAudioSamples.make(
728                            1024, inputIStreamCoder.getChannels(),
729                            inputIStreamCoder.getSampleFormat());
730                    outputIAudioSamples[index] = IAudioSamples.make(
731                            1024, outputIStreamCoder.getChannels(),
732                            outputIStreamCoder.getSampleFormat());
733            }
734    
735            protected IAudioSamples resampleAudio(
736                            IAudioResampler iAudioResampler, IAudioSamples inputIAudioSample,
737                            IAudioSamples resampledIAudioSample)
738                    throws Exception {
739    
740                    if ((iAudioResampler == null) ||
741                            (inputIAudioSample.getNumSamples() <= 0)) {
742    
743                            return inputIAudioSample;
744                    }
745    
746                    iAudioResampler.resample(
747                            resampledIAudioSample, inputIAudioSample,
748                            inputIAudioSample.getNumSamples());
749    
750                    return resampledIAudioSample;
751            }
752    
753            protected IVideoPicture resampleVideo(
754                            IVideoResampler iVideoResampler, IVideoPicture inputIVideoPicture,
755                            IVideoPicture resampledIVideoPicture)
756                    throws Exception {
757    
758                    if (iVideoResampler == null) {
759                            return inputIVideoPicture;
760                    }
761    
762                    if (iVideoResampler.resample(
763                                    resampledIVideoPicture, inputIVideoPicture) < 0) {
764    
765                            throw new RuntimeException("Unable to resample video");
766                    }
767    
768                    return resampledIVideoPicture;
769            }
770    
771            protected void rewind() throws Exception {
772                    IContainer inputIContainer = getInputIContainer();
773    
774                    if (inputIContainer == null) {
775                            return;
776                    }
777    
778                    int value = 0;
779    
780                    for (int i = 0; i < inputIContainer.getNumStreams(); i++) {
781                            IStream inputIStream = inputIContainer.getStream(i);
782    
783                            IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
784    
785                            if (inputIStreamCoder.getCodecType() !=
786                                            ICodec.Type.CODEC_TYPE_VIDEO) {
787    
788                                    continue;
789                            }
790    
791                            value = rewind(i);
792    
793                            if (value < 0) {
794                                    throw new RuntimeException("Error while seeking file");
795                            }
796    
797                            break;
798                    }
799            }
800    
801            protected int rewind(int index) throws Exception {
802                    IContainer inputIContainer = getInputIContainer();
803    
804                    if (inputIContainer == null) {
805                            return -1;
806                    }
807    
808                    int value = inputIContainer.seekKeyFrame(index, -1, 0);
809    
810                    if (value < 0) {
811                            throw new RuntimeException("Error while seeking file");
812                    }
813    
814                    return value;
815            }
816    
817            protected int seek(int index, long timeStamp) throws Exception {
818                    IContainer inputIContainer = getInputIContainer();
819    
820                    if (inputIContainer == null) {
821                            return -1;
822                    }
823    
824                    int value = inputIContainer.seekKeyFrame(index, timeStamp, 0);
825    
826                    if (value < 0) {
827                            throw new RuntimeException("Error while seeking file");
828                    }
829    
830                    return value;
831            }
832    
833            protected long seek(long timeStamp) throws Exception {
834                    IContainer inputIContainer = getInputIContainer();
835    
836                    if (inputIContainer == null) {
837                            return -1;
838                    }
839    
840                    int value = 0;
841    
842                    for (int i = 0; i < inputIContainer.getNumStreams(); i++) {
843                            IStream inputIStream = inputIContainer.getStream(i);
844    
845                            IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
846    
847                            if (inputIStreamCoder.getCodecType() !=
848                                            ICodec.Type.CODEC_TYPE_VIDEO) {
849    
850                                    continue;
851                            }
852    
853                            value = seek(i, timeStamp);
854    
855                            if (value < 0) {
856                                    throw new RuntimeException("Error while seeking file");
857                            }
858    
859                            break;
860                    }
861    
862                    return value;
863            }
864    
865            protected void updateAudioTimeStamp(
866                    IAudioSamples inputAudioSample, long timeStampOffset) {
867    
868                    if (inputAudioSample.getTimeStamp() != Global.NO_PTS) {
869                            inputAudioSample.setTimeStamp(
870                                    inputAudioSample.getTimeStamp() - timeStampOffset);
871                    }
872            }
873    
874            protected void updateVideoTimeStamp(
875                    IVideoPicture inputIVideoPicture, long timeStampOffset) {
876    
877                    if (inputIVideoPicture.getTimeStamp() != Global.NO_PTS) {
878                            inputIVideoPicture.setTimeStamp(
879                                    inputIVideoPicture.getTimeStamp() - timeStampOffset);
880                    }
881            }
882    
883            protected static final int AUDIO_BIT_RATE_DEFAULT = 64000;
884    
885            protected static final int AUDIO_BIT_RATE_MAX = 500000;
886    
887            protected static final int AUDIO_SAMPLE_RATE_DEFAULT = 44100;
888    
889            protected static final int AUDIO_SAMPLE_RATE_MAX = 192000;
890    
891            protected static final int DECODE_VIDEO_THUMBNAIL = 2;
892    
893            private static Log _log = LogFactoryUtil.getLog(LiferayConverter.class);
894    
895            private ConverterFactory.Type _converterFactoryType;
896            private IConverter _videoIConverter;
897    
898    }