h264 boost mode

This commit is contained in:
Maxim Devaev 2026-01-20 07:28:49 +02:00
parent 9eb39bbfc3
commit 5204f00812
5 changed files with 30 additions and 11 deletions

View File

@ -43,7 +43,7 @@
static us_m2m_encoder_s *_m2m_encoder_init( static us_m2m_encoder_s *_m2m_encoder_init(
const char *name, const char *path, uint output_format, const char *name, const char *path, uint output_format,
uint bitrate, uint gop, uint quality, bool allow_dma); uint bitrate, uint gop, uint quality, bool allow_dma, bool boost);
static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame); static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame);
@ -63,9 +63,9 @@ static int _m2m_encoder_compress_raw(us_m2m_encoder_s *enc, const us_frame_s *sr
#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("%s: " x_msg, enc->name, ##__VA_ARGS__) #define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("%s: " x_msg, enc->name, ##__VA_ARGS__)
us_m2m_encoder_s *us_m2m_h264_encoder_init(const char *name, const char *path, uint bitrate, uint gop) { us_m2m_encoder_s *us_m2m_h264_encoder_init(const char *name, const char *path, uint bitrate, uint gop, bool boost) {
bitrate *= 1000; // From Kbps bitrate *= 1000; // From Kbps
return _m2m_encoder_init(name, path, V4L2_PIX_FMT_H264, bitrate, gop, 0, true); return _m2m_encoder_init(name, path, V4L2_PIX_FMT_H264, bitrate, gop, 0, true, boost);
} }
us_m2m_encoder_s *us_m2m_mjpeg_encoder_init(const char *name, const char *path, uint quality) { us_m2m_encoder_s *us_m2m_mjpeg_encoder_init(const char *name, const char *path, uint quality) {
@ -76,12 +76,12 @@ us_m2m_encoder_s *us_m2m_mjpeg_encoder_init(const char *name, const char *path,
bitrate = step * round(bitrate / step); bitrate = step * round(bitrate / step);
bitrate *= 1000; // From Kbps bitrate *= 1000; // From Kbps
assert(bitrate > 0); assert(bitrate > 0);
return _m2m_encoder_init(name, path, V4L2_PIX_FMT_MJPEG, bitrate, 0, 0, true); return _m2m_encoder_init(name, path, V4L2_PIX_FMT_MJPEG, bitrate, 0, 0, true, false);
} }
us_m2m_encoder_s *us_m2m_jpeg_encoder_init(const char *name, const char *path, uint quality) { us_m2m_encoder_s *us_m2m_jpeg_encoder_init(const char *name, const char *path, uint quality) {
// FIXME: DMA не работает // FIXME: DMA не работает
return _m2m_encoder_init(name, path, V4L2_PIX_FMT_JPEG, 0, 0, quality, false); return _m2m_encoder_init(name, path, V4L2_PIX_FMT_JPEG, 0, 0, quality, false, false);
} }
void us_m2m_encoder_destroy(us_m2m_encoder_s *enc) { void us_m2m_encoder_destroy(us_m2m_encoder_s *enc) {
@ -139,7 +139,7 @@ int us_m2m_encoder_compress(us_m2m_encoder_s *enc, const us_frame_s *src, us_fra
static us_m2m_encoder_s *_m2m_encoder_init( static us_m2m_encoder_s *_m2m_encoder_init(
const char *name, const char *path, uint output_format, const char *name, const char *path, uint output_format,
uint bitrate, uint gop, uint quality, bool allow_dma) { uint bitrate, uint gop, uint quality, bool allow_dma, bool boost) {
US_LOG_INFO("%s: Initializing encoder ...", name); US_LOG_INFO("%s: Initializing encoder ...", name);
@ -161,6 +161,7 @@ static us_m2m_encoder_s *_m2m_encoder_init(
enc->gop = gop; enc->gop = gop;
enc->quality = quality; enc->quality = quality;
enc->allow_dma = allow_dma; enc->allow_dma = allow_dma;
enc->boost = boost;
enc->run = run; enc->run = run;
return enc; return enc;
} }
@ -222,7 +223,11 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame)
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, enc->gop); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, enc->gop);
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE);
if (run->p_width * run->p_height <= 1920 * 1080) { // https://forums.raspberrypi.com/viewtopic.php?t=291447#p1762296 if (run->p_width * run->p_height <= 1920 * 1080) { // https://forums.raspberrypi.com/viewtopic.php?t=291447#p1762296
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0); if (enc->boost) {
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_2);
} else {
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0);
}
} else { } else {
SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_5_1); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_5_1);
} }
@ -276,10 +281,13 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame)
} }
} }
if (run->p_width * run->p_height <= 1280 * 720) { if (
(run->p_width * run->p_height <= 1280 * 720)
|| ((enc->output_format == V4L2_PIX_FMT_H264) && enc->boost)
) {
// H264 требует каких-то лимитов. Больше 30 не поддерживается, а при 0 // H264 требует каких-то лимитов. Больше 30 не поддерживается, а при 0
// через какое-то время начинает производить некорректные фреймы. // через какое-то время начинает производить некорректные фреймы.
// Если же привысить fps, то резко увеличивается время кодирования. // Если же превысить fps, то резко увеличивается время кодирования.
run->fps_limit = 60; run->fps_limit = 60;
} else { } else {
run->fps_limit = 30; run->fps_limit = 30;

View File

@ -58,12 +58,13 @@ typedef struct {
uint gop; uint gop;
uint quality; uint quality;
bool allow_dma; bool allow_dma;
bool boost;
us_m2m_encoder_runtime_s *run; us_m2m_encoder_runtime_s *run;
} us_m2m_encoder_s; } us_m2m_encoder_s;
us_m2m_encoder_s *us_m2m_h264_encoder_init(const char *name, const char *path, uint bitrate, uint gop); us_m2m_encoder_s *us_m2m_h264_encoder_init(const char *name, const char *path, uint bitrate, uint gop, bool boost);
us_m2m_encoder_s *us_m2m_mjpeg_encoder_init(const char *name, const char *path, uint quality); us_m2m_encoder_s *us_m2m_mjpeg_encoder_init(const char *name, const char *path, uint quality);
us_m2m_encoder_s *us_m2m_jpeg_encoder_init(const char *name, const char *path, uint quality); us_m2m_encoder_s *us_m2m_jpeg_encoder_init(const char *name, const char *path, uint quality);
void us_m2m_encoder_destroy(us_m2m_encoder_s *enc); void us_m2m_encoder_destroy(us_m2m_encoder_s *enc);

View File

@ -100,6 +100,7 @@ enum _US_OPT_VALUES {
_O_H264_BITRATE, _O_H264_BITRATE,
_O_H264_GOP, _O_H264_GOP,
_O_H264_M2M_DEVICE, _O_H264_M2M_DEVICE,
_O_H264_BOOST,
# undef ADD_SINK # undef ADD_SINK
# ifdef WITH_V4P # ifdef WITH_V4P
@ -206,6 +207,7 @@ static const struct option _LONG_OPTS[] = {
{"h264-bitrate", required_argument, NULL, _O_H264_BITRATE}, {"h264-bitrate", required_argument, NULL, _O_H264_BITRATE},
{"h264-gop", required_argument, NULL, _O_H264_GOP}, {"h264-gop", required_argument, NULL, _O_H264_GOP},
{"h264-m2m-device", required_argument, NULL, _O_H264_M2M_DEVICE}, {"h264-m2m-device", required_argument, NULL, _O_H264_M2M_DEVICE},
{"h264-boost", no_argument, NULL, _O_H264_BOOST},
// Compatibility // Compatibility
{"sink", required_argument, NULL, _O_JPEG_SINK}, {"sink", required_argument, NULL, _O_JPEG_SINK},
{"sink-mode", required_argument, NULL, _O_JPEG_SINK_MODE}, {"sink-mode", required_argument, NULL, _O_JPEG_SINK_MODE},
@ -469,6 +471,7 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u
case _O_H264_BITRATE: OPT_NUMBER("--h264-bitrate", stream->h264_bitrate, 25, 20000, 0); case _O_H264_BITRATE: OPT_NUMBER("--h264-bitrate", stream->h264_bitrate, 25, 20000, 0);
case _O_H264_GOP: OPT_NUMBER("--h264-gop", stream->h264_gop, 0, 60, 0); case _O_H264_GOP: OPT_NUMBER("--h264-gop", stream->h264_gop, 0, 60, 0);
case _O_H264_M2M_DEVICE: OPT_SET(stream->h264_m2m_path, optarg); case _O_H264_M2M_DEVICE: OPT_SET(stream->h264_m2m_path, optarg);
case _O_H264_BOOST: OPT_SET(stream->h264_boost, true);
# ifdef WITH_V4P # ifdef WITH_V4P
case _O_V4P: case _O_V4P:

View File

@ -156,7 +156,13 @@ void us_stream_loop(us_stream_s *stream) {
atomic_store(&run->http->last_request_ts, us_get_now_monotonic()); atomic_store(&run->http->last_request_ts, us_get_now_monotonic());
if (stream->h264_sink != NULL) { if (stream->h264_sink != NULL) {
run->h264_enc = us_m2m_h264_encoder_init("H264", stream->h264_m2m_path, stream->h264_bitrate, stream->h264_gop); run->h264_enc = us_m2m_h264_encoder_init(
"H264",
stream->h264_m2m_path,
stream->h264_bitrate,
stream->h264_gop,
stream->h264_boost);
run->h264_tmp_src = us_frame_init(); run->h264_tmp_src = us_frame_init();
run->h264_dest = us_frame_init(); run->h264_dest = us_frame_init();
} }

View File

@ -94,6 +94,7 @@ typedef struct {
uint h264_bitrate; uint h264_bitrate;
uint h264_gop; uint h264_gop;
char *h264_m2m_path; char *h264_m2m_path;
bool h264_boost;
# ifdef WITH_V4P # ifdef WITH_V4P
us_drm_s *drm; us_drm_s *drm;