我对你的那个jfm的rtp视频聊天稍微改了点,在接收端就无法接受视频信息了,请问是怎么回事?

RanShW 发布于 2013/04/21 11:18
阅读 708
收藏 0
JMF

@leo-H 你好,想跟你请教个问题:我对你的那个jfm的rtp视频聊天稍微改了点,在接收端就无法接受视频信息了,请问是怎么回事?如下:


Sender.java
package testRTP2;



import java.awt.Dimension;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Vector;

import javax.media.CaptureDeviceInfo;
import javax.media.CaptureDeviceManager;
import javax.media.Codec;
import javax.media.Control;
import javax.media.Format;
import javax.media.Manager;
import javax.media.NoProcessorException;
import javax.media.Owned;
import javax.media.Processor;
import javax.media.control.FormatControl;
import javax.media.control.QualityControl;
import javax.media.control.TrackControl;
import javax.media.format.AudioFormat;
import javax.media.format.UnsupportedFormatException;
import javax.media.format.VideoFormat;
import javax.media.protocol.ContentDescriptor;
import javax.media.protocol.DataSource;
import javax.media.protocol.PushBufferDataSource;
import javax.media.protocol.PushBufferStream;
import javax.media.rtp.InvalidSessionAddressException;
import javax.media.rtp.RTPManager;
import javax.media.rtp.SendStream;
import javax.media.rtp.SessionAddress;

public class Sender {
	
	public static void main(String[] args) {	
		try {//设置本地地址和远端地址都为本机地址,自己传给自己,试验用
			SessionAddress local = new SessionAddress(InetAddress.getLocalHost(),50000);
			SessionAddress target = new SessionAddress(InetAddress.getLocalHost(),60000);		
			new Sender(local,target);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}		
	       }
        public Sender(SessionAddress local,SessionAddress target) {
                 Vector<CaptureDeviceInfo> deviceList = CaptureDeviceManager.getDeviceList(null); //就改了这
CaptureDeviceInfo info = (CaptureDeviceInfo) deviceList.firstElement();
		 
//		CaptureDeviceInfo info=CaptureDeviceManager.getDevice(str);

//		CaptureDeviceInfo info = (CaptureDeviceInfo) CaptureDeviceManager.getDeviceList(new VideoFormat(null)).get(0);
//		CaptureDeviceInfo info = (CaptureDeviceInfo) CaptureDeviceManager.getDeviceList(new AudioFormat(null)).get(0);用这一句替换上一句可改成音频传输
		Processor p = null;
		try {
			p = Manager.createProcessor(info.getLocator());
		} catch (NoProcessorException | IOException e) {
			e.printStackTrace();
		}
		StateHelper sh = new StateHelper(p);
		
		doSomeVideoProcess(p,sh);
//		doSomeAudioProcess(p,sh);用这一句替换上一句可改成音频传输
		RTPManager mgr = RTPManager.newInstance();//RTP管理器实例化
		try {//分别将本机和目的机IP地址加入至RTP会话管理器
			mgr.initialize(local);
			mgr.addTarget(target);
		} catch (InvalidSessionAddressException | IOException e) {
			e.printStackTrace();
		}
		
		DataSource ds = p.getDataOutput();
		PushBufferDataSource pbds = (PushBufferDataSource)ds;
	    PushBufferStream pbss[] = pbds.getStreams();
	    for(int i=0;i<pbss.length;i++) {
			try {
				SendStream ss = mgr.createSendStream(ds, i);//产生第i条轨道的传输流
				ss.start();//传输流开始
			} catch (UnsupportedFormatException | IOException e) {
				e.printStackTrace();
			}
	    }
	    p.start();
	    try {
			Thread.sleep(60000);//传送一分钟后关闭
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	    if(p!=null) {
			p.stop();
			p.close();
		}
		if(mgr!=null) {
			mgr.removeTargets("client disconnnected");
			mgr.dispose();
			mgr = null;
		}
	}	
	private static void doSomeVideoProcess(Processor p,StateHelper sh) {
		sh.configure(5000);
		p.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW_RTP));
		setVideoTrackFormat(p.getTrackControls());		
		sh.realize(5000);
		setJPEGQuality(p, 0.5f);
	}
	private static void doSomeAudioProcess(Processor p,StateHelper sh) {
		sh.configure(5000);
		p.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW));
		setAudioTrackFormat(p.getTrackControls());		
		sh.realize(5000);
	}
	private static 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)) {
	        // For JPEG, make sure width and height are divisible by 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)) {
	        // For H.263, we only support some specific sizes.
	        if (size.width < 128) {
		        width = 128;
		        height = 96;
	        } else if (size.width < 176) {
		        width = 176;
		        height = 144;
	        } else {
		        width = 352;
		        height = 288;
	        }
	    } else {
	    	// We don't know this particular format.  We'll just
	        // leave it alone then.
	        return supported;	        
	    }
	    return (new VideoFormat(null, 
                new Dimension(width, height), 
                Format.NOT_SPECIFIED,
                null,
                Format.NOT_SPECIFIED)).intersects(supported);
	}
	private static void setAudioTrackFormat(TrackControl[] trackControls) {
		boolean ok = false;
	    for(TrackControl t:trackControls){
	    	if(!ok && t instanceof FormatControl) {
	    		if(((FormatControl)t).setFormat(new AudioFormat(AudioFormat.ULAW_RTP,8000,8,1))==null) 
	    			t.setEnabled(false);
	    		 else 
	    			ok = true;	    		
	    	} else {
	    		t.setEnabled(false);
	    	}
	    }
	}
	private static boolean setVideoTrackFormat(TrackControl[] tracks) {
		if(tracks==null || tracks.length<1)
			return false;
		boolean atLeastOneTrack = false;
		for(TrackControl t:tracks) {
			if(t.isEnabled()) {
				Format[] supported = t.getSupportedFormats();
				Format chosen = null;
				if(supported.length>0) {
					if(supported[0] instanceof VideoFormat)
						chosen = checkForVideoSizes(t.getFormat(),supported[0]);
					else
						chosen = supported[0];					
					t.setFormat(chosen);
					atLeastOneTrack = true;
				} else {
					t.setEnabled(false);
				}
			} else {
				t.setEnabled(false);
			}
		}
		return atLeastOneTrack;
	}	
	private static void setJPEGQuality(Processor 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);	                
		                break;
		            }
	            }
	        }
	        if (qc != null)
	            break;
	        }
	    }
	}
	
}
Receiver.java:



