Skip to content

Commit 8b1a95d

Browse files
authored
http jpg streaming (#161)
1 parent 5b5dd51 commit 8b1a95d

File tree

7 files changed

+717
-2
lines changed

7 files changed

+717
-2
lines changed

README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828

2929
:heavy_check_mark: ***NEW FEATURE*** [`cv::imshow` supports Linux framebuffer and Windows](#cvimshow-supports-linux-framebuffer-and-windows)
3030

31+
:heavy_check_mark: ***NEW FEATURE*** [`cv::VideoWriter` supports jpg streaming over http](#cvvideowriter-supports-jpg-streaming-over-http)
32+
3133
|opencv 4.10.0 package size|The official opencv|opencv-mobile|
3234
|:-:|:-:|:-:|
3335
|source zip|95.2 MB|8.25 MB|
@@ -610,6 +612,35 @@ int main()
610612
</td></tr>
611613
</table>
612614

615+
## `cv::VideoWriter` supports jpg streaming over http
616+
617+
In Linux, `cv::VideoWriter` could be used for streaming images as jpg over http, while it is noop on other platforms. Initialize a `cv::VideoWriter` instance, `open` the writer with name `httpjpg` and a port number, then it will setup a simple http server. You can open the streaming url with a web browser, and image will be shown in the browser as soon as it is sent to the writer. The image size and content can be dynamic, which is useful for streaming frames from a live camera.
618+
619+
```cpp
620+
#include <opencv2/core/core.hpp>
621+
#include <opencv2/highgui/highgui.hpp>
622+
623+
int main()
624+
{
625+
cv::VideoCapture cap;
626+
cap.open(0);
627+
628+
cv::VideoWriter http;
629+
http.open("httpjpg", 7766);
630+
631+
// open streaming url http://<server ip>:7766 in web browser
632+
633+
cv::Mat bgr;
634+
while (1)
635+
{
636+
cap >> bgr;
637+
http << bgr;
638+
}
639+
640+
return 0;
641+
}
642+
```
643+
613644
# opencv modules included
614645

615646
|module|comment|

highgui/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ set(highgui_srcs
1010
${CMAKE_CURRENT_LIST_DIR}/src/highgui.cpp
1111
${CMAKE_CURRENT_LIST_DIR}/src/kanna_rotate.cpp
1212
${CMAKE_CURRENT_LIST_DIR}/src/videocapture.cpp
13+
${CMAKE_CURRENT_LIST_DIR}/src/videowriter.cpp
1314

1415
# dnn
1516
${CMAKE_CURRENT_LIST_DIR}/src/nms.cpp
@@ -18,7 +19,8 @@ set(highgui_srcs
1819
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
1920
list(APPEND highgui_srcs
2021
${CMAKE_CURRENT_LIST_DIR}/src/capture_v4l2.cpp
21-
${CMAKE_CURRENT_LIST_DIR}/src/display_fb.cpp)
22+
${CMAKE_CURRENT_LIST_DIR}/src/display_fb.cpp
23+
${CMAKE_CURRENT_LIST_DIR}/src/writer_http.cpp)
2224
endif()
2325

2426
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")

highgui/include/opencv2/highgui/highgui.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,28 @@ class CV_EXPORTS_W VideoCapture
9595
VideoCaptureImpl* const d;
9696
};
9797

98+
class VideoWriterImpl;
99+
class CV_EXPORTS_W VideoWriter
100+
{
101+
public:
102+
VideoWriter();
103+
104+
~VideoWriter();
105+
106+
bool open(const String& name, int port);
107+
108+
bool isOpened() const;
109+
110+
void release();
111+
112+
VideoWriter& operator<<(const Mat& bgr_image);
113+
114+
void write(const Mat& image);
115+
116+
protected:
117+
VideoWriterImpl* const d;
118+
};
119+
98120
} // namespace cv
99121

100122
#endif // OPENCV_HIGHGUI_HPP

highgui/src/highgui.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
#if CV_WITH_RK
5252
#include "jpeg_encoder_rk_mpp.h"
5353
#endif
54-
#if defined __linux__
54+
#if defined __linux__ && !__ANDROID__
5555
#include "display_fb.h"
5656
#endif
5757

highgui/src/videowriter.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//
2+
// Copyright (C) 2024 nihui
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
17+
#include <opencv2/core.hpp>
18+
#include <opencv2/highgui.hpp>
19+
20+
#include <stdio.h>
21+
#include <string.h>
22+
23+
#if defined __linux__ && !__ANDROID__
24+
#include "writer_http.h"
25+
#endif
26+
27+
namespace cv {
28+
29+
class VideoWriterImpl
30+
{
31+
public:
32+
VideoWriterImpl();
33+
34+
public:
35+
bool is_opened;
36+
int width;
37+
int height;
38+
float fps;
39+
40+
#if defined __linux__ && !__ANDROID__
41+
writer_http wt_http;
42+
#endif
43+
};
44+
45+
VideoWriterImpl::VideoWriterImpl()
46+
{
47+
is_opened = false;
48+
width = 0;
49+
height = 0;
50+
fps = 0;
51+
}
52+
53+
VideoWriter::VideoWriter() : d(new VideoWriterImpl)
54+
{
55+
}
56+
57+
VideoWriter::~VideoWriter()
58+
{
59+
release();
60+
61+
delete d;
62+
}
63+
64+
bool VideoWriter::open(const String& name, int port)
65+
{
66+
if (d->is_opened)
67+
{
68+
release();
69+
}
70+
71+
if (name == "httpjpg")
72+
{
73+
#if defined __linux__ && !__ANDROID__
74+
if (writer_http::supported())
75+
{
76+
int ret = d->wt_http.open(port);
77+
if (ret == 0)
78+
{
79+
d->is_opened = true;
80+
}
81+
}
82+
else
83+
#endif
84+
{
85+
}
86+
}
87+
88+
return d->is_opened;
89+
}
90+
91+
bool VideoWriter::isOpened() const
92+
{
93+
return d->is_opened;
94+
}
95+
96+
void VideoWriter::release()
97+
{
98+
if (!d->is_opened)
99+
return;
100+
101+
#if defined __linux__ && !__ANDROID__
102+
if (writer_http::supported())
103+
{
104+
d->wt_http.close();
105+
}
106+
else
107+
#endif
108+
{
109+
}
110+
111+
d->is_opened = false;
112+
d->width = 0;
113+
d->height = 0;
114+
d->fps = 0;
115+
}
116+
117+
VideoWriter& VideoWriter::operator<<(const Mat& image)
118+
{
119+
write(image);
120+
121+
return *this;
122+
}
123+
124+
void VideoWriter::write(const Mat& image)
125+
{
126+
if (!d->is_opened)
127+
return;
128+
129+
#if defined __linux__ && !__ANDROID__
130+
if (writer_http::supported())
131+
{
132+
// encode jpg
133+
std::vector<uchar> buf;
134+
cv::imencode(".JPG", image, buf);
135+
136+
d->wt_http.write_jpgbuf((const unsigned char*)buf.data(), buf.size());
137+
}
138+
else
139+
#endif
140+
{
141+
}
142+
}
143+
144+
} // namespace cv

0 commit comments

Comments
 (0)