【问题标题】:How to stream motion jpeg using CGI?如何使用 CGI 流式传输运动 jpeg?
【发布时间】:2019-01-31 21:02:02
【问题描述】:

我正在创建一个 Web 应用程序,该应用程序需要显示我从高速摄像机抓取的视频。 为此,我正在尝试创建一个 Motion JPEG CGI 应用程序,当浏览器访问此 CGI 应用程序时,它仅将这些帧输出为 JPG 序列。

所以我的问题是:如何创建一个简单的 C++ 代码,它只读取一系列 JPG 文件,然后将其输出打印到其他文件中,以供浏览器加载一个 JPG 序列?

我尝试了以下代码,但它不起作用...

#include <iostream>
#include <cstdio>

int main()
{
    std::cout << "Cache-Control: no-cache\n\n";
    std::cout << "Cache-Control: private\n\n";
    std::cout << "Pragma: no-cache\n\n";
    std::cout << "Content-type: multipart/x-mixed-replace; boundary=spiderman\n\n";

    int i = 0;
    while(true)
    {
        char buffer[1024];
        sprintf(buffer, "/tmp/img_%d.jpg", (i%2));
        FILE* fp = fopen(buffer, "r");
        while(!feof(fp))
        {
            fread(buffer, 1, 1, fp); 
            fwrite(buffer, 1, 1, stdout);
        }
        fclose(fp);
        i++;
        std::cout << "--spiderman\n";
        std::cout << "Content-type: image/jpeg\n\n";
    }
}

【问题讨论】:

  • 解决此问题的第一步是使用stdoutstd::cout 生成输出,但不能同时使用两者。第二步,在决定使用哪一个之后,是在文件和标准输出之间正确实现一次复制多个字节。这不会很好地“流式传输”。
  • 我只是在做一个测试...所以我希望最简单的代码,在任何优化之前。
  • stdoutstd::cout 不是优化。像这样使用两者很可能会以神秘的方式失败,因为每个都有完全独立的内部缓冲区,它们完全不知道彼此的存在。在文件描述符 #1 的实际输出中,stdout 的随机部分将与 std::cout 的随机部分混合,产生有趣的结果。

标签: c++ http cgi jpeg


【解决方案1】:

经过非常艰苦的二进制调试,我想出了一个简单的解决方案:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>

int main()
{
    printf("Content-Type: multipart/x-mixed-replace; boundary=--jpgboundary\r\n\r\n");

    int i = 0;
    while(true)
    {
        char fnameBuffer[1024];
        sprintf(fnameBuffer, "/tmp/img_%d.jpg", (i%2));
        FILE* fp = fopen(fnameBuffer, "r");
        fseek(fp, 0, SEEK_END);
        long fileSize = ftell(fp);
        rewind(fp);

        char* buffer = (char*)malloc(sizeof(char)*fileSize);
        fread(buffer, 1, fileSize, fp);
        fclose(fp);
        free(buffer);

        i++;
        printf("--jpgboundary");
        printf("Content-type: image/jpeg\r\n");
        printf("Content-length: %ld\r\n\r\n", fileSize);
        fwrite(buffer, 1, fileSize, stdout);
        printf("\r\n\r\n\r\n");

        usleep(1000);
    }
}

这实际上加载了一系列图像并将它们刷新到浏览器。 我用谷歌浏览器测试了输出,它按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-20
    • 1970-01-01
    • 2011-02-24
    • 2020-10-06
    • 1970-01-01
    相关资源
    最近更新 更多