mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-24 18:56:32 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ebcf99c8 | ||
|
|
6a6b910869 | ||
|
|
4e8acf371f | ||
|
|
c4cb8288c7 |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 5.48
|
current_version = 5.49
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)
|
parse = (?P<major>\d+)\.(?P<minor>\d+)
|
||||||
serialize =
|
serialize =
|
||||||
{major}.{minor}
|
{major}.{minor}
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ $ modprobe bcm2835-v4l2 max_video_width=2592 max_video_height=1944
|
|||||||
µStreamer supports bandwidth-efficient streaming using [H.264 compression](https://en.wikipedia.org/wiki/Advanced_Video_Coding) and the Janus WebRTC server. See the [Janus integration guide](docs/h264.md) for full details.
|
µStreamer supports bandwidth-efficient streaming using [H.264 compression](https://en.wikipedia.org/wiki/Advanced_Video_Coding) and the Janus WebRTC server. See the [Janus integration guide](docs/h264.md) for full details.
|
||||||
|
|
||||||
## Nginx
|
## Nginx
|
||||||
When uStreamer is behind an Nginx proxy, it's buffering behavior introduces latency into the video stream. It's possible to disable Nginx's buffering to eliminate the additional latency:
|
When uStreamer is behind an Nginx proxy, its buffering behavior introduces latency into the video stream. It's possible to disable Nginx's buffering to eliminate the additional latency:
|
||||||
|
|
||||||
```nginx
|
```nginx
|
||||||
location /stream {
|
location /stream {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Manpage for ustreamer-dump.
|
.\" Manpage for ustreamer-dump.
|
||||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||||
.TH USTREAMER-DUMP 1 "version 5.48" "January 2021"
|
.TH USTREAMER-DUMP 1 "version 5.49" "January 2021"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ustreamer-dump \- Dump uStreamer's memory sink to file
|
ustreamer-dump \- Dump uStreamer's memory sink to file
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Manpage for ustreamer.
|
.\" Manpage for ustreamer.
|
||||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||||
.TH USTREAMER 1 "version 5.48" "November 2020"
|
.TH USTREAMER 1 "version 5.49" "November 2020"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ustreamer \- stream MJPEG video from any V4L2 device to the network
|
ustreamer \- stream MJPEG video from any V4L2 device to the network
|
||||||
@@ -52,7 +52,7 @@ Initial image resolution. Default: 640x480.
|
|||||||
.TP
|
.TP
|
||||||
.BR \-m\ \fIfmt ", " \-\-format\ \fIfmt
|
.BR \-m\ \fIfmt ", " \-\-format\ \fIfmt
|
||||||
Image format.
|
Image format.
|
||||||
Available: YUYV, UYVY, RGB565, RGB24, JPEG; default: YUYV.
|
Available: YUYV, YVYU, UYVY, RGB565, RGB24, JPEG; default: YUYV.
|
||||||
.TP
|
.TP
|
||||||
.BR \-a\ \fIstd ", " \-\-tv\-standard\ \fIstd
|
.BR \-a\ \fIstd ", " \-\-tv\-standard\ \fIstd
|
||||||
Force TV standard.
|
Force TV standard.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=5.48
|
pkgver=5.49
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Lightweight and fast MJPEG-HTTP streamer"
|
pkgdesc="Lightweight and fast MJPEG-HTTP streamer"
|
||||||
url="https://github.com/pikvm/ustreamer"
|
url="https://github.com/pikvm/ustreamer"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ustreamer
|
PKG_NAME:=ustreamer
|
||||||
PKG_VERSION:=5.48
|
PKG_VERSION:=5.49
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ def _find_sources(suffix: str) -> list[str]:
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup(
|
setup(
|
||||||
name="ustreamer",
|
name="ustreamer",
|
||||||
version="5.48",
|
version="5.49",
|
||||||
description="uStreamer tools",
|
description="uStreamer tools",
|
||||||
author="Maxim Devaev",
|
author="Maxim Devaev",
|
||||||
author_email="mdevaev@gmail.com",
|
author_email="mdevaev@gmail.com",
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define US_VERSION_MAJOR 5
|
#define US_VERSION_MAJOR 5
|
||||||
#define US_VERSION_MINOR 48
|
#define US_VERSION_MINOR 49
|
||||||
|
|
||||||
#define US_MAKE_VERSION2(_major, _minor) #_major "." #_minor
|
#define US_MAKE_VERSION2(_major, _minor) #_major "." #_minor
|
||||||
#define US_MAKE_VERSION1(_major, _minor) US_MAKE_VERSION2(_major, _minor)
|
#define US_MAKE_VERSION1(_major, _minor) US_MAKE_VERSION2(_major, _minor)
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ unsigned us_frame_get_padding(const us_frame_s *frame) {
|
|||||||
unsigned bytes_per_pixel = 0;
|
unsigned bytes_per_pixel = 0;
|
||||||
switch (frame->format) {
|
switch (frame->format) {
|
||||||
case V4L2_PIX_FMT_YUYV:
|
case V4L2_PIX_FMT_YUYV:
|
||||||
|
case V4L2_PIX_FMT_YVYU:
|
||||||
case V4L2_PIX_FMT_UYVY:
|
case V4L2_PIX_FMT_UYVY:
|
||||||
case V4L2_PIX_FMT_RGB565: bytes_per_pixel = 2; break;
|
case V4L2_PIX_FMT_RGB565: bytes_per_pixel = 2; break;
|
||||||
case V4L2_PIX_FMT_BGR24:
|
case V4L2_PIX_FMT_BGR24:
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ static const struct {
|
|||||||
const unsigned format; // cppcheck-suppress unusedStructMember
|
const unsigned format; // cppcheck-suppress unusedStructMember
|
||||||
} _FORMATS[] = {
|
} _FORMATS[] = {
|
||||||
{"YUYV", V4L2_PIX_FMT_YUYV},
|
{"YUYV", V4L2_PIX_FMT_YUYV},
|
||||||
|
{"YVYU", V4L2_PIX_FMT_YVYU},
|
||||||
{"UYVY", V4L2_PIX_FMT_UYVY},
|
{"UYVY", V4L2_PIX_FMT_UYVY},
|
||||||
{"RGB565", V4L2_PIX_FMT_RGB565},
|
{"RGB565", V4L2_PIX_FMT_RGB565},
|
||||||
{"RGB24", V4L2_PIX_FMT_RGB24},
|
{"RGB24", V4L2_PIX_FMT_RGB24},
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
#define US_STANDARDS_STR "PAL, NTSC, SECAM"
|
#define US_STANDARDS_STR "PAL, NTSC, SECAM"
|
||||||
|
|
||||||
#define US_FORMAT_UNKNOWN -1
|
#define US_FORMAT_UNKNOWN -1
|
||||||
#define US_FORMATS_STR "YUYV, UYVY, RGB565, RGB24, BGR24, MJPEG, JPEG"
|
#define US_FORMATS_STR "YUYV, YVYU, UYVY, RGB565, RGB24, BGR24, MJPEG, JPEG"
|
||||||
|
|
||||||
#define US_IO_METHOD_UNKNOWN -1
|
#define US_IO_METHOD_UNKNOWN -1
|
||||||
#define US_IO_METHODS_STR "MMAP, USERPTR"
|
#define US_IO_METHODS_STR "MMAP, USERPTR"
|
||||||
|
|||||||
@@ -37,8 +37,7 @@ typedef struct {
|
|||||||
|
|
||||||
static void _jpeg_set_dest_frame(j_compress_ptr jpeg, us_frame_s *frame);
|
static void _jpeg_set_dest_frame(j_compress_ptr jpeg, us_frame_s *frame);
|
||||||
|
|
||||||
static void _jpeg_write_scanlines_yuyv(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
static void _jpeg_write_scanlines_yuv(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
||||||
static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
|
||||||
static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
||||||
static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
||||||
static void _jpeg_write_scanlines_bgr24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
static void _jpeg_write_scanlines_bgr24(struct jpeg_compress_struct *jpeg, const us_frame_s *frame);
|
||||||
@@ -71,21 +70,17 @@ void us_cpu_encoder_compress(const us_frame_s *src, us_frame_s *dest, unsigned q
|
|||||||
|
|
||||||
jpeg_start_compress(&jpeg, TRUE);
|
jpeg_start_compress(&jpeg, TRUE);
|
||||||
|
|
||||||
# define WRITE_SCANLINES(x_format, x_func) \
|
|
||||||
case x_format: { x_func(&jpeg, src); break; }
|
|
||||||
|
|
||||||
switch (src->format) {
|
switch (src->format) {
|
||||||
// https://www.fourcc.org/yuv.php
|
// https://www.fourcc.org/yuv.php
|
||||||
WRITE_SCANLINES(V4L2_PIX_FMT_YUYV, _jpeg_write_scanlines_yuyv);
|
case V4L2_PIX_FMT_YUYV:
|
||||||
WRITE_SCANLINES(V4L2_PIX_FMT_UYVY, _jpeg_write_scanlines_uyvy);
|
case V4L2_PIX_FMT_YVYU:
|
||||||
WRITE_SCANLINES(V4L2_PIX_FMT_RGB565, _jpeg_write_scanlines_rgb565);
|
case V4L2_PIX_FMT_UYVY: _jpeg_write_scanlines_yuv(&jpeg, src); break;
|
||||||
WRITE_SCANLINES(V4L2_PIX_FMT_RGB24, _jpeg_write_scanlines_rgb24);
|
case V4L2_PIX_FMT_RGB565: _jpeg_write_scanlines_rgb565(&jpeg, src); break;
|
||||||
WRITE_SCANLINES(V4L2_PIX_FMT_BGR24, _jpeg_write_scanlines_bgr24);
|
case V4L2_PIX_FMT_RGB24: _jpeg_write_scanlines_rgb24(&jpeg, src); break;
|
||||||
default: assert(0 && "Unsupported input format for CPU encoder");
|
case V4L2_PIX_FMT_BGR24: _jpeg_write_scanlines_bgr24(&jpeg, src); break;
|
||||||
|
default: assert(0 && "Unsupported input format for CPU encoder"); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
# undef WRITE_SCANLINES
|
|
||||||
|
|
||||||
jpeg_finish_compress(&jpeg);
|
jpeg_finish_compress(&jpeg);
|
||||||
jpeg_destroy_compress(&jpeg);
|
jpeg_destroy_compress(&jpeg);
|
||||||
|
|
||||||
@@ -108,40 +103,7 @@ static void _jpeg_set_dest_frame(j_compress_ptr jpeg, us_frame_s *frame) {
|
|||||||
frame->used = 0;
|
frame->used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _jpeg_write_scanlines_yuyv(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
|
static void _jpeg_write_scanlines_yuv(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
|
||||||
uint8_t *line_buf;
|
|
||||||
US_CALLOC(line_buf, frame->width * 3);
|
|
||||||
|
|
||||||
const unsigned padding = us_frame_get_padding(frame);
|
|
||||||
const uint8_t *data = frame->data;
|
|
||||||
|
|
||||||
while (jpeg->next_scanline < frame->height) {
|
|
||||||
uint8_t *ptr = line_buf;
|
|
||||||
|
|
||||||
for (unsigned x = 0; x < frame->width; ++x) {
|
|
||||||
// See also: https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-yuyv.html
|
|
||||||
const bool is_odd_pixel = x & 1;
|
|
||||||
const uint8_t y = data[is_odd_pixel ? 2 : 0];
|
|
||||||
const uint8_t u = data[1];
|
|
||||||
const uint8_t v = data[3];
|
|
||||||
|
|
||||||
ptr[0] = y;
|
|
||||||
ptr[1] = u;
|
|
||||||
ptr[2] = v;
|
|
||||||
ptr += 3;
|
|
||||||
|
|
||||||
data += (is_odd_pixel ? 4: 0);
|
|
||||||
}
|
|
||||||
data += padding;
|
|
||||||
|
|
||||||
JSAMPROW scanlines[1] = {line_buf};
|
|
||||||
jpeg_write_scanlines(jpeg, scanlines, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(line_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const us_frame_s *frame) {
|
|
||||||
uint8_t *line_buf;
|
uint8_t *line_buf;
|
||||||
US_CALLOC(line_buf, frame->width * 3);
|
US_CALLOC(line_buf, frame->width * 3);
|
||||||
|
|
||||||
@@ -154,9 +116,23 @@ static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const
|
|||||||
for (unsigned x = 0; x < frame->width; ++x) {
|
for (unsigned x = 0; x < frame->width; ++x) {
|
||||||
// See also: https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-uyvy.html
|
// See also: https://www.kernel.org/doc/html/v4.8/media/uapi/v4l/pixfmt-uyvy.html
|
||||||
const bool is_odd_pixel = x & 1;
|
const bool is_odd_pixel = x & 1;
|
||||||
const uint8_t y = data[is_odd_pixel ? 3 : 1];
|
uint8_t y, u, v;
|
||||||
const uint8_t u = data[0];
|
if (frame->format == V4L2_PIX_FMT_YUYV) {
|
||||||
const uint8_t v = data[2];
|
y = data[is_odd_pixel ? 2 : 0];
|
||||||
|
u = data[1];
|
||||||
|
v = data[3];
|
||||||
|
} else if (frame->format == V4L2_PIX_FMT_YVYU) {
|
||||||
|
y = data[is_odd_pixel ? 2 : 0];
|
||||||
|
u = data[3];
|
||||||
|
v = data[1];
|
||||||
|
} else if (frame->format == V4L2_PIX_FMT_UYVY) {
|
||||||
|
y = data[is_odd_pixel ? 3 : 1];
|
||||||
|
u = data[0];
|
||||||
|
v = data[2];
|
||||||
|
} else {
|
||||||
|
assert(0 && "Unsupported pixel format");
|
||||||
|
return; // Makes linter happy
|
||||||
|
}
|
||||||
|
|
||||||
ptr[0] = y;
|
ptr[0] = y;
|
||||||
ptr[1] = u;
|
ptr[1] = u;
|
||||||
|
|||||||
Reference in New Issue
Block a user