package testRTP2;


import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.Manager;
import javax.media.NoPlayerException;
import javax.media.Player;
import javax.media.RealizeCompleteEvent;
import javax.media.control.BufferControl;
import javax.media.protocol.DataSource;
import javax.media.rtp.InvalidSessionAddressException;
import javax.media.rtp.RTPManager;
import javax.media.rtp.ReceiveStream;
import javax.media.rtp.ReceiveStreamListener;
import javax.media.rtp.SessionAddress;
import javax.media.rtp.event.ByeEvent;
import javax.media.rtp.event.NewReceiveStreamEvent;
import javax.media.rtp.event.ReceiveStreamEvent;
import javax.media.rtp.event.StreamMappedEvent;
import javax.swing.JFrame;

public class Receiver extends JFrame implements ReceiveStreamListener,ControllerListener{
	
	public static void main(String[] args) {
		try {
			SessionAddress local = new SessionAddress(InetAddress.getLocalHost(),60000);
			SessionAddress target = new SessionAddress(InetAddress.getLocalHost(),50000);		
			new Receiver(local,target);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		}		
	}
	
	public Receiver(SessionAddress local, SessionAddress target) {
		mgr = RTPManager.newInstance();
		mgr.addReceiveStreamListener(this);
		try {
			mgr.initialize(local);
			mgr.addTarget(target);
		} catch (InvalidSessionAddressException | IOException e) {
			e.printStackTrace();
		}
		BufferControl bc = (BufferControl)mgr.getControl("javax.media.control.BufferControl");
        if (bc != null)
            bc.setBufferLength(350);
        addWindowListener(new WindowAdapter() {
        	@Override
        	public void windowClosing(WindowEvent e) {
        		disconnect();
        	}
		});
        setSize(500,400);
        setLocation(350,250);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setVisible(true);
	}
	@Override
	public void update(ReceiveStreamEvent e) {
		System.out.println(e.getSource());
		System.out.println(e.getParticipant());
		if(e instanceof NewReceiveStreamEvent) {//为什么在这获取不到?
			ReceiveStream rs = ((NewReceiveStreamEvent)e).getReceiveStream();
			//System.out.println(rs.getDataSource());
			DataSource ds = rs.getDataSource();
			try {
				System.out.println(ds.getLocator());
				player = Manager.createPlayer(ds);
			} catch (NoPlayerException | IOException e1) {
				e1.printStackTrace();
			}
			player.addControllerListener(this);
			player.start();	}
			else if(e instanceof StreamMappedEvent)//在这加入了这个else if后执行的是这个
			{
				System.out.println("null datasource");
			}
		 else if(e instanceof ByeEvent) {
			disconnect();
		}
	}
	public void disconnect() {
		if(player!=null) {
			player.stop();
			player.close();
		}
		if(mgr!=null) {
			mgr.removeTargets("closing session");
			mgr.dispose();
			mgr = null;
		}		
	}
	@Override
	public void controllerUpdate(ControllerEvent e) {
		if(e instanceof RealizeCompleteEvent) {
			if(player.getVisualComponent()!=null)
				add(player.getVisualComponent());
			if(player.getControlPanelComponent()!=null)
				add(player.getControlPanelComponent(),BorderLayout.SOUTH);
			pack();
		}
	}
	Player player;
	RTPManager mgr;
	
}

