【问题标题】:Trying to read MJPEG header in C#尝试在 C# 中读取 MJPEG 标头
【发布时间】:2013-09-27 15:48:37
【问题描述】:

是否有人熟悉在通过 HTTP 协议发送的 MJPEG 文件中提取标头的方法?我在 C# 中遇到过 HttpClient 类,但我对它缺乏经验,而且我还没有看到任何有关 MJPEG 流的示例。感谢您的帮助。

【问题讨论】:

    标签: c# http stream mjpeg dotnet-httpclient


    【解决方案1】:

    我不是专家,但我认为 MJPEG 流是包含在两个字节中的单个 JPEG 图片流:FFD8 和 FFD9。

    使用优化的裸 C# 模块(如数组、测试和循环),您可以解析调用 HttpClient 返回的流以剥离其 JPEG 帧。

    这是一个快速、简单和愚蠢的显示流的东西。唯一的幻想是使用 HttpClient 及其异步函数:

    async static Task Start(string url, Action<byte[]> action, int bufSize = 1024, CancellationToken? tk = null) {
    
        var myTk = tk.HasValue ? tk.Value : CancellationToken.None;
    
        using(var cli = new HttpClient()) {
    
            var streamBuffer = new byte[bufSize];
    
            // Give it the maximum size in bytes of your picture
            var frameBuffer = new List<byte>(1024 * 1024);
    
            var ff = false;
            var inPic = false;
    
            using(var stream = await cli.GetStreamAsync(url).ConfigureAwait(false)) {
    
                while(!myTk.IsCancellationRequested) {
    
                    var l = await stream.ReadAsync(streamBuffer, 0, bufSize).ConfigureAwait(false);
                    var idx = 0;
    
                    while(idx < l) {
                        var c = streamBuffer[idx++];
    
                        // We have found a FF
                        if(c == 0xff) {
                            ff = true;
                        }
                        // We found a JPEG picture start
                        else if(ff && c == 0xd8) {
                            frameBuffer.Clear();
                            frameBuffer.Add(0xff);
                            frameBuffer.Add(0xd8);
                            if(inPic) {
                                Console.WriteLine("Skipped frame : end expected");
                            }
                            ff = false;
                            inPic = true;
                        }
                        // We found a JPEG picture end
                        else if(ff && c == 0xd9) {
                            frameBuffer.Add(0xff);
                            frameBuffer.Add(0xd9);
    
                            // Send the JPEG picture as an event
                            action(frameBuffer.ToArray());
    
                            ff = false;
                            if(!inPic) {
                                Console.WriteLine("Skipped frame : start expected");
                            }
                            inPic = false;
                        }
                        // We are inside a JPEG picture
                        else if(inPic) {
                            if(ff) {
                                frameBuffer.Add(0xff);
                                ff = false;
                            }
                            frameBuffer.Add(c);
                        }
                    }
                }
            }
        }
    }
    

    尝试一下,在 Winforms 应用程序中使用 PictureBox,然后在 button_click 中使用:

    var s = SynchronizationContext.Current;
    
    // assuming pb is your PictureBox
    
    await Start("http://whateverurlthatstreamsmjpegs.com", 
        img => {
            s.Post(new SendOrPostCallback(i => {
                if(pb.Image != null)
                    pb.Image.Dispose();
                pb.Image = (Image)new ImageConverter().ConvertFrom((byte[])i);
            }), img);
        }, 1024, CancellationToken.None);
    

    这与专业的 MJPEG 解码器相差甚远,并且仍然存在一些错误,但有一个改进得多的版本I put in a gist。 gist 版本还包括登录和密码功能,以观看来自某些 IP 摄像机的流。

    【讨论】:

      【解决方案2】:

      在 Ch9 上试试这个 Coding4Fun 项目

      http://channel9.msdn.com/coding4fun/articles/MJPEG-Decoder

      【讨论】:

        猜你喜欢
        • 2012-05-08
        • 1970-01-01
        • 2014-03-14
        • 2016-04-29
        • 2018-05-16
        • 2017-10-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多