drogonframework / drogon

Drogon: A C++14/17/20 based HTTP web application framework running on Linux/macOS/Unix/Windows
MIT License
11.04k stars 1.06k forks source link

newAsyncStreamResponse video stream #1980

Open GuardHer opened 3 months ago

GuardHer commented 3 months ago

I want to upload the real-time video stream of the camera, but it will block the current thread, causing other requests to not be received normally. How should I do it without blocking?

void video::async_video_stream(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) const
{
    cap_.open(path);// Open the default camera
    if (!cap_.isOpened()) {
        auto resp_err = HttpResponse::newHttpResponse();
        resp_err->setStatusCode(k500InternalServerError);
        resp_err->setBody("Failed to open video file");
        callback(resp_err);
        return;
    }

    auto sendFrame = [this](ResponseStreamPtr res) -> void {
        double frame_rate = cap_.get(cv::CAP_PROP_FPS);
        int delay         = static_cast<int>(1000.0 / frame_rate);
        while (cap_.isOpened()) {
            cv::Mat frame;
            cap_ >> frame;// Capture a frame
            if (!frame.empty()) {
                std::vector<uchar> img_buffer;
                cv::imencode(".jpg", frame, img_buffer);
                std::string ima_data(img_buffer.begin(), img_buffer.end());
                auto img_size = img_buffer.size();
                std::ostringstream ss;
                ss << "--frame\r\nContent-Type: image/jpeg\r\n\r\n";
                ss << ima_data << "\r\n";
                res->send(ss.str());

                std::this_thread::sleep_for(std::chrono::milliseconds(delay));// 10ms
            } else {
                break;
            }
        }
        res->close();
        cap_.release();
    };

    auto resp = HttpResponse::newAsyncStreamResponse(sendFrame);
    resp->addHeader("Content-Type", "multipart/x-mixed-replace;boundary=frame");
    callback(resp);
}
nqf commented 3 months ago

You should execute a while loop in another thread, otherwise it will block the io thread.