From 06861e165874093ab0fc27d76c7c595244182881 Mon Sep 17 00:00:00 2001 From: Ziver Koc Date: Wed, 31 Oct 2012 19:34:46 +0000 Subject: [PATCH] Added frame grabber --- src/zall/ZalleryTranscoder.java | 54 ++++--- src/zall/util/test/Transcoder.java | 221 ++++++++++++++++++----------- 2 files changed, 171 insertions(+), 104 deletions(-) diff --git a/src/zall/ZalleryTranscoder.java b/src/zall/ZalleryTranscoder.java index bb64a5b..3a036b4 100644 --- a/src/zall/ZalleryTranscoder.java +++ b/src/zall/ZalleryTranscoder.java @@ -1,12 +1,14 @@ package zall; import java.io.File; +import java.io.IOException; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.logging.Level; import java.util.logging.Logger; +import javax.imageio.ImageIO; import javax.servlet.ServletConfig; import javax.servlet.http.HttpServlet; @@ -25,6 +27,8 @@ import com.xuggle.xuggler.ICodec; import com.xuggle.xuggler.IStreamCoder; import com.xuggle.xuggler.IVideoPicture; import com.xuggle.xuggler.IVideoResampler; +import com.xuggle.xuggler.video.ConverterFactory; +import com.xuggle.xuggler.video.IConverter; import zall.bean.Media.Size; import zall.bean.Video; @@ -127,7 +131,7 @@ public class ZalleryTranscoder extends HttpServlet{ ///////////// Start Transcoding // create a media reader IMediaReader reader = ToolFactory.makeReader( originalFile.getPath() ); - reader.addListener(new FrameGrabListener(reader, 0.2)); + reader.addListener(new FrameGrabListener(reader, smallFile, 0.2)); reader.addListener(new ProgressListener(reader)); VideoTranscoderListener converter = new VideoTranscoderListener(640, 360); @@ -221,28 +225,22 @@ class VideoTranscoderListener extends MediaToolAdapter{ private IVideoResampler videoResampler = null; private IAudioResampler audioResampler = null; - IMediaWriter writer; - @Override public void onAddStream(IAddStreamEvent event) { int streamIndex = event.getStreamIndex(); IStreamCoder streamCoder = event.getSource().getContainer().getStream(streamIndex).getStreamCoder(); if (streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) { - //writer.addAudioStream(streamIndex, streamIndex, ICodec.ID.CODEC_ID_AAC, 2, 44100); streamCoder.setSampleRate( 44100 ); - /* - streamCoder.setCodec( ICodec.ID.CODEC_ID_AAC ); - streamCoder.setBitRate( 128 ); - */ + //streamCoder.setCodec( ICodec.ID.CODEC_ID_AAC ); + //streamCoder.setBitRate( 128 ); } else if (streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) { - //writer.addVideoStream(streamIndex, streamIndex, ICodec.ID.CODEC_ID_H264, VIDEO_WIDTH, VIDEO_HEIGHT); streamCoder.setWidth( width ); streamCoder.setHeight( height ); - - /* - streamCoder.setCodec(ICodec.findEncodingCodec( ICodec.ID.CODEC_ID_H264 )); - streamCoder.setBitRate( 500000 ); + + //streamCoder.setCodec(ICodec.findEncodingCodec( ICodec.ID.CODEC_ID_H264 )); + //streamCoder.setBitRate( 800000 ); + /* int retval = Configuration.configure("/usr/local/xuggler/share/ffmpeg/libx264-superfast.ffpreset", streamCoder); if (retval<0) throw new RuntimeException("cound not cofigure coder from preset file"); @@ -323,21 +321,38 @@ class ProgressListener extends MediaToolAdapter { class FrameGrabListener extends MediaToolAdapter { private long totalLength; private long grabAt; + private File outputFile; - public FrameGrabListener(IMediaReader reader, double at) { + public FrameGrabListener(IMediaReader reader, File outputFile, double at) { if( !reader.isOpen() ) reader.open(); // read container this.totalLength = reader.getContainer().getDuration(); + this.outputFile = outputFile; setAtProgress(at); } @Override public void onVideoPicture(IVideoPictureEvent event) { - long currentLength = event.getTimeStamp(); - - if( grabAt > 0 && currentLength > grabAt ){ - System.out.println("\nScreanshoot!!!"); - grabAt = -1; + try{ + long currentLength = event.getTimeStamp(); + + if( grabAt > 0 && currentLength > grabAt ){ + System.out.println("\nScreanshoot!!!"); + + ConverterFactory.Type mConverterType = ConverterFactory.findRegisteredConverter( + ConverterFactory.XUGGLER_BGR_24); + IConverter mVideoConverter = ConverterFactory.createConverter( + mConverterType.getDescriptor(), + event.getPicture()); + + ImageIO.write( + mVideoConverter.toImage(event.getPicture()), + "png", + outputFile); + grabAt = -1; + } + }catch(IOException e){ + e.printStackTrace(); } } @@ -346,3 +361,4 @@ class FrameGrabListener extends MediaToolAdapter { } } + diff --git a/src/zall/util/test/Transcoder.java b/src/zall/util/test/Transcoder.java index f466c01..4074eac 100644 --- a/src/zall/util/test/Transcoder.java +++ b/src/zall/util/test/Transcoder.java @@ -1,47 +1,62 @@ +/* +javac -cp xuggle-xuggler-5.4.jar Transcoder.java +java -cp xuggle-xuggler-5.4.jar:./:slf4j-api-1.6.4.jar Transcoder + +http://whaticode.com/2010/04/30/use-java-to-convert-any-media-type-to-flv-with-xuggler-part-2/ +*/ package zall.util.test; import java.io.File; +import javax.imageio.ImageIO; +import java.io.IOException; import com.xuggle.mediatool.IMediaReader; import com.xuggle.mediatool.IMediaWriter; -import com.xuggle.mediatool.MediaListenerAdapter; import com.xuggle.mediatool.MediaToolAdapter; import com.xuggle.mediatool.ToolFactory; import com.xuggle.mediatool.event.IAddStreamEvent; +import com.xuggle.mediatool.event.AudioSamplesEvent; +import com.xuggle.mediatool.event.IAudioSamplesEvent; import com.xuggle.mediatool.event.IVideoPictureEvent; import com.xuggle.mediatool.event.VideoPictureEvent; -import com.xuggle.xuggler.Configuration; import com.xuggle.xuggler.ICodec; -import com.xuggle.xuggler.IContainer; -import com.xuggle.xuggler.IStream; import com.xuggle.xuggler.IStreamCoder; import com.xuggle.xuggler.IVideoPicture; import com.xuggle.xuggler.IVideoResampler; +import com.xuggle.xuggler.IAudioSamples; +import com.xuggle.xuggler.IAudioResampler; +import com.xuggle.xuggler.video.IConverter; +import com.xuggle.xuggler.video.ConverterFactory; + public class Transcoder { public static void main(String[] args){ - File originalFile = new File( "C:\\Users\\Ziver\\Desktop\\Downloads\\test2.mp4" ); - File mediumFile = new File( "C:\\Users\\Ziver\\Desktop\\Downloads\\temp\\test2_medium.mp4" ); - File smallFile = new File( "C:\\Users\\Ziver\\Desktop\\Downloads\\temp\\test2_small.png" ); + File originalFile = new File( "test2.mp4" ); + File mediumFile = new File( "test2_medium.mp4" ); + File smallFile = new File( "test2_small.png" ); + //ConvertVideo tmp = new ConvertVideo(originalFile, mediumFile); + //tmp.run(); + //return; + ///////////// Start Transcoding // create a media reader IMediaReader reader = ToolFactory.makeReader( originalFile.getPath() ); - reader.open(); - + reader.addListener(new FrameGrabListener(reader, smallFile, 0.2)); + reader.addListener(new ProgressListener(reader)); + + VideoTranscoderListener converter = new VideoTranscoderListener(480, 270); + reader.addListener(converter); + // create a media writer - IMediaWriter mediaWriter = ToolFactory.makeWriter(mediumFile.getPath(), reader); - // add a writer to the reader, to create the output file - reader.addListener(mediaWriter); - - mediaWriter.addListener(new Resizer(450, 295)); - mediaWriter.addListener(new CodecChanger()); - mediaWriter.addListener(new ProgressListener(reader.getContainer())); + IMediaWriter writer = ToolFactory.makeWriter(mediumFile.getPath(), reader); + converter.addListener(writer); // create a media viewer with stats enabled for debugging - //IMediaViewer mediaViewer = ToolFactory.makeViewer(true); // add a viewer to the reader, to see the decoded media + //IMediaViewer mediaViewer = ToolFactory.makeViewer(true); //reader.addListener(mediaViewer); + //writer.addListener(mediaViewer); // read and decode packets from the source file and // and dispatch decoded audio and video to the writer @@ -54,29 +69,53 @@ public class Transcoder { mediumFile.delete(); smallFile.delete(); } - - System.out.println("Done!"); + + System.out.println("\n\nDone!"); + } } +class VideoTranscoderListener extends MediaToolAdapter{ + private int width; + private int height; -class Resizer extends MediaToolAdapter { - private Integer width; - private Integer height; + public VideoTranscoderListener(int width, int height) { + this.width = width; + this.height = height; + } private IVideoResampler videoResampler = null; + private IAudioResampler audioResampler = null; + + @Override + public void onAddStream(IAddStreamEvent event) { + int streamIndex = event.getStreamIndex(); + IStreamCoder streamCoder = event.getSource().getContainer().getStream(streamIndex).getStreamCoder(); + if (streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_AUDIO) { + streamCoder.setSampleRate( 44100 ); + //streamCoder.setCodec( ICodec.ID.CODEC_ID_AAC ); + //streamCoder.setBitRate( 128 ); + } + else if (streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) { + streamCoder.setWidth( width ); + streamCoder.setHeight( height ); - public Resizer(Integer aWidth, Integer aHeight) { - this.width = aWidth; - this.height = aHeight; + //streamCoder.setCodec(ICodec.findEncodingCodec( ICodec.ID.CODEC_ID_H264 )); + //streamCoder.setBitRate( 800000 ); + /* + int retval = Configuration.configure("/usr/local/xuggler/share/ffmpeg/libx264-superfast.ffpreset", streamCoder); + if (retval<0) + throw new RuntimeException("cound not cofigure coder from preset file"); + */ + } + super.onAddStream(event); } @Override public void onVideoPicture(IVideoPictureEvent event) { IVideoPicture pic = event.getPicture(); if (videoResampler == null) { - videoResampler = IVideoResampler.make(width, height, pic.getPixelType(), pic.getWidth(), pic - .getHeight(), pic.getPixelType()); + videoResampler = IVideoResampler.make(width, height, pic.getPixelType(), pic.getWidth(), pic.getHeight(), pic.getPixelType()); } IVideoPicture out = IVideoPicture.make(pic.getPixelType(), width, height); videoResampler.resample(out, pic); @@ -85,20 +124,45 @@ class Resizer extends MediaToolAdapter { super.onVideoPicture(asc); out.delete(); } + + @Override + public void onAudioSamples(IAudioSamplesEvent event) { + IAudioSamples samples = event.getAudioSamples(); + if (audioResampler == null) { + audioResampler = IAudioResampler.make(2, samples.getChannels(), 44100, samples.getSampleRate()); + } + if (event.getAudioSamples().getNumSamples() > 0) { + IAudioSamples out = IAudioSamples.make(samples.getNumSamples(), samples.getChannels()); + audioResampler.resample(out, samples, samples.getNumSamples()); + + AudioSamplesEvent asc = new AudioSamplesEvent(event.getSource(), out, event.getStreamIndex()); + super.onAudioSamples(asc); + out.delete(); + } + } + } class ProgressListener extends MediaToolAdapter { private long currentLength; private long totalLength; + private int progress = -1; - public ProgressListener(IContainer c) { - this.totalLength = c.getDuration(); + public ProgressListener(IMediaReader reader) { + if( !reader.isOpen() ) + reader.open(); // read container + this.totalLength = reader.getContainer().getDuration(); } @Override public void onVideoPicture(IVideoPictureEvent event) { currentLength = event.getTimeStamp(); - System.out.println(currentLength+" / "+totalLength+" - "+getProgress()); + + if( (int)(100*getProgress()) != progress ){ + progress = (int)(100*getProgress()); + System.out.print("\n"+(int)(100*getProgress())+"% "); + } + else System.out.print("."); } public long getProcessedLength(){ @@ -109,66 +173,53 @@ class ProgressListener extends MediaToolAdapter { return totalLength; } - public int getProgress(){ - return (int)(((double)currentLength/totalLength)*100); + public double getProgress(){ + if(totalLength > 0) + return ((double)currentLength/totalLength); + return 0; } } -class CodecChanger extends MediaListenerAdapter { - /* - * HTML5 - * video codec - avc1.42E01E i.e. H.264/MPEG-4 AVC - * audio codec - mp4a.40.2 i.e. MPEG-4 AAC LC - */ - - - public void onAddStream(IAddStreamEvent event) { - // put your stream specific configuration code here - // you can get the container from the writer and - // get the specific stream from the container using - // the stream index in the event - int streamIndex = event.getStreamIndex(); - IStream stream = event.getSource().getContainer().getStream(streamIndex); - ICodec.Type codecType = stream.getStreamCoder().getCodecType(); - - if(codecType == ICodec.Type.CODEC_TYPE_AUDIO){ - applyAudioSettings(stream); - } else { - applyVideoSettings(stream); - } +class FrameGrabListener extends MediaToolAdapter { + private long totalLength; + private long grabAt; + private File outputFile; + + public FrameGrabListener(IMediaReader reader, File outputFile, double at) { + if( !reader.isOpen() ) + reader.open(); // read container + this.totalLength = reader.getContainer().getDuration(); + this.outputFile = outputFile; + setAtProgress(at); } - private void applyVideoSettings(IStream stream) { - IStreamCoder coder = stream.getStreamCoder(); - coder.setCodec(ICodec.ID.CODEC_ID_H264); - coder.setBitRate( 500000 ); - - //IVideoResampler.make(outWidth, outHeight, outContainer.getPixelType(), inContainer.getWidth(), inContainer.getHeight(), inContainer.getPixelType()); + @Override + public void onVideoPicture(IVideoPictureEvent event) { + try{ + long currentLength = event.getTimeStamp(); + + if( grabAt > 0 && currentLength > grabAt ){ + System.out.println("\nScreanshoot!!!"); + + ConverterFactory.Type mConverterType = ConverterFactory.findRegisteredConverter( + ConverterFactory.XUGGLER_BGR_24); + IConverter mVideoConverter = ConverterFactory.createConverter( + mConverterType.getDescriptor(), + event.getPicture()); + + ImageIO.write( + mVideoConverter.toImage(event.getPicture()), + "png", + outputFile); + grabAt = -1; + } + }catch(IOException e){ + e.printStackTrace(); + } } - private void applyAudioSettings(IStream stream) { - IStreamCoder coder = stream.getStreamCoder(); - // ICodec.ID.CODEC_ID_MP3 - coder.setCodec( ICodec.ID.CODEC_ID_AAC ); - //coder.setSampleRate( 44000 ); - coder.setBitRate( 128 ); - - //IAudioResampler.make(out.getChannels(), in.getChannels(), out.getSampleRate(), in.getSampleRate()); - } -} + public void setAtProgress(double procent){ + grabAt = (long)(totalLength * procent); + } +} -class SetVideoTranscodeListener extends MediaToolAdapter { - @Override - public void onAddStream(IAddStreamEvent event) { - int streamIndex = event.getStreamIndex(); - IStreamCoder streamCoder = event.getSource().getContainer().getStream(streamIndex).getStreamCoder(); - - if (streamCoder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) { - streamCoder.setCodec(ICodec.findEncodingCodec(ICodec.ID.CODEC_ID_H264)); - int retval = Configuration.configure("/usr/local/xuggler/share/ffmpeg/libx264-superfast.ffpreset", streamCoder); - if (retval<0) - throw new RuntimeException("cound not cofigure coder from preset file"); - } - super.onAddStream(event); - } -} \ No newline at end of file