FileDocCategorySizeDatePackage
SunRayRenderer.javaAPI DocJMF 2.1.1e10970Mon May 12 12:21:24 BST 2003com.sun.media.renderer.video

SunRayRenderer.java

/*
 * @(#)SunRayRenderer.java	1.9 02/08/21
 *
 * Copyright (c) 1996-2002 Sun Microsystems, Inc.  All rights reserved.
 */

package com.sun.media.renderer.video;

import javax.media.*;
import javax.media.Format;
import javax.media.format.VideoFormat;
import javax.media.format.YUVFormat;
import javax.media.renderer.VideoRenderer;
import java.awt.*;
import java.awt.image.*;
import java.util.Vector;
import java.io.File;
import com.sun.media.*;
import com.sun.media.util.WindowUtil;
import com.sun.media.util.MediaThread;


public class SunRayRenderer extends BasicVideoRenderer
implements com.sun.media.util.DynamicPlugIn {

    private static boolean available = false;
    private static int jawtAvail = WindowUtil.getJAWTAvail();

    private static boolean debug = false;

    private    int        blitter     = 0;
    protected  Object     data        = null;

    private    int        offsetX = 0;
    private    int        offsetY = 0;

    private    int        yuvType;
    private    int        yOff;
    private    int        uOff;
    private    int        vOff;
    private    int        yStride;
    private    int        uvStride;
    private    int        lastOutWidth = -1;
    private    int        lastOutHeight = -1;
    private    boolean    firstTime = true;

    private    EventThread  xeventThread = null;
    
    private native void srSetJAWT(int jawt);
    private synchronized native boolean srInitialize();
    private synchronized native boolean srDisplayIsSunRay();
    private synchronized native boolean srSetComponent(Object component);
    private synchronized native boolean srSetInputFormat(int width, int height,
						   int offY, int offU, int offV,
						   int strideY, int strideUV,
						   int subX, int subY);
    private synchronized native boolean srSetOutputSize(int width, int height);
    private synchronized native boolean srDraw(Object data);
    private synchronized native boolean srFree();
    private synchronized native boolean srEventCheck();

    static {
	if (debug) {
	    System.err.println("SunRayRenderer static entered");
	}
	try {
	    Object jmfSecurity = JMFSecurityManager.getJMFSecurity();
	    if (jmfSecurity != null &&
    jmfSecurity.getClass().getName().equals("com.sun.media.NetscapeSecurity")) {
		// Netscape only supports green threads and libutmedia
		// uses pthread_mutex so requires native threads.
		if (debug) {
		    System.err.println("SunRayRenderer under Netscape");
		}
		available = false;
	    } else {
		// avoid load failed messages on non-SunRay systems.
		// Note: doesn't work if Sun Ray server installed in
		// non-standard directory.
		File lib = new File("/opt/SUNWut/lib/libutmedia.so");
		if (lib.exists()) {
		    JMFSecurityManager.loadLibrary("jmutil");
		    JMFSecurityManager.loadLibrary("jmsunray");
		    available = true;
		} else {
		    if (debug) {
			System.err.println("SunRayRenderer no libutmedia");
		    }
		    available = false;
		}
	    }
	} catch (UnsatisfiedLinkError ule) {
	    if (debug) {
		System.err.println("SunRayRenderer load libjmsunray failed");
	    }
	    available = false;
	} catch (SecurityException se) {
	    if (debug) {
		System.err.println("SunRayRenderer security exception");
	    }
	    available = false;
	} catch (NullPointerException npe) {
	    if (debug) {
		System.err.println("SunRayRenderer null pointer exception");
	    }
	    available = false;
	} catch (Exception e) {
	    System.err.println("SunRayRenderer exception: " + e);
	    e.printStackTrace();
	    available = false;
	}
    }

    public SunRayRenderer() {
	super("SunRay Renderer");
	if (debug) {
	    System.err.println("SunRayRenderer <init>() entered");
	}
	supportedFormats = new VideoFormat[] {
				new YUVFormat(YUVFormat.YUV_411),
				new YUVFormat(YUVFormat.YUV_420),
				new YUVFormat(YUVFormat.YUV_422),
				new YUVFormat(YUVFormat.YUV_111)
	};
	if (!available) {
//	    throw new RuntimeException("Could not load jmsunray library");
	    return;
	}

	srSetJAWT(jawtAvail);

	if (!srDisplayIsSunRay()) {
	    if (debug) {
		System.err.println("SunRayRenderer display is not a Sun Ray ");
	    }
	    available = false;
//	    throw new RuntimeException("Display is not a Sun Ray");
	    return;
	}
	if (!srInitialize()) {
	    available = false;
	}
	if (debug) {
	    System.err.println("SunRayRenderer <init>() completed");
	}
    }

    public void open() throws ResourceUnavailableException {

	if (debug) {
	    System.err.println("SunRayRenderer open() entered");
	}
	if (!available) {
	    if (debug) {
		System.err.println("SunRayRenderer Sun Ray not available");
	    }
	    throw new ResourceUnavailableException("Sun Ray not available");
	}
    }

    public void reset() {
    }

    public synchronized void close() {
	if (debug) {
	    System.err.println("SunRayRenderer close() entered");
	}
	if (xeventThread != null) {
	    xeventThread.stopChecking();
	    xeventThread.interrupt();
	    while (xeventThread.isAlive()) {
		try {
		    Thread.currentThread().sleep(5);
		} catch (InterruptedException ex) {
		}
	    }
	    xeventThread = null;
	}
	if (available && blitter != 0)
	    srFree();
	if (debug) {
	    System.err.println("SunRayRenderer close() complete");
	}
    }

    /**
     * Set the data input format.
     * @return false if the format is not supported.
     */
    public Format setInputFormat(Format format) {
	if (debug) {
	    System.err.println("SunRayRenderer setInputFormat() entered");
	}
	if (!available) {
	    if (debug) {
		System.err.println("SunRayRenderer setInputFormat !available");
	    }
	    return null;
	}

	if (!(format instanceof YUVFormat))
	    return null;
	if (super.setInputFormat(format) != null) {
	    if (inputFormat instanceof YUVFormat) {
		YUVFormat yuvf = (YUVFormat) inputFormat;
		yuvType = yuvf.getYuvType();
		yOff = yuvf.getOffsetY();
		uOff = yuvf.getOffsetU();
		vOff = yuvf.getOffsetV();
		yStride = yuvf.getStrideY();
		uvStride = yuvf.getStrideUV();
	    } else
		return null;

	    int subx = 4;	// assume 411
	    int suby = 4;
	    if (yuvType == YUVFormat.YUV_422) {
		subx = 2;
	        suby = 2;
	    } else if (yuvType == YUVFormat.YUV_111) {
		subx = 1;
		suby = 1;
	    } else if (yuvType == YUVFormat.YUV_420) {
		subx = 2;
	        suby = 2;
	    }

	    // Inform the native code of the input format change
	    srSetInputFormat(inWidth, inHeight,
				yOff, uOff, vOff,
				yStride, uvStride,
				subx, suby);
	    
	    if (outWidth == -1 || outHeight == -1) {
		outWidth = inWidth;
		outHeight = inHeight;
	    }

	    if (component != null)
		component.setSize(outWidth, outHeight);
	    // All's well
	    if (debug) {
		System.err.println("SunRayRenderer setInputFormat() returned "
								+ format);
	    }
	    return format;
	} else {
	    // Unsupported format
	    return null;
	}
    }

    protected void setAvailable(boolean on) {
	if (debug) {
	    System.err.println("SunRayRenderer setAvailable() entered");
	}
	Thread xevt = null;
	super.setAvailable(on);
	synchronized (this) {
	    if (on) {
		if (xeventThread == null) {
		    xeventThread = new EventThread(this);
		    xeventThread.start();
		}
	    } else {
		if (xeventThread != null) {
		    xeventThread.stopChecking();
		    xeventThread.interrupt();
		    xevt = xeventThread;
		    xeventThread = null;
		    data = null;
		}
	    }
	}
	// wait for the thread to end outside the synchronized block
	// to avoid a deadlock
	if (xevt != null) {
	    while (xevt.isAlive()) {
		try {
		    Thread.currentThread().sleep(5);
		} catch (InterruptedException ex) {
		}
	    }
	}
    }

    protected synchronized void removingComponent() {
	if (debug) {
	    System.err.println("SunRayRenderer removingComponent() entered");
	}
	if (blitter != 0) {
	    srFree();
	}
    }

    protected int doProcess(Buffer buffer) {
	return doProcess(buffer, false);
    }

    protected int doProcess(Buffer buffer, boolean repaint) {
//	if (debug) {
//	    System.err.println("SunRayRenderer doProcess() entered");
//	}
	if (!available || component == null)
	    return BUFFER_PROCESSED_OK;
	synchronized (this) {
	    if (!componentAvailable)
		return BUFFER_PROCESSED_OK;
	    if (blitter == 0 || firstTime) {
		firstTime = false;
		if (blitter == 0)
		    srInitialize();
		int handle = com.sun.media.util.WindowUtil.getWindowHandle(component);
		if (handle != 0) {
		    srSetComponent(component);
		    // Reset it to force calling setInputFormat
		    inputFormat = new VideoFormat(null);
		}
		if (blitter == 0) {
		    if (debug) {
			System.err.println("Could not create blitter");
		    }
		    return BUFFER_PROCESSED_FAILED;
		}
	    }

	    if (!repaint) {
		if (!buffer.getFormat().equals(inputFormat)) {
		    if (setInputFormat(buffer.getFormat()) == null)
			return BUFFER_PROCESSED_FAILED;
		}
		
		data = buffer.getData();
	    } else
		if (data == null)
		    return BUFFER_PROCESSED_FAILED;
	    
	    if (outWidth > 0 && outHeight > 0) {
		if (outWidth != lastOutWidth || outHeight != lastOutHeight) {
		    outWidth &= ~1;
		    lastOutWidth = outWidth;
		    lastOutHeight = outHeight;
		    
		    srSetOutputSize(outWidth, outHeight);
		    if (debug) {
			System.err.println("SunRayRenderer srSetOutputSize() "
					+ outWidth + "x" + outHeight);
		    }
		}
		return (srDraw(data))?
		    BUFFER_PROCESSED_OK : BUFFER_PROCESSED_FAILED;
	    } else
		return BUFFER_PROCESSED_FAILED;
	}
    }

    public Format [] getBaseInputFormats() {
	if (debug) {
	    System.err.println("SunRayRenderer getBaseInputFormats() entered");
	}
	Format [] formats = new Format[1];
	formats[0] = new YUVFormat();
	return formats;
    }

    public Format [] getBaseOutputFormats() {
	if (debug) {
	    System.err.println("SunRayRenderer getBaseOutputFormats() entered");
	}
	Format [] formats = new Format[0];
	return formats;
    }

    protected synchronized void repaint() {
	if (debug) {
	    System.err.println("SunRayRenderer repaint() entered");
	}
	if (!isStarted() && data != null)
	    doProcess(null, true);
    }

    /****************************************************************
     * INNER CLASSES
     ****************************************************************/

    /*
     * This class establishes a thread that invokes the native code
     * to check for X events (move, resize, expose, clip region change)
     */
    class EventThread extends MediaThread {
	SunRayRenderer renderer;
	private    boolean    checkEvents = true;

	public EventThread(SunRayRenderer renderer) {
	    super("SunRayRenderer Event Thread");
	    this.renderer = renderer;
	    useVideoPriority();
	}

	public void stopChecking() {
	    checkEvents = false;
	}

	public void run() {
	    while(checkEvents) {
		// srEventCheck will return true for resize or repaint
		if (renderer.srEventCheck()) {
		    renderer.repaint();
		}
		try {
		    sleep(5);
		} catch (InterruptedException ex) {
		}
	    }
	    renderer = null;
	}
 
    }		// end of EventThread

}