StateHelper.java

import javax.media.*;

public class StateHelper implements ControllerListener{

	public StateHelper (Player p) {
		player = p;
		p.addControllerListener(this);
	}
	
	public boolean configure (int timeOutMillis) {
		long startTime = System.currentTimeMillis();
		synchronized (this) {
			if (player instanceof Processor)
				((Processor)player).configure();
			else 
				return false;
			while(!configured && !failed) {
				try {
					wait(timeOutMillis);
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
				if(System.currentTimeMillis() - startTime > timeOutMillis)
					break;
			}
		}
		return configured;
	}
	
	public boolean prefetch(int timeOutMillis) {
		long startTime = System.currentTimeMillis();
		synchronized (this) {
			player.prefetch();
			while(!prefetched && !failed) {
				try {
					wait(timeOutMillis);
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
				if(System.currentTimeMillis() - startTime > timeOutMillis)
					break;
			}
		}
		return prefetched && !failed;
	}
	
	public boolean realize(int timeOutMillis) {
		long startTime = System.currentTimeMillis();
		synchronized (this) {
			player.realize();
			while(!realized && !failed) {
				try {
					wait(timeOutMillis);
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
				if(System.currentTimeMillis() - startTime > timeOutMillis)
					break;
			}
		}
		return realized;
	}
	
	public boolean playToEndOfMedia(int timeOutMillis) {
		long startTime = System.currentTimeMillis();
		eom = false;
		synchronized (this) {
			player.start();
			while(!eom && !failed) {
				try {
					wait(timeOutMillis);
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
				if(System.currentTimeMillis() - startTime > timeOutMillis)
					break;
			}
		}
		return eom && !failed;
	}
	
	public void close() {
		synchronized (this) {
			player.close();
			while(!closed) {
				try {
					wait(100);
				} catch (InterruptedException e) {
					// TODO: handle exception
				}
			}
		}
		player.removeControllerListener(this);
	}
	
	@Override
	public synchronized void controllerUpdate(ControllerEvent e) {
		if(e instanceof RealizeCompleteEvent) {
			realized = true;
		} else if(e instanceof ConfigureCompleteEvent) {
			configured = true;
		} else if(e instanceof PrefetchCompleteEvent) {
			prefetched = true;
		} else if(e instanceof EndOfMediaEvent) {
			eom = true;
		} else if(e instanceof ControllerErrorEvent) {
			failed = true;
		} else if(e instanceof ControllerClosedEvent) {
			closed = true;
		} else {
			return;
		}
		notifyAll();		
	}
		
	boolean configured = false;
	boolean realized = false;
	boolean prefetched = false;
	boolean closed = false;
	boolean failed = false;
	boolean eom = false;
	
	Player player = null;
}

真的不好意思麻烦您,这个环节是我做毕业设计的关键环节。希望您能指点迷津,真心感谢!

以下是问题补充:

@RanShW:或许接收端可以接受,但是视频播放不出来,SENDER处的修改是为了使用本地的USEB摄像头。是哪出了问题呢? (2013/04/21 16:54)
@RanShW:我觉得问题可能出在Receiver的获取播放器的VisualComponent上,因为当前获取到的是空值,无法将播放器组件添加到面板上,是么? (2013/04/21 17:15)
加载中
0
leo-H
leo-H
不好意思,我也不是很懂。你搜索 StreamMappedEvent似乎有一些结果
R
RanShW
恩,好吧 ,还是很感谢你提供这段代码和你的回复~
返回顶部
顶部