FileDocCategorySizeDatePackage
V4LCapture.javaAPI DocJMF 2.1.1e5304Mon May 12 12:21:30 BST 2003com.sun.media.protocol.v4l

V4LCapture.java

/*
 * @(#)V4LCapture.java	1.6 03/04/23
 *
 * Copyright (c) 1996-2003 Sun Microsystems, Inc.  All rights reserved.
 */

package com.sun.media.protocol.v4l;

import javax.media.Format;
import javax.media.format.*;
import java.awt.Dimension;

class V4LCapture {

    private int nativePeer = 0;

    private boolean supportsMMap = false;
    private boolean supportsRead = false;
    private int cardNo = 0;
    
    static {
	com.sun.media.JMFSecurityManager.loadLibrary("jmv4l");
	// System.loadLibrary("jmv4l");
    }
    
    V4LCapture(int cardNo) {
	nativePeer = nOpen(cardNo);
	if (nativePeer != 0)
	    this.cardNo = cardNo;
	else
	    throw new Error("Can't open video card " + cardNo);
    }

    void close() {
	synchronized (this) {
	    nClose();
	    nativePeer = 0;
	}
    }

    native int nOpen(int cardNo);

    native int nClose();
    
    native int getCapability(VCapability vcap);

    native int getChannel(VChannel vchan);

    native int setChannel(VChannel vchan);

    native int getPicture(VPicture vpict);

    native int setPicture(VPicture vpict);

    native int getTuner(VTuner vtuner);

    native int setTuner(VTuner vtuner);

    native int getFrequency();

    native int setFrequency(int freq);

    native int setFormat(int depth, int palette,
				int width, int height,
				float frameRate);

    native int start();

    native int stop();

    native int readNextFrame(byte [] buffer, int offset, int length);


    int formatToPalette(Format format) {
	if (format == null)
	    return 0;
	
	if (format instanceof RGBFormat) {
	    RGBFormat rgbf = (RGBFormat) format;
	    int bpp = rgbf.getBitsPerPixel();
	    switch (bpp) {
	    case 24:
		return VPicture.VIDEO_PALETTE_RGB24;
	    case 16:
		if (rgbf.getGreenMask() == (0x3F << 5))
		    return VPicture.VIDEO_PALETTE_RGB565;
		else
		    return VPicture.VIDEO_PALETTE_RGB555;
	    case 32:
		return VPicture.VIDEO_PALETTE_RGB32;
	    }
	    return 0;
	} else if (format instanceof YUVFormat) {
	    YUVFormat yuvf = (YUVFormat) format;
	    switch (yuvf.getYuvType()) {
	    case YUVFormat.YUV_YUYV:
		if (yuvf.getOffsetY() == 0)
		    return VPicture.VIDEO_PALETTE_YUV422;
		else
		    // Not necessarily, but because the inverse function supports only these two
		    return VPicture.VIDEO_PALETTE_UYVY;
	    case YUVFormat.YUV_420:
		return VPicture.VIDEO_PALETTE_YUV420P;
	    }
	}
	// Not one of the supported types
	return 0;
    }
	    



	    
    VideoFormat paletteToFormat(int palette, Dimension size) {
	int area = size.width * size.height;
	VideoFormat format;
	
	switch (palette) {
	case VPicture.VIDEO_PALETTE_RGB565 :
	    format = new RGBFormat(size, area * 2, Format.byteArray,
				   Format.NOT_SPECIFIED, 16,
				   0x1F << 11, 0x3F << 5, 0x1F,
				   2, size.width * 2,
				   Format.FALSE, RGBFormat.LITTLE_ENDIAN);
	    break;
	case VPicture.VIDEO_PALETTE_RGB24 :
	    format = new RGBFormat(size, area * 3, Format.byteArray,
				   Format.NOT_SPECIFIED, 24,
				   3, 2, 1,
				   3, size.width * 3,
				   Format.FALSE, Format.NOT_SPECIFIED);
	    break;
	case VPicture.VIDEO_PALETTE_RGB32 :
	    format = new RGBFormat(size, area * 4, Format.byteArray,
				   Format.NOT_SPECIFIED, 32,
				   1, 2, 3,
				   4, size.width * 4,
				   Format.FALSE, Format.NOT_SPECIFIED);
	    break;
	case VPicture.VIDEO_PALETTE_RGB555 :
	    format = new RGBFormat(size, area * 2, Format.byteArray,
				   Format.NOT_SPECIFIED, 16,
				   0x1F << 10, 0x1F << 5, 0x1F,
				   2, size.width * 2,
				   Format.FALSE, RGBFormat.LITTLE_ENDIAN);
	    break;
	case VPicture.VIDEO_PALETTE_YUV422 :
	case VPicture.VIDEO_PALETTE_YUYV :
	    format = new YUVFormat(size, area * 2, Format.byteArray,
				   Format.NOT_SPECIFIED, YUVFormat.YUV_YUYV,
				   size.width * 2, size.width * 2,
				   0, 1, 3);
	    break;
	case VPicture.VIDEO_PALETTE_UYVY :
	    format = new YUVFormat(size, area * 2, Format.byteArray,
				   Format.NOT_SPECIFIED, YUVFormat.YUV_YUYV,
				   size.width * 2, size.width * 2,
				   1, 0, 2);
	    break;
	case VPicture.VIDEO_PALETTE_YUV420P :
	    format = new YUVFormat(size, area + (area / 2), Format.byteArray,
				   Format.NOT_SPECIFIED, YUVFormat.YUV_420,
				   size.width, size.width / 2,
				   0, area, area + (area / 4));
	    break;

	// TODO : Rest of the formats

	default :
	    format = null;
	}

	return format;
    }

    int paletteToDepth(int palette) {
	int p2d [] = {
	    0,
	    8,  // VIDEO_PALETTE_GREY
	    8,  // VIDEO_PALETTE_HI240
	    16, // VIDEO_PALETTE_RGB565
	    24, // VIDEO_PALETTE_RGB24
	    32, // VIDEO_PALETTE_RGB32
	    16, // VIDEO_PALETTE_RGB555
	    16, // VIDEO_PALETTE_YUV422
	    16, // VIDEO_PALETTE_YUYV
	    16, // VIDEO_PALETTE_UYVY
	    12, // VIDEO_PALETTE_YUV420
	    12, // VIDEO_PALETTE_YUV411
	    12, // VIDEO_PALETTE_RAW
	    16, // VIDEO_PALETTE_YUV422P
	    12, // VIDEO_PALETTE_YUV411P
	    12, // VIDEO_PALETTE_YUV420P
	    12, // VIDEO_PALETTE_YUV410P
	    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	};
	return p2d[palette];
    }
    
//     public static void main(String [] args) {
// 	V4LCapture cap = new V4LCapture(0);
// 	VCapability vcap = new VCapability();
// 	cap.getCapability(vcap);
// 	cap.close();
// 	System.err.println("Card = " + vcap.name);
// 	System.err.println("Channels = " + vcap.channels);
//     }
}