Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Live camera picture from SequenceGrabber using awt or OpenGL



Thanks for this Jochen tops stuff...

> -----Original Message-----
> From: quicktime-java-bounces+ant=email@hidden
> [mailto:quicktime-java-bounces+ant=email@hidden] On Behalf
> Of Jochen Broz
> Sent: 19 February 2005 12:26
> To: email@hidden
> Subject: Live camera picture from SequenceGrabber using awt or OpenGL
> 
> Hello,
> 
> Getting live image from sequence grabber has been discussed on this
> list frequently. There have been lots of hints about how to get images
> at high rates from the SequenceGrabber to the screen.  For example an
> interesting comment about the topic came from Alexander Powell in
> November 2004 at this mailing list. He suggested to use OpenGL to get
> the image on the screen.
> 
> I was experimenting with the topic and since there have not been many
> code examples about this up to now, I thought, it might be of interest
> here to see some examples of how to do that.
> 
>   I present two ways of getting sequence grabber live images to screen.
> Both have been tested with my Logitech QuickCam. So I do not know, if
> the code works with other cameras. One method is using JOGL, (see
> http://today.java.net/pub/a/today/2003/09/11/jogl2d.html for a
> introduction to Java and OpenGL) and one that is based on awt's
> BufferedImage.
> 
> The basic steps are in common for both methods:
> 1. Set up the SequenceGrabber Component
> 2. Define a offscreen gWorld, where the SequenceGrabber may draw to
> 3. Configure the VideoChannel
> 4. Start previewing
> 5. Get the RawImage from the gWorld frequently, and bring it to the
> screen (either with awt or JOGL)
> 
> But there is a problem with step 4. Driving the camera in Preview mode
> does not work correctly. Chris Adamson is talking about this in the
> "making a Motion Detector" section of his new book "Quicktime for Java
> - A Developers Notebook" (O`Reilly). The update of the GWorld is not
> reliable  and in the worst case only once and then never again. But if
> you switch to record mode this problem disappears.
> This behavior can be exploited to create a reliable preview mode:
> 
> Configure the VideoChannel to
> quicktime.std.StdQTConstants.seqGrabPlayDuringRecord
> 		VideoChannel vc
> 		vc.setUsage(quicktime.std.StdQTConstants.seqGrabRecord |
>
quicktime.std.StdQTConstants.seqGrabPreview
> |
> 
> 	quicktime.std.StdQTConstants.seqGrabPlayDuringRecord);
> 
> Go ahead as if you would try to record a movie. Set sequence grabbers
> data output to dummy file and set the
> quicktime.std.StdQTConstants.seqGrabDontMakeMovie flag. This prevents
> quicktime from creating the file.
> Thus, this approach seems to be quite equivalent to the original
> preview mode. Finally start recording.
> 
> 		QTFile movieFile = new QTFile(new java.io.File("NoFile"));
> 		sg.setDataOutput( null,
> quicktime.std.StdQTConstants.seqGrabDontMakeMovie);
>   		sg.prepare(true, true);
> 		sg.startRecord();
> 
> In both methods, the data is copied from the gWorlds RawImage to an int
> array. This can be the data buffer for an awt BufferedImage or can be
> passed to the OpenGLs glDrawPixel method.
> 
> Here is the example code. The OpenGL method is faster then the awt
> method. Unfortunately, the OpenGL image is upside down. So one should
> apply one of OpenGLs rotate methods. I am not very familiar with OpenGL
> and have not managed to turn it.
> 
> 
> 
> 
> ************************************************************************
> ****************
> //
> //  LiveCam.java
> //  LiveCam
> //
> //  Created by Jochen Broz on 19.02.05.
> //  Copyright (c) 2005 Jochen Broz. All rights reserved.
> //
> 
> import java.util.*;
> 
> // for the OpenGL stuff
> import net.java.games.jogl.*;
> 
> 
> // For accessing the sequence grabber
> import quicktime.*;
> import quicktime.std.sg.*;
> import quicktime.std.*;
> import quicktime.qd.*;
> import quicktime.util.*;
> import quicktime.io.*;
> import quicktime.std.image.*;
> 
> 
> // For creation of awt images
> import java.awt.*;
> import java.awt.image.*;
> import javax.swing.*;
> 
> 
> public class LiveCam {
> 
> 	int frameCount = 0;
> 
> 	// Data concerning the sequence grabber, its gWorld and its image
> size
> 	SequenceGrabber sg;
> 	QDRect cameraImageSize;
> 	QDGraphics gWorld;
> 
> 
> 	// Data concerning building awt images from cameras gWorld
> 	public int[] pixelData;
> 	BufferedImage image;
> 
> 
> 	/**
> 	 * flag, indicating that all capture and display tasks should
> continue
> or not
> 	 */
> 	boolean cameraActive = true;
> 
> 	/**
> 	 * Creates the LiveCam object.
> 	 */
> 	public LiveCam() throws Exception{
> 		initSequenceGrabber();
> 		initBufferedImage();
> 	}
> 
> 	/**
> 	 * Initializes the SequenceGrabber. Gets it's source video bounds,
> creates a gWorld with that size.
> 	 * Configures the video channel for grabbing, previewing and playing
> during recording.
> 	 */
> 	private void initSequenceGrabber() throws Exception{
> 		sg = new SequenceGrabber();
> 		SGVideoChannel vc = new SGVideoChannel(sg);
> 		cameraImageSize = vc.getSrcVideoBounds();
> 
> 		gWorld =new QDGraphics(cameraImageSize);
> 		sg.setGWorld(gWorld, null);
> 
> 		vc.setBounds(cameraImageSize);
> 		vc.setUsage(quicktime.std.StdQTConstants.seqGrabRecord |
>
quicktime.std.StdQTConstants.seqGrabPreview
> |
> 
> 	quicktime.std.StdQTConstants.seqGrabPlayDuringRecord);
> 		vc.setFrameRate(0);
> 		vc.setCompressorType(
> quicktime.std.StdQTConstants.kComponentVideoCodecType);
> 	}
> 
> 
> 	/**
> 	 * This initializes the buffered image. First if determines the size
> of the data.
> 	 * Finds the number of ints per row, sets up the int array, where we
> can put the
> 	 * pixel data in. A DataBuffer is defined, using that int array.
> Based
> on this DataBuffer
> 	 * the BufferedImage is defined.
> 	 * The BufferedImage definition is not needed when the OpenGL view
> is
> used. There we only need
> 	 * the int-array pixelData. But I do not expect that defining the
> Buffered image has negative influence
> 	 * on OpenGLs performance.
> 	 */
> 	private void initBufferedImage() throws Exception{
> 
> 		int size =  gWorld.getPixMap().getPixelData().getSize();
> 		int intsPerRow =
> gWorld.getPixMap().getPixelData().getRowBytes()/4;
> 
> 		size = intsPerRow*cameraImageSize.getHeight();
> 		pixelData = new int[size];
> 		DataBuffer db = new DataBufferInt(pixelData, size);
> 
> 		ColorModel colorModel = new DirectColorModel(32, 0x00ff0000,
> 0x0000ff00, 0x000000ff);
> 		int[] masks= {0x00ff0000, 0x0000ff00, 0x000000ff};
> 		WritableRaster raster = Raster.createPackedRaster(db,
> cameraImageSize.getWidth(), cameraImageSize.getHeight(), intsPerRow,
> masks, null);
> 		image = new BufferedImage(colorModel, raster, false, null);
> 
> 	}
> 
> 
> 	/**
> 	 * This is a bit tricky. We do not start Previewing, but recording.
> By
> setting the output to a
> 	 * dummy file (which will never be created (hope so)) with the
> 	 * quicktime.std.StdQTConstants.seqGrabDontMakeMovie flag set. This
> seems to be equivalent to
> 	 * preview mode with the advantage, that it refreshes correctly.
> 	 */
> 	private void startPreviewing() throws Exception{
> 		QTFile movieFile = new QTFile(new java.io.File("NoFile"));
> 		sg.setDataOutput( null,
> quicktime.std.StdQTConstants.seqGrabDontMakeMovie);
>   		sg.prepare(true, true);
> 		sg.startRecord();
> 
> 		// setting up a thread, to idle the sequence grabber
> 		Runnable idleCamera = new Runnable(){
> 			int taskingDelay = 25;
> 			public void run(){
> 				try{
> 					while(cameraActive){
> 						Thread.sleep(taskingDelay);
> 						synchronized(sg){
> 							sg.idleMore();
> 							sg.update(null);
> 						}
> 					}
> 				}catch(Exception ex){
> 					ex.printStackTrace();
> 				}
> 			}
> 		};
> 		(new Thread(idleCamera)).start();
> 	}
> 
> 
> 	/**
> 	 * This creates a Panel, which displays the buffered image using
> awt.
> A Thread is started, copying
> 	 * the pixel data from the sequence grabbers gWorld to the data
> buffer
> of the BufferedImage. Then
> 	 * the image is repainted.
> 	 */
> 	public Component buildSwingCameraView(){
> 		/**
> 		* Used for the threadding image update
> 		 */
> 		final Component ret = new Component(){
> 			public void paint(Graphics g){
> 				super.paint(g);
> 				g.drawImage(image, 0, 0, this);
> 				frameCount++;
> 			};
> 		};
> 
> 		Runnable imageUpdate = new Runnable(){
> 			int taskingDelay = 10;
> 			public void run(){
> 				try{
> 					while(cameraActive){
> 						synchronized(sg){
> 
> 	gWorld.getPixMap().getPixelData().copyToArray(0, pixelData, 0,
> pixelData.length);
> 							ret.repaint();
> 						}
> 						Thread.sleep(taskingDelay);
> 					}
> 				}catch(Exception ex){
> 					ex.printStackTrace();
> 				}
> 			}
> 		};
> 		(new Thread(imageUpdate)).start();
> 		return ret;
> 	}
> 
> 
> 	/**
> 	 * This creates a Panel, which displays the camera image using
> OpenGL
> 	 */
> 	public Component buildOpenGLCameraView(){
> 		GLEventListener jogler = new GLEventListener(){
> 			final int WIDTH =
> gWorld.getPixMap().getPixelData().getRowBytes()/4;
> 			final int HEIGHT = cameraImageSize.getHeight();
> 
> 			public void init(GLDrawable drawable){
> 				GL gl = drawable.getGL();
> 				gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
> 				gl.glShadeModel(GL.GL_FLAT);
> 			}
> 
> 			public void display(GLDrawable drawable){
> 				GL gl = drawable.getGL();
> 				GLU glu = drawable.getGLU();
> 				gl.glClear(GL.GL_COLOR_BUFFER_BIT|
> GL.GL_DEPTH_BUFFER_BIT);
> 				gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1);
>
gWorld.getPixMap().getPixelData().copyToArray(0,
> pixelData, 0,
> WIDTH*HEIGHT);
> 				gl.glDrawPixels(WIDTH, HEIGHT, gl.GL_BGRA,
> gl.GL_UNSIGNED_INT_8_8_8_8_REV, pixelData);
> 				frameCount++;
> 			}
> 
> 			public void reshape(GLDrawable drawable, int i, int
x,
> int width,
> int height){
> 				GL gl = drawable.getGL();
> 				GLU glu = drawable.getGLU();
> 				gl.glViewport(0, 0, WIDTH, HEIGHT);
> 				gl.glMatrixMode(GL.GL_PROJECTION);
> 				gl.glLoadIdentity();
> 				glu.gluOrtho2D(0.0, (double) WIDTH, 0.0,
(double)
> HEIGHT);
> 				gl.glMatrixMode(GL.GL_MODELVIEW);
> 				gl.glLoadIdentity();
> 			}
> 
> 			public void displayChanged(GLDrawable drawable,
boolean
> modeChanged,
> boolean deviceChanged){}
> 		};
> 
> 		GLCapabilities caps = new GLCapabilities();
> 		GLCanvas canvas =
> GLDrawableFactory.getFactory().createGLCanvas(caps);
> 		canvas.addGLEventListener(jogler);
> 		Animator animator = new Animator(canvas);
> 		animator.start();
> 		return canvas;
> 	}
> 
> 	public QDRect getImageSize(){
> 		return cameraImageSize;
> 	}
> 
> 	public int getFrameCount(){
> 		return frameCount;
> 	}
> 
> 
>      public static void main (String args[]) {
> 		try{
> 			QTSession.open();
> 
> 			LiveCam myCam = new LiveCam();
> 			Frame cameraFrame = new Frame("LiveCam");
> 			myCam.startPreviewing();
> 
> 			// Switch between the two lines to select OpenGL or
awt
> display:
> 			//Component imagePanel =
myCam.buildSwingCameraView();
> 			Component imagePanel =
myCam.buildOpenGLCameraView();
> 
> 			cameraFrame.add(imagePanel);
> 			cameraFrame.setBounds(100, 100,
> myCam.getImageSize().getWidth(),
> myCam.getImageSize().getHeight());
> 			cameraFrame.show();
> 
> 			// Do some frame counting
> 			System.out.println("Counting frames:");
> 			Thread.sleep(5000);
> 			int fc = myCam.getFrameCount();
> 			Thread.sleep(10000);
> 			System.out.println("Frame
> rate:"+0.1*(myCam.getFrameCount()-fc));
> 
> 		}catch(Exception ex){
> 			ex.printStackTrace();
> 			QTSession.close();
> 		}
> 
>      }
> }
> 
>  _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> QuickTime-java mailing list      (email@hidden)
> Help/Unsubscribe/Update your Subscription:
> http://lists.apple.com/mailman/options/quicktime-java/email@hidden
> 
> This email sent to email@hidden

 _______________________________________________
Do not post admin requests to the list. They will be ignored.
QuickTime-java mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/quicktime-java/email@hidden

This email sent to email@hidden

References: 
 >Live camera picture from SequenceGrabber using awt or OpenGL (From: Jochen Broz <email@hidden>)



Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.