Java 通过网络发送数据包

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

我正在用ffmpeg编码器生成AV数据包,现在我想用UDP将它们发送到另一台计算机,并在那里显示它们。 问题是我不知道如何将数据包转换成字节并返回。我尝试了以下方法来复制包:

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);