001    /**
002     * Copyright (c) 2000-2011 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.ImageProcessorImpl;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    
021    import com.xuggle.ferry.RefCounted;
022    import com.xuggle.xuggler.Global;
023    import com.xuggle.xuggler.IAudioResampler;
024    import com.xuggle.xuggler.IAudioSamples.Format;
025    import com.xuggle.xuggler.IAudioSamples;
026    import com.xuggle.xuggler.ICodec;
027    import com.xuggle.xuggler.IContainer;
028    import com.xuggle.xuggler.IPacket;
029    import com.xuggle.xuggler.IPixelFormat;
030    import com.xuggle.xuggler.IRational;
031    import com.xuggle.xuggler.IStream;
032    import com.xuggle.xuggler.IStreamCoder;
033    import com.xuggle.xuggler.IVideoPicture;
034    import com.xuggle.xuggler.IVideoResampler;
035    import com.xuggle.xuggler.video.ConverterFactory;
036    import com.xuggle.xuggler.video.IConverter;
037    
038    import java.awt.image.BufferedImage;
039    import java.awt.image.RenderedImage;
040    
041    import java.io.File;
042    import java.io.FileOutputStream;
043    
044    import javax.imageio.ImageIO;
045    
046    /**
047     * @author Juan González
048     * @author Sergio González
049     * @author Brian Wing Shun Chan
050     * @author Alexander Chow
051     */
052    public abstract class LiferayConverter {
053    
054            public abstract void convert() throws Exception;
055    
056            protected void cleanUp(IPacket inputIPacket, IPacket outputIPacket) {
057                    if (inputIPacket != null) {
058                            inputIPacket.delete();
059                    }
060    
061                    if (outputIPacket != null) {
062                            outputIPacket.delete();
063                    }
064            }
065    
066            protected void cleanUp(
067                    IStreamCoder[] inputIStreamCoders, IStreamCoder[] outputIStreamCoders) {
068    
069                    if (inputIStreamCoders != null) {
070                            for (IStreamCoder iStreamCoder : inputIStreamCoders) {
071                                    if (iStreamCoder != null) {
072                                            iStreamCoder.close();
073                                    }
074                            }
075                    }
076    
077                    if (outputIStreamCoders != null) {
078                            for (IStreamCoder iStreamCoder : outputIStreamCoders) {
079                                    if (iStreamCoder != null) {
080                                            iStreamCoder.close();
081                                    }
082                            }
083                    }
084            }
085    
086            protected void cleanUp(
087                    RefCounted[] inputRefCountedArray, RefCounted[] outputRefCountedArray) {
088    
089                    if (inputRefCountedArray != null) {
090                            for (RefCounted refCounted : inputRefCountedArray) {
091                                    if (refCounted != null) {
092                                            refCounted.delete();
093                                    }
094                            }
095                    }
096    
097                    if (outputRefCountedArray != null) {
098                            for (RefCounted refCounted : outputRefCountedArray) {
099                                    if (refCounted != null) {
100                                            refCounted.delete();
101                                    }
102                            }
103                    }
104            }
105    
106            protected int countNonKeyAfterKey(
107                    IPacket inputIPacket, Boolean keyPacketFound, int nonKeyAfterKeyCount) {
108    
109                    if (inputIPacket.isKey()) {
110                            nonKeyAfterKeyCount = 0;
111                    }
112                    else if (keyPacketFound) {
113                            nonKeyAfterKeyCount++;
114                    }
115    
116                    return nonKeyAfterKeyCount;
117            }
118    
119            protected IAudioResampler createIAudioResampler(
120                            IStreamCoder inputIStreamCoder, IStreamCoder outputIStreamCoder)
121                    throws Exception {
122    
123                    IAudioResampler iAudioResampler = null;
124    
125                    Format inputSampleFormat = inputIStreamCoder.getSampleFormat();
126                    Format outputSampleFormat = outputIStreamCoder.getSampleFormat();
127    
128                    if ((inputIStreamCoder.getChannels() ==
129                                    outputIStreamCoder.getChannels()) &&
130                            (inputIStreamCoder.getSampleRate() ==
131                                    outputIStreamCoder.getSampleRate()) &&
132                            inputSampleFormat.equals(outputSampleFormat)) {
133    
134                            return iAudioResampler;
135                    }
136    
137                    iAudioResampler = IAudioResampler.make(
138                            outputIStreamCoder.getChannels(), inputIStreamCoder.getChannels(),
139                            outputIStreamCoder.getSampleRate(),
140                            inputIStreamCoder.getSampleRate(),
141                            outputIStreamCoder.getSampleFormat(),
142                            inputIStreamCoder.getSampleFormat());
143    
144                    if (iAudioResampler == null) {
145                            throw new RuntimeException("Audio resampling is not supported");
146                    }
147    
148                    return iAudioResampler;
149            }
150    
151            protected IVideoResampler createIVideoResampler(
152                            IStreamCoder inputIStreamCoder, IStreamCoder outputIStreamCoder,
153                            int height, int width)
154                    throws Exception {
155    
156                    IVideoResampler iVideoResampler = null;
157    
158                    IPixelFormat.Type inputIPixelFormatType =
159                            inputIStreamCoder.getPixelType();
160                    IPixelFormat.Type outputIPixelFormatType =
161                            outputIStreamCoder.getPixelType();
162    
163                    if ((height == inputIStreamCoder.getHeight()) &&
164                            (width == inputIStreamCoder.getWidth()) &&
165                            inputIPixelFormatType.equals(outputIPixelFormatType)) {
166    
167                            return iVideoResampler;
168                    }
169    
170                    iVideoResampler = IVideoResampler.make(
171                            width, height, outputIStreamCoder.getPixelType(),
172                            inputIStreamCoder.getWidth(), inputIStreamCoder.getHeight(),
173                            inputIStreamCoder.getPixelType());
174    
175                    if (iVideoResampler == null) {
176                            throw new RuntimeException("Video resampling is not supported");
177                    }
178    
179                    return iVideoResampler;
180            }
181    
182            protected void decodeAudio(
183                            IAudioResampler iAudioResampler, IAudioSamples inputIAudioSample,
184                            IAudioSamples resampledIAudioSample, IPacket inputIPacket,
185                            IPacket outputIPacket, IStreamCoder inputIStreamCoder,
186                            IStreamCoder outputIStreamCoder, IContainer outputIContainer,
187                            int currentPacketSize, int previousPacketSize, int streamIndex,
188                            long timeStampOffset)
189                    throws Exception {
190    
191                    int offset = 0;
192    
193                    while (offset < inputIPacket.getSize()) {
194                            boolean stopDecoding = false;
195    
196                            int value = inputIStreamCoder.decodeAudio(
197                                    inputIAudioSample, inputIPacket, offset);
198    
199                            if (value <= 0) {
200                                    if ((previousPacketSize == currentPacketSize) &&
201                                            (previousPacketSize != -1)) {
202    
203                                            throw new RuntimeException(
204                                                    "Unable to decode audio stream " + streamIndex);
205                                    }
206                                    else {
207                                            stopDecoding = true;
208                                    }
209                            }
210    
211                            updateAudioTimeStamp(inputIAudioSample, timeStampOffset);
212    
213                            offset += value;
214    
215                            IAudioSamples outputIAudioSample = resampleAudio(
216                                    iAudioResampler, inputIAudioSample, resampledIAudioSample);
217    
218                            encodeAudio(
219                                    outputIStreamCoder, outputIPacket, outputIAudioSample,
220                                    outputIContainer);
221    
222                            if (stopDecoding) {
223                                    if (_log.isDebugEnabled()) {
224                                            _log.debug("Stop decoding audio stream " + streamIndex);
225                                    }
226    
227                                    break;
228                            }
229                    }
230            }
231    
232            protected int decodeVideo(
233                            IVideoResampler iVideoResampler, IVideoPicture inputIVideoPicture,
234                            IVideoPicture resampledIVideoPicture, IPacket inputIPacket,
235                            IPacket outputIPacket, IStreamCoder inputIStreamCoder,
236                            IStreamCoder outputIStreamCoder, IContainer outputIContainer,
237                            File thumbnailFile, String thumbnailExtension, int thumbnailHeight,
238                            int thumbnailWidth, long timeStampOffset)
239                    throws Exception {
240    
241                    int offset = 0;
242    
243                    boolean stopDecoding = false;
244    
245                    while (offset < inputIPacket.getSize()) {
246                            int value = inputIStreamCoder.decodeVideo(
247                                    inputIVideoPicture, inputIPacket, offset);
248    
249                            if (value <= 0) {
250                                    return value;
251                            }
252    
253                            updateVideoTimeStamp(inputIVideoPicture, timeStampOffset);
254    
255                            offset += value;
256    
257                            // Workaround for FFmpeg bug. See
258                            // http://comments.gmane.org/gmane.comp.video.ffmpeg.devel/135657
259    
260                            ICodec.ID iCodecID = inputIStreamCoder.getCodecID();
261    
262                            if (iCodecID.equals(ICodec.ID.CODEC_ID_MJPEG)) {
263                                    stopDecoding = true;
264                            }
265    
266                            if (!inputIVideoPicture.isComplete()) {
267                                    if (stopDecoding) {
268                                            return 1;
269                                    }
270                                    else {
271                                            continue;
272                                    }
273                            }
274    
275                            if (thumbnailFile != null) {
276                                    BufferedImage bufferedImage = null;
277    
278                                    if (_converterFactoryType == null) {
279                                            _converterFactoryType =
280                                                    ConverterFactory.findRegisteredConverter(
281                                                            ConverterFactory.XUGGLER_BGR_24);
282                                    }
283    
284                                    if (_converterFactoryType == null) {
285                                            throw new UnsupportedOperationException(
286                                                    "No converter found for " +
287                                                            ConverterFactory.XUGGLER_BGR_24);
288                                    }
289    
290                                    if (_videoIConverter == null) {
291                                            _videoIConverter = ConverterFactory.createConverter(
292                                                    _converterFactoryType.getDescriptor(),
293                                                    inputIVideoPicture);
294                                    }
295    
296                                    bufferedImage = _videoIConverter.toImage(inputIVideoPicture);
297    
298                                    thumbnailFile.createNewFile();
299    
300                                    ImageProcessorImpl imageProcessorImpl =
301                                            ImageProcessorImpl.getInstance();
302    
303                                    RenderedImage renderedImage = imageProcessorImpl.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[] outputIStreamCoders, IContainer outputIContainer) {
383    
384                    for (IStreamCoder outputIStreamCoder : outputIStreamCoders) {
385                            if (outputIStreamCoder == null) {
386                                    continue;
387                            }
388    
389                            IPacket iPacket = IPacket.make();
390    
391                            flush(outputIStreamCoder, outputIContainer, iPacket);
392    
393                            while (iPacket.isComplete()) {
394                                    flush(outputIStreamCoder, outputIContainer, iPacket);
395                            }
396                    }
397            }
398    
399            protected void flush(
400                    IStreamCoder outputIStreamCoder, IContainer outputIContainer,
401                    IPacket iPacket) {
402    
403                    if (outputIStreamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) {
404                            outputIStreamCoder.encodeAudio(iPacket, null, 0);
405                    }
406                    else {
407                            outputIStreamCoder.encodeVideo(iPacket, null, 0);
408                    }
409    
410                    if (iPacket.isComplete()) {
411                            outputIContainer.writePacket(iPacket, true);
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    }