1

我想使用 mongoose 轻量级 Web 服务器实现 MJPEG 流。有人可以给我一些关于我如何有效地做到这一点的指示吗?我已经有了需要流式传输的 jpeg 文件,并且我了解 MJPEG 概念。我只需要知道如何从协议级别实现 MJPEG 流。

4

1 回答 1

2

几乎所有 ip 摄像机都实现的基于 http 的 mjpeg 是多部分 mime 消息的子类型。http://en.wikipedia.org/wiki/MIME#Mixed-Replace

您必须将 cvloop() 替换为填充 jbuf 的实现。

#include <vector>
#include "mongoose.h"

#ifdef _WIN32 
#include <windows.h>
#define SLEEP(ms) Sleep(ms)
#endif
#ifdef __linux__ 
#define SLEEP(ms) usleep(ms*1000)
#endif

std::vector<unsigned char> jbuf;//fill this with a single jpeg image data

#include "opencv2/highgui/highgui.hpp"
void cvloop()
{
    cv::VideoCapture cap("c:/toprocess/frame_%004d.jpg");
    cv::Mat frame;
    for(;;)
    {
        cap>>frame;
        std::vector<unsigned char> buffer;
        std::vector<int> param(2);
        param[0]=CV_IMWRITE_JPEG_QUALITY;
        param[1]=40;
        imencode(".jpg",frame,buffer,param);
        jbuf.swap(buffer);
        SLEEP(50);
    }
}

// This function will be called by mongoose on every new request.
static int begin_request_handler(struct mg_connection *conn) {
    mg_printf(conn,
        "HTTP/1.1 200 OK\r\n"
        "Content-Type: multipart/x-mixed-replace;boundary=b\r\n"
        "Cache-Control: no-store\r\n"
        "Pragma: no-cache\r\n"
        "Connection: close\r\n"
        "\r\n");
    for(;;)
    {
        if( jbuf.size()<4 || 
            (jbuf[0]!=0xff && jbuf[0]!=0xd8) ||
            (jbuf[jbuf.size()-2]!=0xff && jbuf[jbuf.size()-1]!=0xd9))
        {
            SLEEP(10);
            continue;
        }
        mg_printf(conn,
            "--b\r\n"
            "Content-Type: image/jpeg\r\n"
            "Content-length: %d\r\n"
            "\r\n",jbuf.size());
        int ret=mg_write(conn,&jbuf[0], jbuf.size());
        if(ret==0||ret==-1) return 1;
        SLEEP(50);
    }
    return 1;
}

int main(void) {
    struct mg_context *ctx;
    struct mg_callbacks callbacks;

    // List of options. Last element must be NULL.
    const char *options[] = {"listening_ports", "8080",NULL};

    // Prepare callbacks structure. We have only one callback, the rest are NULL.
    memset(&callbacks, 0, sizeof(callbacks));
    callbacks.begin_request = begin_request_handler;

    // Start the web server.
    ctx = mg_start(&callbacks, NULL, options);
    cvloop();

    // Wait until user hits "enter". Server is running in separate thread.
    // Navigating to http://localhost:8080 will invoke begin_request_handler().
    getchar();

    // Stop the server.
    mg_stop(ctx);

    return 0;
}
于 2013-03-30T21:27:29.917 回答