Il codice è un bel pò lungo.Spero riuscite a capirlo.
Devo convertire il segnale RGB in JPEG, in modo che posso trasmetterlo in rete (JPEG/RTP), tramite protocollo RTP. In fase di esecuzione mi dice che il Processor non può convertire il formato RGB in JPEG. Ho utilizzato il codec per trasformare da RGB a JPEG con il codec messo a disposizione dalle JMF.
Il mio scopo è di trasmettere da un computer ad un altro tramite rete il video da telecamera.
Grazie
import java.net.*;
import java.awt.*;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.protocol.DataSource;
import javax.media.format.*;
import javax.media.control.TrackControl;
import javax.media.control.QualityControl;
import java.io.*;
import java.util.*;
import com.sun.media.codec.video.jpeg.NativeEncoder;
import com.sun.media.MimeManager.*;
import javax.media.rtp.*;
import javax.media.rtp.rtcp.*;
import com.sun.media.rtp.*;
public class VideoTransmit {
// Input MediaLocator
// Can be a file or http or capture source
private MediaLocator locator;
private String ipAddress;
private String port;
private NativeEncoder e;
private Processor processor = null;
private DataSink rtptransmitter = null;
private DataSource dataOutput = null;
private RTPManager rtpMgrs[];
private int portBase;
//Locator del video da trasmettere
//Indirizzo IP del trasmettitore
//Numero porta del trasmettitore
public VideoTransmit(MediaLocator locator,String ipAddress, String port) {
this.locator = locator;
this.ipAddress = ipAddress;
this.port = port;
}
/**
* Starts the transmission. Returns null if transmission started ok.
* Otherwise it returns a string with the reason why the setup failed.
*/
public synchronized String start() throws Exception {
String result;
// Create a processor for the specified media locator
// and program it to output JPEG/RTP
result = createProcessor();
if (result != null)
return result;
// Create an RTP session to transmit the output of the
// processor to the specified IP address and port no.
result = createTransmitter();
if (result != null) {
processor.close();
processor = null;
return result;
}
// Start the transmission
processor.start();
return null;
}
public void stop() {
synchronized (this) {
if (processor != null) {
processor.stop();
processor.close();
processor = null;
rtptransmitter.close();
rtptransmitter = null;
}
}
}
private String createProcessor() throws Exception {
if(locator == null)
return "Locator is null";
DataSource ds;
DataSource clone;
try {
ds = Manager.createDataSource(locator);
} catch (Exception e) {
return "Couldn't create DataSource";
}
// Try to create a processor to handle the input media locator
try {
processor = Manager.createProcessor(ds);
} catch (Exception e) {
return "Couldn't create processor";
}
boolean result = waitForState(processor, Processor.Configured);
if (result == false)
return "Couldn't configure processor";
ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
processor.setContentDescriptor(cd);
TrackControl [] tracks = processor.getTrackControls();
Format[] supported;
// Do we have atleast one track?
if(tracks == null || tracks.length < 1)
return "Couldn't find tracks in processor";
boolean programmed = false;
for(int i = 0; i < tracks.length; i++) {
Format format = tracks[i].getFormat();
supported = tracks[i].getSupportedFormats();
System.out.println("Formati supportai dal plug-in " + supported[0]);
if(tracks[i].isEnabled() && format instanceof VideoFormat && supported[0] instanceof VideoFormat && !programmed) {
Format fSupportato = tracks[i].setFormat(supported[0]);
System.out.println("FORMATO SUPPORTATO: "+ fSupportato);
Dimension size = ((VideoFormat)format).getSize();
float frameRate = ((VideoFormat)format).getFrameRate();
int w = (size.width % 8 == 0 ? size.width : (int)(size.width / 8) * 8);
int h = (size.height % 8 == 0 ? size.height : (int)(size.height / 8) * 8);
Codec c = null;
try { Class natEnc = Class.forName("com.sun.media.codec.video.jpeg.Nati veEncoder");
c = (Codec)natEnc.newInstance();
System.out.println("Successfully started codec");
}
catch(Exception classerr) {
System.out.println("Cannot find class: "+classerr);
}
//Formati in uscita supportati dal Codec
Format[] fInput = c.getSupportedInputFormats();
Format[] fOutput = c.getSupportedOutputFormats(null);
for(int count=0; count<fOutput.length; count++)
{ System.out.println("FormOut:" + fOutput[count]);
}
if(fOutput[0] instanceof VideoFormat)
{ System.out.println("Formati supportati in uscita: "+ fOutput[0]);
}
else
{ System.out.println("Not Supported");
System.exit(-1);
}
Format fIn = c.setInputFormat(format);
//Setta il formato all'uscita del codec
Format fOut = c.setOutputFormat(fOutput[0]);
try {
c.open(); //initialize the coder
}
catch(ResourceUnavailableException err) {
System.out.println("Unable to open codec: "+err);
}
tracks[i].setFormat(fOut);
//Setta la qualità di codifica del video
Control cse[] = (Control[])c.getControls();
for(int j = 0; j < cse.length; j++)
{
if(cse[j] instanceof QualityControl)
{ QualityControl qc = (QualityControl)cse[j];
qc.setQuality(0.6F);
break;
}
}
programmed = true;
}
else
tracks[i].setEnabled(false);
}
if(!programmed)
return "Couldn't find video track";
result = waitForState(processor, Controller.Realized);
if(result == false)
return "Couldn't realize processor";
// Set the JPEG quality to .5.
//setJPEGQuality(processor, 0.5f);
// Get the output data source of the processor
dataOutput = processor.getDataOutput();
return null;
}
private String createTransmitter() {
// Cheated. Should have checked the type.
PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
PushBufferStream pbss[] = pbds.getStreams();
rtpMgrs = new RTPManager[pbss.length];
SessionAddress localAddr, destAddr;
InetAddress ipAddr;
SendStream sendStream;
int port;
SourceDescription srcDesList[];
for (int i = 0; i < pbss.length; i++) {
try {
rtpMgrs[i] = RTPManager.newInstance();
// The local session address will be created on the
// same port as the the target port. This is necessary
// if you use AVTransmit2 in conjunction with JMStudio.
// JMStudio assumes - in a unicast session - that the
// transmitter transmits from the same port it is receiving
// on and sends RTCP Receiver Reports back to this port of
// the transmitting host.
port = portBase + 2*i;
ipAddr = InetAddress.getByName(ipAddress);
localAddr = new SessionAddress( InetAddress.getLocalHost(),
port);
destAddr = new SessionAddress( ipAddr, port);
rtpMgrs[i].initialize( localAddr);
rtpMgrs[i].addTarget( destAddr);
System.err.println( "Created RTP session: " + ipAddress + " " + port);
//Crea un flusso di dati che vengono inviati dentro una sessione RTP
sendStream = rtpMgrs[i].createSendStream(dataOutput, i); //Connessione tra il DataSource e RTPManager
sendStream.start(); //Inizia la trasmissione del flusso oltre la rete
} catch (Exception e) {
return e.getMessage();
}
}
return null;
}
/**
* Setting the encoding quality to the specified value on the JPEG encoder.
* 0.5 is a good default.
*/
void setJPEGQuality(Player p, float val) {
Control cs[] = p.getControls();
QualityControl qc = null;
VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);
// Loop through the controls to find the Quality control for
// the JPEG encoder.
for (int i = 0; i < cs.length; i++) {
if(cs[i] instanceof QualityControl && cs[i] instanceof Owned) {
Object owner = ((Owned)cs[i]).getOwner();
// Check to see if the owner is a Codec.
// Then check for the output format.
if (owner instanceof Codec) {
Format fmts[] = ((Codec)owner).getSupportedOutputFormats(null);
for (int j = 0; j < fmts.length; j++) {
if (fmts[j].matches(jpegFmt)) {
qc = (QualityControl)cs[i];
qc.setQuality(val);
System.err.println("- Setting quality to " +
val + " on " + qc);
break;
}
}
}
if (qc != null)
break;
}
}
}
/************************************************** **************
* Convenience methods to handle processor's state changes.
************************************************** **************/
private Integer stateLock = new Integer(0);
private boolean failed = false;
Integer getStateLock() {
return stateLock;
}
void setFailed() {
failed = true;
}
private synchronized boolean waitForState(Processor p, int state) {
p.addControllerListener(new StateListener());
failed = false;
// Call the required method on the processor
if(state == Processor.Configured) {
p.configure();
} else if(state == Processor.Realized) {
p.realize();
}
// Wait until we get an event that confirms the
// success of the method, or a failure event.
// See StateListener inner class
while(p.getState() < state && !failed) {
synchronized(getStateLock()) {
try {
getStateLock().wait();
}
catch (InterruptedException ie) {
return false;
}
}
}
if(failed)
return false;
else
return true;
}
/************************************************** **************
* Inner Classes
************************************************** **************/
class StateListener implements ControllerListener {
public void controllerUpdate(ControllerEvent ce) {
// If there was an error during configure or
// realize, the processor will be closed
if (ce instanceof ControllerClosedEvent)
setFailed();
// All controller events, send a notification
// to the waiting thread in waitForState method.
if(ce instanceof ControllerEvent) {
synchronized(getStateLock()) {
getStateLock().notifyAll();
}
}
}
}
/************************************************** **************
* Sample Usage for VideoTransmit class
************************************************** **************/
public static void main(String [] args) throws Exception {
CaptureDeviceInfo deviceInfo = null;
VideoFormat formatoVideo = new VideoFormat(VideoFormat.RGB);
Vector deviceList = CaptureDeviceManager.getDeviceList(formatoVideo);
if(deviceList.size()>0)
{
deviceInfo = (CaptureDeviceInfo)deviceList.elementAt(0);
}
//MediaLocator ml = new MediaLocator("vfw://0");
MediaLocator ml = deviceInfo.getLocator(); //MediaLocator della webcam
//String sloc = "file:E:\\Documents and Settings\\Antonio\\Desktop\\Antonio\\Video\\Media( luglio)\\testcam04.avi";
//MediaLocator ml = new MediaLocator(sloc);
String IPaddr = "192.168.122.68";
String NumPort = "1550";
// Create a video transmit object with the specified params.
VideoTransmit vt = new VideoTransmit(ml,IPaddr,NumPort);
// Start the transmission
String result = vt.start();
// result will be non-null if there was an error. The return
// value is a String describing the possible error. Print it.
if (result != null) {
System.err.println("Error : " + result);
System.exit(0);
}
System.err.println("Start transmission for 60 seconds...");
// Transmit for 60 seconds and then close the processor
// This is a safeguard when using a capture data source
// so that the capture device will be properly released
// before quitting.
// The right thing to do would be to have a GUI with a
// "Stop" button that would call stop on VideoTransmit
try {
Thread.currentThread().sleep(60000);
} catch (InterruptedException ie) {
}
// Stop the transmission
vt.stop();
System.err.println("...transmission ended.");
System.exit(0);
}
}