Java 通过网络发送数据包
我正在用ffmpeg编码器生成AV数据包,现在我想用UDP将它们发送到另一台计算机,并在那里显示它们。 问题是我不知道如何将数据包转换成字节并返回。我尝试了以下方法来复制包:Java 通过网络发送数据包,java,ffmpeg,Java,Ffmpeg,我正在用ffmpeg编码器生成AV数据包,现在我想用UDP将它们发送到另一台计算机,并在那里显示它们。 问题是我不知道如何将数据包转换成字节并返回。我尝试了以下方法来复制包: AVPacket newPacket = avcodec.av_packet_alloc(); ByteBuffer byteBuffer = packet.buf().buffer().asByteBuffer(); int bufferSize = byteBuffer.capacity(); byte bytes
AVPacket newPacket = avcodec.av_packet_alloc();
ByteBuffer byteBuffer = packet.buf().buffer().asByteBuffer();
int bufferSize = byteBuffer.capacity();
byte bytes[] = new byte[bufferSize];
byteBuffer.get(bytes);
AVBufferRef newBufferRef = avutil.av_buffer_alloc(bufferSize);
newBufferRef.data(new BytePointer(bytes));
newPacket.buf(newBufferRef);
ByteBuffer dataBuffer = packet.data().asByteBuffer();
int dataSize = dataBuffer.capacity();
byte dataBytes[] = new byte[dataSize];
dataBuffer.get(dataBytes);
BytePointer dataPointer = new BytePointer(dataBytes);
newPacket.data(dataPointer);
newPacket.dts(packet.dts());
newPacket.duration(packet.duration());
newPacket.flags(packet.flags());
newPacket.pos(packet.pos());
newPacket.pts(packet.pts());
newPacket.side_data_elems(0);
newPacket.size(packet.size());
newPacket.stream_index(packet.stream_index());
videoPlayer.sendPacket(newPacket);
这给了我一个错误:
[h264 @ 0000018951be8440] Invalid NAL unit size (3290676 > 77).
[h264 @ 0000018951be8440] Error splitting the input into NAL units.
[h264 @ 0000018951bf6480] Invalid NAL unit size (15305314 > 163).
[h264 @ 0000018951bf6480] Error splitting the input into NAL units.
问题是newPacket.data()
。直接设置时:newPacket.data(packet.data())
它起作用了。另外,packet.data().asByteBuffer().capacity()
返回1,packet.data().capacity()
返回0
这是我创建解码器的方法:
private void startUnsafe() throws Exception
{
int result;
convertContext = null;
codec = null;
codecContext = null;
AVFrame = null;
RGBAVFrame = null;
frame = new Frame();
codec = avcodec_find_decoder(codecID);
if(codec == null)
{
throw new Exception("Unable to find decoder");
}
codecContext = avcodec_alloc_context3(codec);
if(codecContext == null)
{
releaseUnsafe();
throw new Exception("Unable to alloc codec context!");
}
AVCodecParameters para = avcodec_parameters_alloc();
para.bit_rate(streamBitrate);
para.width(streamWidth);
para.height(streamHeight);
para.codec_id(codecID);
para.codec_type(AVMEDIA_TYPE_VIDEO);
try
{
byte extradataByte[] = Files.readAllBytes(new File("extradata.byte").toPath());
para.extradata(new BytePointer(extradataByte));
para.extradata_size(extradataByte.length);
}
catch (IOException e1)
{
e1.printStackTrace();
throw new Exception("extradata file not available");
}
result = avcodec_parameters_to_context(codecContext, para);
if(result < 0)
{
throw new Exception("Unable to copy parameters to context! [" + result + "]");
}
codecContext.thread_count(0);
result = avcodec_open2(codecContext, codec, new AVDictionary());
if(result < 0)
{
releaseUnsafe();
throw new Exception("Unable to open codec context![" + result + "]");
}
AVFrame = av_frame_alloc();
if(AVFrame == null)
{
releaseUnsafe();
throw new Exception("Unable to alloc AVFrame!");
}
RGBAVFrame = av_frame_alloc();
if(RGBAVFrame == null)
{
releaseUnsafe();
throw new Exception("Unable to alloc AVFrame!");
}
initRGBAVFrame();
TimerTask task = new TimerTask() {
@Override
public void run()
{
timerTask();
}
};
timer = new Timer();
timer.scheduleAtFixedRate(task, 0, (long) (1000/streamFramerateDouble));
window.setVisible(true);
}
我想这是因为我没有设置sidedata字段,但是当我试图设置它时,编码器会与第二个数据包崩溃
输出如下所示:
< p>调用to <代码> avBase.DATA()/CUT>返回<代码> BytePointer < /C> >,它是本地C++指针的包装器。没有与指针关联的容量信息,这意味着您需要手动设置容量。您可能需要以下内容:
int packetSize = packet.size();
ByteBuffer dataBuffer = packet.data().capacity(packetSize).asByteBuffer();
我找到了一个适合我的解决方案 AVFrame到字节:
int dataSize = packet.size();
ByteBuffer dataBuffer = packet.data().capacity(dataSize).asByteBuffer();
byte dataBytes[] = new byte[dataSize];
dataBuffer.get(dataBytes);
AVPacketSideData sideData = packet.side_data();
int sideSize = sideData.size();
ByteBuffer sideBuffer = sideData.data().capacity(sideSize).asByteBuffer();
byte sideBytes[] = new byte[sideSize];
sideBuffer.get(sideBytes);
int sideType = sideData.type();
int sideElements = packet.side_data_elems();
long dts = packet.dts();
long pts = packet.pts();
int flags = packet.flags();
返回到AVFrame的字节数:
packet = avcodec.av_packet_alloc();
packet.pts(pts);
packet.dts(dts);
packet.flags(flags);
Pointer newDataPointer = avutil.av_malloc(dataSize);
BytePointer dataPointer = new BytePointer(newDataPointer);
dataPointer.put(dataBytes);
packet.data(dataPointer);
packet.size(dataSize);
Pointer newSidePointer = avutil.av_malloc(sideSize);
BytePointer sidePointer = new BytePointer(newSidePointer);
sidePointer.put(sideBytes);
BytePointer sideDataPointer = avcodec.av_packet_new_side_data(packet, sideType, sideSize);
AVPacketSideData sideData = new AVPacketSideData(sideDataPointer);
sideData.data(sidePointer);
sideData.type(sideType);
sideData.size(sideSize);
packet.side_data(sideData);
packet.side_data_elems(sideElements);
这给了我这个错误是什么?发送端还是接收端?视频播放器是什么类型的?
videoPlayer
如何序列化元数据?接收需要什么协议?videoPlayer是我自己的类,它创建一个JFrame,并使用“int result=avcodec\u send\u packet(codecContext,packet)”将新数据包直接发送到编码器代码>,结果
为-1094995529,上面的错误将打印到控制台。目前,我只是尝试将数据包转换成字节,然后再转换回来,而不通过网络发送数据包。现在它有时可以工作。解码器几乎每秒返回一次数据包-1094995529
,我将此错误打印到控制台:将输入拆分为NAL单位时出错。找不到启动代码。将输入拆分为NAL单位时出错。缺少参考图片,默认为65580参考图片在重新订购mmco期间丢失:unref短路故障参考3>=2解码MB 107 13时出错,bytestream 35在重新订购mmco期间隐藏B帧参考图片中的6542 DC、6542 AC、6542 MV错误:unref短路故障
,我发现,当我只设置新数据包的data()
和size()
字段时,得到相同的结果。所以我不需要设置dts,pts。。。
int dataSize = packet.size();
ByteBuffer dataBuffer = packet.data().capacity(dataSize).asByteBuffer();
byte dataBytes[] = new byte[dataSize];
dataBuffer.get(dataBytes);
AVPacketSideData sideData = packet.side_data();
int sideSize = sideData.size();
ByteBuffer sideBuffer = sideData.data().capacity(sideSize).asByteBuffer();
byte sideBytes[] = new byte[sideSize];
sideBuffer.get(sideBytes);
int sideType = sideData.type();
int sideElements = packet.side_data_elems();
long dts = packet.dts();
long pts = packet.pts();
int flags = packet.flags();
packet = avcodec.av_packet_alloc();
packet.pts(pts);
packet.dts(dts);
packet.flags(flags);
Pointer newDataPointer = avutil.av_malloc(dataSize);
BytePointer dataPointer = new BytePointer(newDataPointer);
dataPointer.put(dataBytes);
packet.data(dataPointer);
packet.size(dataSize);
Pointer newSidePointer = avutil.av_malloc(sideSize);
BytePointer sidePointer = new BytePointer(newSidePointer);
sidePointer.put(sideBytes);
BytePointer sideDataPointer = avcodec.av_packet_new_side_data(packet, sideType, sideSize);
AVPacketSideData sideData = new AVPacketSideData(sideDataPointer);
sideData.data(sidePointer);
sideData.type(sideType);
sideData.size(sideSize);
packet.side_data(sideData);
packet.side_data_elems(sideElements);