001    /**
002     * Copyright (c) 2000-2012 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    
022    import com.xuggle.ferry.RefCounted;
023    import com.xuggle.xuggler.Global;
024    import com.xuggle.xuggler.IAudioResampler;
025    import com.xuggle.xuggler.IAudioSamples.Format;
026    import com.xuggle.xuggler.IAudioSamples;
027    import com.xuggle.xuggler.ICodec;
028    import com.xuggle.xuggler.IContainer;
029    import com.xuggle.xuggler.IPacket;
030    import com.xuggle.xuggler.IPixelFormat;
031    import com.xuggle.xuggler.IRational;
032    import com.xuggle.xuggler.IStream;
033    import com.xuggle.xuggler.IStreamCoder;
034    import com.xuggle.xuggler.IVideoPicture;
035    import com.xuggle.xuggler.IVideoResampler;
036    import com.xuggle.xuggler.video.ConverterFactory;
037    import com.xuggle.xuggler.video.IConverter;
038    
039    import java.awt.image.BufferedImage;
040    import java.awt.image.RenderedImage;
041    
042    import java.io.File;
043    import java.io.FileOutputStream;
044    
045    import javax.imageio.ImageIO;
046    
047    /**
048     * @author Juan González
049     * @author Sergio González
050     * @author Brian Wing Shun Chan
051     * @author Alexander Chow
052     */
053    public abstract class LiferayConverter {
054    
055            public abstract void convert() throws Exception;
056    
057            protected void cleanUp(IPacket inputIPacket, IPacket outputIPacket) {
058                    if (inputIPacket != null) {
059                            inputIPacket.delete();
060                    }
061    
062                    if (outputIPacket != null) {
063                            outputIPacket.delete();
064                    }
065            }
066    
067            protected void cleanUp(
068                    IStreamCoder[] inputIStreamCoders, IStreamCoder[] outputIStreamCoders) {
069    
070                    if (inputIStreamCoders != null) {
071                            for (IStreamCoder iStreamCoder : inputIStreamCoders) {
072                                    if (iStreamCoder != null) {
073                                            iStreamCoder.close();
074                                    }
075                            }
076                    }
077    
078                    if (outputIStreamCoders != null) {
079                            for (IStreamCoder iStreamCoder : outputIStreamCoders) {
080                                    if (iStreamCoder != null) {
081                                            iStreamCoder.close();
082                                    }
083                            }
084                    }
085            }
086    
087            protected void cleanUp(
088                    RefCounted[] inputRefCountedArray, RefCounted[] outputRefCountedArray) {
089    
090                    if (inputRefCountedArray != null) {
091                            for (RefCounted refCounted : inputRefCountedArray) {
092                                    if (refCounted != null) {
093                                            refCounted.delete();
094                                    }
095                            }
096                    }
097    
098                    if (outputRefCountedArray != null) {
099                            for (RefCounted refCounted : outputRefCountedArray) {
100                                    if (refCounted != null) {
101                                            refCounted.delete();
102                                    }
103                            }
104                    }
105            }
106    
107            protected int countNonKeyAfterKey(
108                    IPacket inputIPacket, Boolean keyPacketFound, int nonKeyAfterKeyCount) {
109    
110                    if (inputIPacket.isKey()) {
111                            nonKeyAfterKeyCount = 0;
112                    }
113                    else if (keyPacketFound) {
114                            nonKeyAfterKeyCount++;
115                    }
116    
117                    return nonKeyAfterKeyCount;
118            }
119    
120            protected IAudioResampler createIAudioResampler(
121                            IStreamCoder inputIStreamCoder, IStreamCoder outputIStreamCoder)
122                    throws Exception {
123    
124                    IAudioResampler iAudioResampler = null;
125    
126                    Format inputSampleFormat = inputIStreamCoder.getSampleFormat();
127                    Format outputSampleFormat = outputIStreamCoder.getSampleFormat();
128    
129                    if ((inputIStreamCoder.getChannels() ==
130                                    outputIStreamCoder.getChannels()) &&
131                            (inputIStreamCoder.getSampleRate() ==
132                                    outputIStreamCoder.getSampleRate()) &&
133                            inputSampleFormat.equals(outputSampleFormat)) {
134    
135                            return iAudioResampler;
136                    }
137    
138                    iAudioResampler = IAudioResampler.make(
139                            outputIStreamCoder.getChannels(), inputIStreamCoder.getChannels(),
140                            outputIStreamCoder.getSampleRate(),
141                            inputIStreamCoder.getSampleRate(),
142                            outputIStreamCoder.getSampleFormat(),
143                            inputIStreamCoder.getSampleFormat());
144    
145                    if (iAudioResampler == null) {
146                            throw new RuntimeException("Audio resampling is not supported");
147                    }
148    
149                    return iAudioResampler;
150            }
151    
152            protected IVideoResampler createIVideoResampler(
153                            IStreamCoder inputIStreamCoder, IStreamCoder outputIStreamCoder,
154                            int height, int width)
155                    throws Exception {
156    
157                    IVideoResampler iVideoResampler = null;
158    
159                    IPixelFormat.Type inputIPixelFormatType =
160                            inputIStreamCoder.getPixelType();
161                    IPixelFormat.Type outputIPixelFormatType =
162                            outputIStreamCoder.getPixelType();
163    
164                    if ((height == inputIStreamCoder.getHeight()) &&
165                            (width == inputIStreamCoder.getWidth()) &&
166                            inputIPixelFormatType.equals(outputIPixelFormatType)) {
167    
168                            return iVideoResampler;
169                    }
170    
171                    iVideoResampler = IVideoResampler.make(
172                            width, height, outputIStreamCoder.getPixelType(),
173                            inputIStreamCoder.getWidth(), inputIStreamCoder.getHeight(),
174                            inputIStreamCoder.getPixelType());
175    
176                    if (iVideoResampler == null) {
177                            throw new RuntimeException("Video resampling is not supported");
178                    }
179    
180                    return iVideoResampler;
181            }
182    
183            protected void decodeAudio(
184                            IAudioResampler iAudioResampler, IAudioSamples inputIAudioSample,
185                            IAudioSamples resampledIAudioSample, IPacket inputIPacket,
186                            IPacket outputIPacket, IStreamCoder inputIStreamCoder,
187                            IStreamCoder outputIStreamCoder, IContainer outputIContainer,
188                            int currentPacketSize, int previousPacketSize, int streamIndex,
189                            long timeStampOffset)
190                    throws Exception {
191    
192                    int offset = 0;
193    
194                    while (offset < inputIPacket.getSize()) {
195                            boolean stopDecoding = false;
196    
197                            int value = inputIStreamCoder.decodeAudio(
198                                    inputIAudioSample, inputIPacket, offset);
199    
200                            if (value <= 0) {
201                                    if ((previousPacketSize == currentPacketSize) &&
202                                            (previousPacketSize != -1)) {
203    
204                                            throw new RuntimeException(
205                                                    "Unable to decode audio stream " + streamIndex);
206                                    }
207                                    else {
208                                            stopDecoding = true;
209                                    }
210                            }
211    
212                            updateAudioTimeStamp(inputIAudioSample, timeStampOffset);
213    
214                            offset += value;
215    
216                            IAudioSamples outputIAudioSample = resampleAudio(
217                                    iAudioResampler, inputIAudioSample, resampledIAudioSample);
218    
219                            encodeAudio(
220                                    outputIStreamCoder, outputIPacket, outputIAudioSample,
221                                    outputIContainer);
222    
223                            if (stopDecoding) {
224                                    if (_log.isDebugEnabled()) {
225                                            _log.debug("Stop decoding audio stream " + streamIndex);
226                                    }
227    
228                                    break;
229                            }
230                    }
231            }
232    
233            protected int decodeVideo(
234                            IVideoResampler iVideoResampler, IVideoPicture inputIVideoPicture,
235                            IVideoPicture resampledIVideoPicture, IPacket inputIPacket,
236                            IPacket outputIPacket, IStreamCoder inputIStreamCoder,
237                            IStreamCoder outputIStreamCoder, IContainer outputIContainer,
238                            File thumbnailFile, String thumbnailExtension, int thumbnailHeight,
239                            int thumbnailWidth, long timeStampOffset)
240                    throws Exception {
241    
242                    int offset = 0;
243    
244                    boolean stopDecoding = false;
245    
246                    while (offset < inputIPacket.getSize()) {
247                            int value = inputIStreamCoder.decodeVideo(
248                                    inputIVideoPicture, inputIPacket, offset);
249    
250                            if (value <= 0) {
251                                    return value;
252                            }
253    
254                            updateVideoTimeStamp(inputIVideoPicture, timeStampOffset);
255    
256                            offset += value;
257    
258                            // Workaround for FFmpeg bug. See
259                            // http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/135657
260    
261                            ICodec.ID iCodecID = inputIStreamCoder.getCodecID();
262    
263                            if (iCodecID.equals(ICodec.ID.CODEC_ID_MJPEG)) {
264                                    stopDecoding = true;
265                            }
266    
267                            if (!inputIVideoPicture.isComplete()) {
268                                    if (stopDecoding) {
269                                            return 1;
270                                    }
271                                    else {
272                                            continue;
273                                    }
274                            }
275    
276                            if (thumbnailFile != null) {
277                                    BufferedImage bufferedImage = null;
278    
279                                    if (_converterFactoryType == null) {
280                                            _converterFactoryType =
281                                                    ConverterFactory.findRegisteredConverter(
282                                                            ConverterFactory.XUGGLER_BGR_24);
283                                    }
284    
285                                    if (_converterFactoryType == null) {
286                                            throw new UnsupportedOperationException(
287                                                    "No converter found for " +
288                                                            ConverterFactory.XUGGLER_BGR_24);
289                                    }
290    
291                                    if (_videoIConverter == null) {
292                                            _videoIConverter = ConverterFactory.createConverter(
293                                                    _converterFactoryType.getDescriptor(),
294                                                    inputIVideoPicture);
295                                    }
296    
297                                    bufferedImage = _videoIConverter.toImage(inputIVideoPicture);
298    
299                                    thumbnailFile.createNewFile();
300    
301                                    ImageTool imageTool = ImageToolImpl.getInstance();
302    
303                                    RenderedImage renderedImage = imageTool.scale(
304                                            bufferedImage, thumbnailHeight, thumbnailWidth);
305    
306                                    ImageIO.write(
307                                            renderedImage, thumbnailExtension,
308                                            new FileOutputStream(thumbnailFile));
309    
310                                    return DECODE_VIDEO_THUMBNAIL;
311                            }
312    
313                            if ((outputIStreamCoder != null) && (outputIContainer != null)) {
314                                    IVideoPicture outputIVideoPicture = resampleVideo(
315                                            iVideoResampler, inputIVideoPicture,
316                                            resampledIVideoPicture);
317    
318                                    outputIVideoPicture.setQuality(0);
319    
320                                    encodeVideo(
321                                            outputIStreamCoder, outputIVideoPicture, outputIPacket,
322                                            outputIContainer);
323                            }
324    
325                            if (stopDecoding) {
326                                    break;
327                            }
328                    }
329    
330                    return 1;
331            }
332    
333            protected void encodeAudio(
334                            IStreamCoder outputIStreamCoder, IPacket outputIPacket,
335                            IAudioSamples outputIAudioSample, IContainer outputIContainer)
336                    throws Exception {
337    
338                    int consumedSamplesCount = 0;
339    
340                    while (consumedSamplesCount < outputIAudioSample.getNumSamples()) {
341                            int value = outputIStreamCoder.encodeAudio(
342                                    outputIPacket, outputIAudioSample, consumedSamplesCount);
343    
344                            if (value <= 0) {
345                                    throw new RuntimeException("Unable to encode audio");
346                            }
347    
348                            consumedSamplesCount += value;
349    
350                            if (outputIPacket.isComplete()) {
351                                    value = outputIContainer.writePacket(outputIPacket, true);
352    
353                                    if (value < 0) {
354                                            throw new RuntimeException("Unable to write audio packet");
355                                    }
356                            }
357                    }
358            }
359    
360            protected void encodeVideo(
361                            IStreamCoder outputIStreamCoder, IVideoPicture outputIVideoPicture,
362                            IPacket outputIPacket, IContainer outputIContainer)
363                    throws Exception {
364    
365                    int value = outputIStreamCoder.encodeVideo(
366                            outputIPacket, outputIVideoPicture, 0);
367    
368                    if (value < 0) {
369                            throw new RuntimeException("Unable to encode video");
370                    }
371    
372                    if (outputIPacket.isComplete()) {
373                            value = outputIContainer.writePacket(outputIPacket, true);
374    
375                            if (value < 0) {
376                                    throw new RuntimeException("Unable to write video packet");
377                            }
378                    }
379            }
380    
381            protected void flush(
382                    IStreamCoder outputIStreamCoder, IContainer outputIContainer,
383                    IPacket iPacket) {
384    
385                    if (outputIStreamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
386                            outputIStreamCoder.encodeAudio(iPacket, null, 0);
387                    }
388                    else {
389                            outputIStreamCoder.encodeVideo(iPacket, null, 0);
390                    }
391    
392                    if (iPacket.isComplete()) {
393                            outputIContainer.writePacket(iPacket, true);
394                    }
395            }
396    
397            protected void flush(
398                    IStreamCoder[] outputIStreamCoders, IContainer outputIContainer) {
399    
400                    for (IStreamCoder outputIStreamCoder : outputIStreamCoders) {
401                            if (outputIStreamCoder == null) {
402                                    continue;
403                            }
404    
405                            IPacket iPacket = IPacket.make();
406    
407                            flush(outputIStreamCoder, outputIContainer, iPacket);
408    
409                            while (iPacket.isComplete()) {
410                                    flush(outputIStreamCoder, outputIContainer, iPacket);
411                            }
412                    }
413            }
414    
415            protected int getAudioEncodingChannels(
416                    IContainer outputIContainer, int channels) {
417    
418                    if ((channels == 0) || (channels > 2)) {
419                            channels = 2;
420                    }
421    
422                    return channels;
423            }
424    
425            protected ICodec getAudioEncodingICodec(IContainer outputIContainer) {
426                    return null;
427            }
428    
429            protected abstract IContainer getInputIContainer();
430    
431            protected long getSeekTimeStamp(int percentage) throws Exception {
432                    IContainer inputIContainer = getInputIContainer();
433    
434                    long seekTimeStamp = -1;
435    
436                    long videoSeconds = inputIContainer.getDuration() / 1000000L;
437    
438                    long seekSeconds = ((videoSeconds * percentage) / 100L);
439    
440                    for (int i = 0; i < inputIContainer.getNumStreams(); i++) {
441                            IStream inputIStream = inputIContainer.getStream(i);
442    
443                            IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
444    
445                            if (inputIStreamCoder.getCodecType() !=
446                                            ICodec.Type.CODEC_TYPE_VIDEO) {
447    
448                                    continue;
449                            }
450    
451                            IRational iRational = inputIStream.getTimeBase();
452    
453                            long timeStampOffset =
454                                    iRational.getDenominator() / iRational.getNumerator() *
455                                            seekSeconds;
456    
457                            seekTimeStamp = inputIContainer.getStartTime() + timeStampOffset;
458    
459                            break;
460                    }
461    
462                    return seekTimeStamp;
463            }
464    
465            protected long getStreamTimeStampOffset(IStream iStream) {
466                    long timeStampOffset = 0;
467    
468                    if ((iStream.getStartTime() != Global.NO_PTS) &&
469                            (iStream.getStartTime() > 0) && (iStream.getTimeBase() != null)) {
470    
471                            IRational iRational = IRational.make(
472                                    1, (int)Global.DEFAULT_PTS_PER_SECOND);
473    
474                            timeStampOffset = iRational.rescale(
475                                    iStream.getStartTime(), iStream.getTimeBase());
476                    }
477    
478                    return timeStampOffset;
479            }
480    
481            protected boolean isKeyPacketFound(
482                    IPacket inputIPacket, boolean keyPacketFound) {
483    
484                    if (inputIPacket.isKey() && !keyPacketFound) {
485                            return true;
486                    }
487    
488                    return keyPacketFound;
489            }
490    
491            protected boolean isStartDecoding(
492                    IPacket inputIPacket, IStreamCoder inputIStreamCoder,
493                    boolean keyPacketFound, int nonKeyAfterKeyCount,
494                    boolean onlyDecodeKeyPackets) {
495    
496                    if (onlyDecodeKeyPackets && !inputIPacket.isKey()) {
497                            return false;
498                    }
499    
500                    ICodec.ID iCodecID = inputIStreamCoder.getCodecID();
501    
502                    if (iCodecID.equals(ICodec.ID.CODEC_ID_MJPEG)) {
503                            return true;
504                    }
505                    else if (iCodecID.equals(ICodec.ID.CODEC_ID_MPEG2VIDEO) ||
506                                     iCodecID.equals(ICodec.ID.CODEC_ID_THEORA)) {
507    
508                            if (nonKeyAfterKeyCount != 1) {
509                                    return true;
510                            }
511    
512                            return false;
513                    }
514    
515                    return keyPacketFound;
516            }
517    
518            protected void openContainer(
519                            IContainer iContainer, String url, boolean writeContainer)
520                    throws Exception {
521    
522                    int value = 0;
523    
524                    if (writeContainer) {
525                            value = iContainer.open(url, IContainer.Type.WRITE, null);
526                    }
527                    else {
528                            value = iContainer.open(url, IContainer.Type.READ, null);
529                    }
530    
531                    if (value < 0) {
532                            if (writeContainer) {
533                                    throw new RuntimeException("Unable to open output URL");
534                            }
535                            else {
536                                    throw new RuntimeException("Unable to open input URL");
537                            }
538                    }
539            }
540    
541            protected void openStreamCoder(IStreamCoder iStreamCoder)
542                    throws Exception {
543    
544                    if ((iStreamCoder != null) &&
545                            (iStreamCoder.getCodecType() != ICodec.Type.CODEC_TYPE_UNKNOWN)) {
546    
547                            if (iStreamCoder.open() < 0) {
548                                    throw new RuntimeException("Unable to open coder");
549                            }
550                    }
551            }
552    
553            protected void prepareAudio(
554                            IAudioResampler[] iAudioResamplers,
555                            IAudioSamples[] inputIAudioSamples,
556                            IAudioSamples[] outputIAudioSamples, IStreamCoder inputIStreamCoder,
557                            IStreamCoder[] outputIStreamCoders, IContainer outputIContainer,
558                            IStream[] outputIStreams, ICodec.Type inputICodecType,
559                            String outputURL, int index)
560                    throws Exception {
561    
562                    IStream outputIStream = outputIContainer.addNewStream(index);
563    
564                    outputIStreams[index] = outputIStream;
565    
566                    IStreamCoder outputIStreamCoder = outputIStream.getStreamCoder();
567    
568                    outputIStreamCoders[index] = outputIStreamCoder;
569    
570                    int bitRate = inputIStreamCoder.getBitRate();
571    
572                    if (_log.isInfoEnabled()) {
573                            _log.info("Original audio bitrate " + bitRate);
574                    }
575    
576                    if (bitRate == 0) {
577                            bitRate = _AUDIO_BIT_RATE_DEFAULT;
578                    }
579    
580                    if (_log.isInfoEnabled()) {
581                            _log.info("Modified audio bitrate " + bitRate);
582                    }
583    
584                    outputIStreamCoder.setBitRate(bitRate);
585    
586                    int channels = getAudioEncodingChannels(
587                            outputIContainer, inputIStreamCoder.getChannels());
588    
589                    outputIStreamCoder.setChannels(channels);
590    
591                    ICodec iCodec = getAudioEncodingICodec(outputIContainer);
592    
593                    if (iCodec == null) {
594                            iCodec = ICodec.guessEncodingCodec(
595                                    null, null, outputURL, null, inputICodecType);
596                    }
597    
598                    if (iCodec == null) {
599                            throw new RuntimeException(
600                                    "Unable to determine " + inputICodecType + " encoder for " +
601                                            outputURL);
602                    }
603    
604                    outputIStreamCoder.setCodec(iCodec);
605    
606                    outputIStreamCoder.setGlobalQuality(0);
607    
608                    outputIStreamCoder.setSampleRate(_AUDIO_SAMPLE_RATE_DEFAULT);
609    
610                    iAudioResamplers[index] = createIAudioResampler(
611                            inputIStreamCoder, outputIStreamCoder);
612    
613                    inputIAudioSamples[index] = IAudioSamples.make(
614                            1024, inputIStreamCoder.getChannels());
615                    outputIAudioSamples[index] = IAudioSamples.make(
616                            1024, outputIStreamCoder.getChannels());
617            }
618    
619            protected IAudioSamples resampleAudio(
620                            IAudioResampler iAudioResampler, IAudioSamples inputIAudioSample,
621                            IAudioSamples resampledIAudioSample)
622                    throws Exception {
623    
624                    if ((iAudioResampler == null) ||
625                            (inputIAudioSample.getNumSamples() <= 0)) {
626    
627                            return inputIAudioSample;
628                    }
629    
630                    iAudioResampler.resample(
631                            resampledIAudioSample, inputIAudioSample,
632                            inputIAudioSample.getNumSamples());
633    
634                    return resampledIAudioSample;
635            }
636    
637            protected IVideoPicture resampleVideo(
638                            IVideoResampler iVideoResampler, IVideoPicture inputIVideoPicture,
639                            IVideoPicture resampledIVideoPicture)
640                    throws Exception {
641    
642                    if (iVideoResampler == null) {
643                            return inputIVideoPicture;
644                    }
645    
646                    if (iVideoResampler.resample(
647                                    resampledIVideoPicture, inputIVideoPicture) < 0) {
648    
649                            throw new RuntimeException("Unable to resample video");
650                    }
651    
652                    return resampledIVideoPicture;
653            }
654    
655            protected void rewind() throws Exception {
656                    IContainer inputIContainer = getInputIContainer();
657    
658                    if (inputIContainer == null) {
659                            return;
660                    }
661    
662                    int value = 0;
663    
664                    for (int i = 0; i < inputIContainer.getNumStreams(); i++) {
665                            IStream inputIStream = inputIContainer.getStream(i);
666    
667                            IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
668    
669                            if (inputIStreamCoder.getCodecType() !=
670                                            ICodec.Type.CODEC_TYPE_VIDEO) {
671    
672                                    continue;
673                            }
674    
675                            value = rewind(i);
676    
677                            if (value < 0) {
678                                    throw new RuntimeException("Error while seeking file");
679                            }
680    
681                            break;
682                    }
683            }
684    
685            protected int rewind(int index) throws Exception {
686                    IContainer inputIContainer = getInputIContainer();
687    
688                    if (inputIContainer == null) {
689                            return -1;
690                    }
691    
692                    int value = inputIContainer.seekKeyFrame(index, -1, 0);
693    
694                    if (value < 0) {
695                            throw new RuntimeException("Error while seeking file");
696                    }
697    
698                    return value;
699            }
700    
701            protected int seek(int index, long timeStamp) throws Exception {
702                    IContainer inputIContainer = getInputIContainer();
703    
704                    if (inputIContainer == null) {
705                            return -1;
706                    }
707    
708                    int value = inputIContainer.seekKeyFrame(index, timeStamp, 0);
709    
710                    if (value < 0) {
711                            throw new RuntimeException("Error while seeking file");
712                    }
713    
714                    return value;
715            }
716    
717            protected long seek(long timeStamp) throws Exception {
718                    IContainer inputIContainer = getInputIContainer();
719    
720                    if (inputIContainer == null) {
721                            return -1;
722                    }
723    
724                    int value = 0;
725    
726                    for (int i = 0; i < inputIContainer.getNumStreams(); i++) {
727                            IStream inputIStream = inputIContainer.getStream(i);
728    
729                            IStreamCoder inputIStreamCoder = inputIStream.getStreamCoder();
730    
731                            if (inputIStreamCoder.getCodecType() !=
732                                            ICodec.Type.CODEC_TYPE_VIDEO) {
733    
734                                    continue;
735                            }
736    
737                            value = seek(i, timeStamp);
738    
739                            if (value < 0) {
740                                    throw new RuntimeException("Error while seeking file");
741                            }
742    
743                            break;
744                    }
745    
746                    return value;
747            }
748    
749            protected void updateAudioTimeStamp(
750                    IAudioSamples inputAudioSample, long timeStampOffset) {
751    
752                    if (inputAudioSample.getTimeStamp() != Global.NO_PTS) {
753                            inputAudioSample.setTimeStamp(
754                                    inputAudioSample.getTimeStamp() - timeStampOffset);
755                    }
756            }
757    
758            protected void updateVideoTimeStamp(
759                    IVideoPicture inputIVideoPicture, long timeStampOffset) {
760    
761                    if (inputIVideoPicture.getTimeStamp() != Global.NO_PTS) {
762                            inputIVideoPicture.setTimeStamp(
763                                    inputIVideoPicture.getTimeStamp() - timeStampOffset);
764                    }
765            }
766    
767            protected static final int DECODE_VIDEO_THUMBNAIL = 2;
768    
769            private static final int _AUDIO_BIT_RATE_DEFAULT = 64000;
770    
771            private static final int _AUDIO_SAMPLE_RATE_DEFAULT = 44100;
772    
773            private static Log _log = LogFactoryUtil.getLog(LiferayConverter.class);
774    
775            private ConverterFactory.Type _converterFactoryType;
776            private IConverter _videoIConverter;
777    
778    }