请教个问题:我对网上的一个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(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;
}
}
}
}
相关推荐
基于混合储能协调控制的三相并网逆变系统设计【附说明文档】
内容概要:本文围绕“基于混合储能协调控制的三相并网逆变系统设计”展开,系统阐述了蓄电池与飞轮储能等混合储能系统在微电网中的协同控制策略。研究涵盖三相并网逆变器的能量管理、SOC(荷电状态)恒压恒流充放电控制、PQ控制与双闭环控制等核心技术,并基于Matlab/Simulink仿真平台实现了系统建模与动态仿真验证。文中深入探讨了飞轮储能系统的机侧PQ控制与网侧变流器的恒压双闭环控制,分析了微电网在调频调峰、功率协同分配等方面的运行特性,强调多能源间的协调优化与系统的快速动态响应能力,旨在提升微电网的运行稳定性、电能质量及能源利用效率。; 适合人群:具备电力电子、自动化或电气工程等相关专业背景,从事新能源发电、微电网控制、储能系统集成与优化等领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入研究混合储能系统在微电网中的协调控制机制与能量管理策略;②掌握三相并网逆变器的建模、控制算法设计及Matlab/Simulink仿真方法;③实现储能系统的高效充放电管理与并网功率精确控制;④为学术论文撰写、科研课题申报、工程项目开发或实验复现提供完整的技术方案与参考实例。; 阅读建议:建议结合所提供的仿真模型、说明文档及参考文献,按照系统架构从单元控制到整体协调的顺序分模块学习,重点关注各控制策略的设计原理、参数整定方法与协同逻辑。推荐在Matlab环境中动手复现仿真,通过调整参数和工况来观察系统响应,以深化对理论知识的理解和工程应用能力的掌握。
科技中介服务机构在服务企业时,如何通过平台降低服务门槛和操作复杂度?.docx
科技中介服务机构在服务企业时,如何通过平台降低服务门槛和操作复杂度?
运维管理基于Hyperfilelens的Docker Compose业务系统备份恢复:机房设备更换场景下的数据迁移与验证方案设计
内容概要:本文介绍了在机房存储设备更换及固件升级背景下,通过 Hyperfilelens 实现多套 Docker Compose 部署的业务系统备份与恢复的全过程。文章围绕备份迁移的实际操作,详细阐述了从主机接入、备份路径选择、策略配置、恢复执行到业务验证的七个关键步骤,并结合截图说明各环节的操作要点。特别强调了不仅要完成数据备份与恢复,还需核对目录结构、服务启动状态和业务功能可用性,确保迁移后系统完整可用。最终总结了 Hyperfilelens 在集中管理保护对象、制定备份策略、明确恢复目标和提供可核查记录方面的核心价值,倡导将备份作为常态化运维机制而非临时应急措施。; 适合人群:从事运维、系统管理及相关技术岗位,具备一定 Docker 和服务器管理经验的技术人员,尤其是面临机房设备更新或系统迁移任务的团队成员。; 使用场景及目标:①解决老旧存储设备更换过程中的业务系统平滑迁移问题;②实现基于 Docker Compose 架构的应用数据可靠备份与异机恢复;③建立可复用的备份恢复流程,提升运维自动化与可靠性。; 阅读建议:建议结合文中提到的平台界面和操作命令逐步实践,重点关注备份范围确认、一致性保护、恢复路径核对及业务端到端验证,避免仅依赖工具状态而忽视实际业务可用性。
chromedriver-mac-arm64-158.0.8127.18(Beta).zip
chromedriver-mac-arm64-158.0.8127.18(Beta).zip
政府科技管理者在推动区域科技成果转化时,如何实现科技成果与产业需求的精准对接?.docx
科易网基于AI模型+行业大数据,在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,推出科技创新领域的AI+工具与数智化解决方案,推动科技创新与产业创新智能化发展。


