Witam, dzięki za zainteresowanie. Obiekt tej klasy jest budowany w klasie VideoReceive. Podkreślam, że uruchamiając klase VideoReceive wykorzystując metode "main" czy też inicjując obiekt tej klasy w osobnej klasie okno wyświetla się prawidłowo. Lecz gdy chce je wyświetlić jako okno "podrzędne" nie wiem czy można je tak w tym przypadku nazwać, nie wyświetlają się przyciski i JTextField'y oraz okno nie reaguje na zamknięcie.
Spróbuje to wyjaśnić jeszcze raz.
Mam klasę o nazwie RequestFrame w której tworze obiekt klasy VideoReceive(w niej jest budowany obiekt PlayerWindow) oraz obiekt VideoTransmit, który przesyła obraz z kamery. Po naciśnięciu przycisku prawie wszystko działa jedynie nie wyświetlają się przyciski oraz obraz z kamery zmniejsza się do odpowiedniego rozmiaru tak jak by nie reagowało na powiększenie ramki.
Dodam kod tych dwóch powyższych klas dla jasności.
KLASA VideoReceive:
package avchat;
import java.net.InetAddress;
import java.util.Vector;
import javax.media.*;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import javax.media.control.BufferControl;
import javax.media.protocol.DataSource;
/**
* VideoReceive odbiera sesje RTP.
*/
public class VideoReceive implements ReceiveStreamListener, SessionListener,
ControllerListener
{
public String[] sess = new String[1];
public RTPManager mgrs[] = null;
public Vector playerWindows = null;
boolean dataReceived = false;
Object dataSync = new Object();
public VideoReceive(String adress) {
this.sess[0] = adress;
}
public boolean initialize() {
try {
InetAddress ipAddr;
SessionAddress localAddr = new SessionAddress();
SessionAddress destAddr;
mgrs = new RTPManager[sess.length];
playerWindows = new Vector();
SessionLabel session;
//otwiera sesje RTP.
for (int i = 0; i < sess.length; i++) {
// Parse the session addresses.
try {
session = new SessionLabel(sess[i]);
} catch (IllegalArgumentException e) {
System.err.println("Failed to parse the session address given: " + sess[i]);
return false;
}
System.err.println(" - Open RTP session for: addr: " + session.addr + " port: " + session.port + " ttl: " + session.ttl);
mgrs[i] = (RTPManager) RTPManager.newInstance();
mgrs[i].addSessionListener(this);
mgrs[i].addReceiveStreamListener(this);
ipAddr = InetAddress.getByName(session.addr);
if( ipAddr.isMulticastAddress()) {
//lokalny i zdalny adres para jest identyczna:
localAddr= new SessionAddress( ipAddr,
session.port,
session.ttl);
destAddr = new SessionAddress( ipAddr,
session.port,
session.ttl);
} else {
localAddr= new SessionAddress( InetAddress.getLocalHost(),
session.port);
destAddr = new SessionAddress( ipAddr, session.port);
}
mgrs[i].initialize( localAddr);
//ustawienie bufora do plynnosci obrazu
// if you can get better smoothness.
BufferControl bc = (BufferControl)mgrs[i].getControl("javax.media.control.BufferControl");
if (bc != null)
bc.setBufferLength(350);
mgrs[i].addTarget(destAddr);
}
} catch (Exception e){
System.err.println("Cannot create the RTP Session: " + e.getMessage());
return false;
}
//czeka na dane zanim ruszysz dalej.
long then = System.currentTimeMillis();
long waitingPeriod = 60000; // wait for a maximum of 30 secs.
try{
synchronized (dataSync) {
while (!dataReceived &&
System.currentTimeMillis() - then < waitingPeriod) {
if (!dataReceived)
System.err.println(" - Waiting for RTP data to arrive...");
dataSync.wait(1000);
}
}
} catch (Exception e) {}
if (!dataReceived) {
System.err.println("No RTP data was received.");
close();
return false;
}
return true;
}
public boolean isDone() {
return playerWindows.size() == 0;
}
/**
* zamykanie player'a i menagera sesji
*/
public void close() {
for (int i = 0; i < playerWindows.size(); i++) {
try {
((PlayerWindow)playerWindows.elementAt(i)).close();
} catch (Exception e) {}
}
playerWindows.removeAllElements();
//zamykanie sesji RTP.
for (int i = 0; i < mgrs.length; i++) {
if (mgrs[i] != null) {
mgrs[i].removeTargets( "Closing session from AVReceive2");
mgrs[i].dispose();
mgrs[i] = null;
}
}
}
PlayerWindow find(Player p) {
for (int i = 0; i < playerWindows.size(); i++) {
PlayerWindow pw = (PlayerWindow)playerWindows.elementAt(i);
if (pw.player == p)
return pw;
}
return null;
}
PlayerWindow find(ReceiveStream strm) {
for (int i = 0; i < playerWindows.size(); i++) {
PlayerWindow pw = (PlayerWindow)playerWindows.elementAt(i);
if (pw.stream == strm)
return pw;
}
return null;
}
/**
* SessionListener.
*/
public synchronized void update(SessionEvent evt) {
if (evt instanceof NewParticipantEvent) {
Participant p = ((NewParticipantEvent)evt).getParticipant();
System.err.println(" - A new participant had just joined: " + p.getCNAME());
}
}
/**
* ReceiveStreamListener
*/
public synchronized void update( ReceiveStreamEvent evt) {
RTPManager mgr = (RTPManager)evt.getSource();
Participant participant = evt.getParticipant(); // could be null.
ReceiveStream stream = evt.getReceiveStream(); // could be null.
if (evt instanceof RemotePayloadChangeEvent) {
System.err.println(" - Received an RTP PayloadChangeEvent.");
System.err.println("Sorry, cannot handle payload change.");
System.exit(0);
}
else if (evt instanceof NewReceiveStreamEvent) {
try {
stream = ((NewReceiveStreamEvent)evt).getReceiveStream();
DataSource ds = stream.getDataSource();
//odsszukuje formaty.
RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
if (ctl != null){
System.err.println(" - Recevied new RTP stream: " + ctl.getFormat());
} else
System.err.println(" - Recevied new RTP stream");
if (participant == null)
System.err.println(" The sender of this stream had yet to be identified.");
else {
System.err.println(" The stream comes from: " + participant.getCNAME());
}
// create a player by passing datasource to the Media Manager
Player p = javax.media.Manager.createPlayer(ds);
if (p == null)
return;
p.addControllerListener(this);
p.realize();
PlayerWindow pw = new PlayerWindow(p, stream);
playerWindows.addElement(pw);
// Notify intialize() that a new stream had arrived.
synchronized (dataSync) {
dataReceived = true;
dataSync.notifyAll();
}
} catch (Exception e) {
System.err.println("NewReceiveStreamEvent exception " + e.getMessage());
return;
}
}
else if (evt instanceof StreamMappedEvent) {
if (stream != null && stream.getDataSource() != null) {
DataSource ds = stream.getDataSource();
//odszukuje odpowiedni format.
RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
System.err.println(" - The previously unidentified stream ");
if (ctl != null)
System.err.println(" " + ctl.getFormat());
System.err.println(" had now been identified as sent by: " + participant.getCNAME());
}
}
else if (evt instanceof ByeEvent) {
System.err.println(" - Got \"bye\" from: " + participant.getCNAME());
PlayerWindow pw = find(stream);
if (pw != null) {
pw.close();
playerWindows.removeElement(pw);
}
}
}
/**
* ControllerListener dla Players.
*/
public synchronized void controllerUpdate(ControllerEvent ce) {
Player p = (Player)ce.getSourceController();
if (p == null)
return;
// Get this when the internal players are realized.
if (ce instanceof RealizeCompleteEvent) {
PlayerWindow pw = find(p);
if (pw == null) {
//stalo sie cos dziwnego.
System.err.println("Internal error!");
System.exit(-1);
}
pw.initialize();
pw.setVisible(true);
p.start();
}
if (ce instanceof ControllerErrorEvent) {
p.removeControllerListener(this);
PlayerWindow pw = find(p);
if (pw != null) {
pw.close();
playerWindows.removeElement(pw);
}
System.err.println("AVReceive2 internal error: " + ce);
}
}
/**
* A utility class to parse the session addresses.
*/
class SessionLabel {
public String addr = null;
public int port;
public int ttl = 1;
SessionLabel(String session) throws IllegalArgumentException {
int off;
String portStr = null, ttlStr = null;
if (session != null && session.length() > 0) {
while (session.length() > 1 && session.charAt(0) == '/')
session = session.substring(1);
// Now see if there's a addr specified.
off = session.indexOf('/');
if (off == -1) {
if (!session.equals(""))
addr = session;
} else {
addr = session.substring(0, off);
session = session.substring(off + 1);
// Now see if there's a port specified
off = session.indexOf('/');
if (off == -1) {
if (!session.equals(""))
portStr = session;
} else {
portStr = session.substring(0, off);
session = session.substring(off + 1);
// Now see if there's a ttl specified
off = session.indexOf('/');
if (off == -1) {
if (!session.equals(""))
ttlStr = session;
} else {
ttlStr = session.substring(0, off);
}
}
}
}
if (addr == null)
throw new IllegalArgumentException();
if (portStr != null) {
try {
Integer integer = Integer.valueOf(portStr);
if (integer != null)
port = integer.intValue();
} catch (Throwable t) {
throw new IllegalArgumentException();
}
} else
throw new IllegalArgumentException();
if (ttlStr != null) {
try {
Integer integer = Integer.valueOf(ttlStr);
if (integer != null)
ttl = integer.intValue();
} catch (Throwable t) {
throw new IllegalArgumentException();
}
}
}
}
/*
public static void main(String argv[]) {
String adr = "10.10.1.84/42052";
VideoReceive avReceive = new VideoReceive(adr);
if (!avReceive.initialize()) {
System.err.println("Failed to initialize the sessions.");
System.exit(-1);
}
// sprawdza czy VideoReceive jest gotowe.
try {
while (!avReceive.isDone())
Thread.sleep(1000);
} catch (Exception e) {}
System.err.println("Exiting AVReceive2");
}
*
*/
}// end of VideoReceive
//http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/solutions/AVReceive.html
KLASA VideoTransmite:
package avchat;
import java.awt.*;
import java.io.*;
import java.net.InetAddress;
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 javax.media.rtp.*;
import javax.media.rtp.rtcp.*;
public class VideoTransmit {
// Input MediaLocator
// Can be a file or http or capture source
public MediaLocator locator;
public String ipAddress;
public int portBase;
private Processor processor = null;
private RTPManager rtpMgrs[];
private DataSource dataOutput = null;
public VideoTransmit(MediaLocator locator,
String ipAddress,
int pb,
Format format) {
this.locator = locator;
this.ipAddress = ipAddress;
Integer integer = Integer.valueOf(pb);
if (integer != null)
this.portBase = integer.intValue();
}
/**
* rozpoczyna transmisje. Zwraca zero jezeli transmija sie powiodla.
* w innym wypadku zwaraca Stringa z opise dlaczego sie nie powiodlo.
*/
public synchronized String start() {
String result;
//tworzy processor dla odpowiedniego media locatora
// i porgramuje go do wyjsciowego JPEG/RTP
result = createProcessor();
if (result != null)
return result;
// tworzy sesje RTP do transmiji wyjsciowej
// processora do okreslonego adresu IP i portu.
result = createTransmitter();
if (result != null) {
processor.close();
processor = null;
return result;
}
//rozpoczyna transmisje procesor
processor.start();
return null;
}
/**
* zatrzymuje transmije jezeli juz sie rozpoczela
*/
public void stop() {
synchronized (this) {
if (processor != null) {
processor.stop();
processor.close();
processor = null;
for (int i = 0; i < rtpMgrs.length; i++) {
rtpMgrs[i].removeTargets( "Session ended.");
rtpMgrs[i].dispose();
}
}
}
}
private String createProcessor() {
if (locator == null)
return "Locator is null";
DataSource ds;
DataSource clone;
try {
ds = javax.media.Manager.createDataSource(locator);
clone = ds;
} catch (Exception e) {
return "Couldn't create DataSource";
}
//prubuje stworzyc processor to handle the input media locator
try {
processor = javax.media.Manager.createProcessor(ds);
processor = javax.media.Manager.createProcessor(clone);
} catch (NoProcessorException npe) {
return "Couldn't create processor";
} catch (IOException ioe) {
return "IOException creating processor";
}
//czeka az sie skonfiguruje porcesor
boolean result = waitForState(processor, Processor.Configured);
if (result == false)
return "Couldn't configure processor";
// pobiera odpowiednia trase z porcesora
TrackControl [] tracks = processor.getTrackControls();
// sprawdza czy mamy juz odpowiedni tor?
if (tracks == null || tracks.length < 1)
return "Couldn't find tracks in processor";
// Set the output content descriptor to RAW_RTP
// This will limit the supported formats reported from
// Track.getSupportedFormats to only valid RTP formats.
ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
processor.setContentDescriptor(cd);
Format supported[];
Format chosen;
boolean atLeastOneTrack = false;
// programuje tracks.
for (int i = 0; i < tracks.length; i++) {
Format format = tracks[i].getFormat();
if (tracks[i].isEnabled()) {
supported = tracks[i].getSupportedFormats();
// We've set the output content to the RAW_RTP.
// So all the supported formats should work with RTP.
// We'll just pick the first one.
if (supported.length > 0) {
if (supported[0] instanceof VideoFormat) {
// dla formatow video, powinnismy sprawdzic dwa razy
// rozmiar poniewaz nie kazdy format obsluguje kazdy rozmiar.
chosen = checkForVideoSizes(tracks[i].getFormat(),
supported[0]);
} else
chosen = supported[0];
tracks[i].setFormat(chosen);
System.err.println("Track " + i + " is set to transmit as:");
System.err.println(" " + chosen);
atLeastOneTrack = true;
} else
tracks[i].setEnabled(false);
} else
tracks[i].setEnabled(false);
}
if (!atLeastOneTrack)
return "Couldn't set any of the tracks to a valid RTP format";
// uswiadamiamy processor. This will internally create a flow
// graph and attempt to create an output datasource for JPEG/RTP
// audio frames.
result = waitForState(processor, Controller.Realized);
if (result == false)
return "Couldn't realize processor";
// ustawia JPEG jakosc na 0.5.
setJPEGQuality(processor, 0.5f);
//pobiera wyjsciowe zrodlo danych processora
dataOutput = processor.getDataOutput();
return null;
}
/**
* Use the RTPManager API to create sessions for each media
* track of the processor.
*/
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 VideoTransmit 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(), SessionAddress.ANY_PORT );
destAddr = new SessionAddress( ipAddr, port);
// if(localAddr != destAddr) {
//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);
sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
sendStream.start();
} catch (Exception e) {
return e.getMessage();
}
}
return null;
}
/**
* dla JPEG i H263, wiemy ze pracuja tylko na okreslonym rozmiarze
* dlatego sprawdzamy czy okreslone formaty pracuja na dedykowanych rozmiarach
*/
Format checkForVideoSizes(Format original, Format supported) {
int width, height;
Dimension size = ((VideoFormat)original).getSize();
Format jpegFmt = new Format(VideoFormat.JPEG_RTP);
Format h263Fmt = new Format(VideoFormat.H263_RTP);
if (supported.matches(jpegFmt)) {
// dla JPEG, upewniamy sie czy szerokosc i wysokosc sa podzielne przez 8.
width = (size.width % 8 == 0 ? size.width :
(int)(size.width / 8) * 8);
height = (size.height % 8 == 0 ? size.height :
(int)(size.height / 8) * 8);
} else if (supported.matches(h263Fmt)) {
// dla H.263, wspieramy tylko okreslony rozmiar.
if (size.width < 128) {
width = 128;
height = 96;
} else if (size.width < 176) {
width = 176;
height = 144;
} else {
width = 352;
height = 288;
}
} else {
// Jezeli nie wiadomo jaki jest format video, pozostawiamy go bez zmian
return supported;
}
return (new VideoFormat(null,
new Dimension(width, height),
Format.NOT_SPECIFIED,
null,
Format.NOT_SPECIFIED)).intersects(supported);
}
/**
* 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) {
// jezeli wystapil blad podczas konfiguracji uswiadamiania
// (realize), procesor zostanie zamkniety
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) {
Format fmt = new Format(VideoFormat.H263_RTP);
int i = 0;
// Create a audio transmit object with the specified params.
VideoTransmit at = new VideoTransmit(new MediaLocator("vfw://0"),
"10.10.1.84", 42052, fmt);
// Start the transmission
String result = at.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(6000000);
} catch (InterruptedException ie) {
}
// Stop the transmission
at.stop();
System.err.println("...transmission ended.");
System.exit(0);
}
*
*/
}
//http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/solutions/AVTransmit.html