使用 Image.FromStream() 时出现“参数无效”异常 - UDP 视频直播流

问题描述 投票:0回答:1

我正在尝试使用 UDP 将摄像头从 Raspberry pi 直播到 PC。我按照Picamera2库提供的示例代码使用python发送直播数据,并使用C# WinForms

PictureBox
在PC上显示直播。

C# 应用程序收到数据字节数组后,我将使用内存流和

Image.FromStream()
将字节数组转换为图像。但是,这会引发“参数无效”异常。

Python代码(服务器):

host = #IP Address
port = 24325

with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as server_socket:
    # Initial connection
    server_socket.bind((host, port))
    print("UDP Server is listening...")

    while True:
        data, addr = server_socket.recvfrom(1024)
        rx = data.decode()

        ## Protocol Code...
        # if...

        # Stream code
        elif rx == "STREAM":
            tx = "STREAMING"
            server_socket.sendto(tx.encode(), addr)
                
            print("Starting stream")
                
            # Note: 2 cameras are being used on the Pi but only 1 is being streamed for testing
            picam1 = Picamera2(0)
            picam2 = Picamera2(1)
                
            config1 = picam1.create_preview_configuration()
            config2 = picam2.create_preview_configuration()
            picam1.configure(config1)
            picam2.configure(config2)

            picam1.controls.ExposureTime = 30000
            picam2.controls.ExposureTime = 30000
            encoder = H264Encoder(1000000)
                
            server_socket.connect(addr)
                
            stream = server_socket.makefile("wb")
            picam1.start_recording(encoder, FileOutput(stream))
        else:
            print(f"Recieved from {addr}: {rx}")
            tx = "Your message received"
            server_socket.sendto(tx.encode(), addr)

C# 代码(客户端):

// Connection code...
// Protocol code...

// Receive livestream data
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Any, 0);
bool isReceiving = true;

if (rx == "STREAMING")
{
    logToConsole("Stream started");    // Custom function

    try
    {
        while (isReceiving)
        {
            byte[] streamData = udpClient.Receive(ref serverEndPoint);

            using (MemoryStream ms = new MemoryStream(streamData))
            {
                Image receivedImage = Image.FromStream(ms);

                if (receivedImage != null)
                {
                    pictureBoxStream.Invoke(new Action(() => pictureBoxStream.Image = receivedImage));
                }
            }
        }
    }
    catch (Exception ex)
    {
        logToConsole("Error receiving video stream: " + ex.Message);
    }
}

python c# udp memorystream
1个回答
0
投票

我不是Python开发人员,所以我可能误解了一些东西,但在我看来,存在几个基本问题:

无消息重组

UDP 数据包的最大大小约为 65kb。接收方假设每个数据包都是一个完整的帧,除非图像非常小,否则无法保证这一点。通常,您会在 UDP 之上定义一个协议,该协议允许您发送和重组更大的消息,以及处理无序数据包传送等问题。

无需减压

看起来python代码使用了h264压缩,但是c#上没有任何东西可以解码这样的视频流。

Image.FromStream
应该处理最常见的 图像格式,例如 jpeg 和 png,但您将需要第三方解码器来处理大多数类型的真实视频流。

过早处置河流

来自Image.FromStream

的文档

您必须在图像的生命周期内保持流打开。

所以删除

using

推荐

我建议使用一些现有的协议。 实时流协议可能是一个不错的选择,它构建在UDP之上,并且应该内置处理丢失数据包、乱序交付等的功能。

另一种选择可能是一些简单的东西,例如通过 http、gRCP 或类似的发送 jpeg 帧,这应该保证可靠的传输并且应该相当容易使用。

© www.soinside.com 2019 - 2024. All rights reserved.