Skip to content

Commit 3ac13b4

Browse files
authored
allow setting software H264 profile and level (bluenviron/mediamtx#3965) (#57)
1 parent d743bb5 commit 3ac13b4

File tree

5 files changed

+48
-42
lines changed

5 files changed

+48
-42
lines changed

encoder_hard_h264.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,27 @@ bool encoder_hard_h264_create(const parameters_t *params, int stride, int colors
114114

115115
struct v4l2_control ctrl = {0};
116116
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
117-
ctrl.value = params->profile;
117+
if (strcmp(params->hardware_h264_profile, "baseline") == 0) {
118+
ctrl.value = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
119+
} else if (strcmp(params->hardware_h264_profile, "main") == 0) {
120+
ctrl.value = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
121+
} else {
122+
ctrl.value = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
123+
}
118124
int res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
119125
if (res != 0) {
120126
set_error("unable to set profile");
121127
goto failed;
122128
}
123129

124130
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_LEVEL;
125-
ctrl.value = params->level;
131+
if (strcmp(params->hardware_h264_level, "4.0") == 0) {
132+
ctrl.value = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
133+
} else if (strcmp(params->hardware_h264_level, "4.1") == 0) {
134+
ctrl.value = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
135+
} else {
136+
ctrl.value = V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
137+
}
126138
res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
127139
if (res != 0) {
128140
set_error("unable to set level");

encoder_soft_h264.c

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,6 @@
99

1010
#include "encoder_soft_h264.h"
1111

12-
#define PRESET "ultrafast"
13-
#define TUNE "zerolatency"
14-
#define PROFILE "baseline"
15-
1612
static char errbuf[256];
1713

1814
static void set_error(const char *format, ...) {
@@ -32,7 +28,6 @@ typedef struct {
3228
x264_t *x_handler;
3329
x264_picture_t x_pic_in;
3430
x264_picture_t x_pic_out;
35-
uint64_t next_pts;
3631
pthread_mutex_t mutex;
3732
} encoder_soft_h264_priv_t;
3833

@@ -41,10 +36,18 @@ bool encoder_soft_h264_create(const parameters_t *params, int stride, int colors
4136
encoder_soft_h264_priv_t *encp = (encoder_soft_h264_priv_t *)(*enc);
4237
memset(encp, 0, sizeof(encoder_soft_h264_priv_t));
4338

44-
int res = x264_param_default_preset(&encp->x_params, PRESET, TUNE);
45-
if (res < 0) {
46-
set_error("x264_param_default_preset() failed");
47-
goto failed;
39+
if (strcmp(params->software_h264_profile, "baseline") == 0) {
40+
int res = x264_param_default_preset(&encp->x_params, "ultrafast", "zerolatency");
41+
if (res < 0) {
42+
set_error("x264_param_default_preset() failed");
43+
goto failed;
44+
}
45+
} else {
46+
int res = x264_param_default_preset(&encp->x_params, "superfast", NULL);
47+
if (res < 0) {
48+
set_error("x264_param_default_preset() failed");
49+
goto failed;
50+
}
4851
}
4952

5053
encp->x_params.i_width = params->width;
@@ -68,8 +71,9 @@ bool encoder_soft_h264_create(const parameters_t *params, int stride, int colors
6871
encp->x_params.rc.i_vbv_max_bitrate = params->bitrate / 1000;
6972
encp->x_params.rc.i_rc_method = X264_RC_ABR;
7073
encp->x_params.i_bframe = 0;
74+
encp->x_params.i_level_idc = (int)(atof(params->software_h264_level) * 10.0f);
7175

72-
res = x264_param_apply_profile(&encp->x_params, PROFILE);
76+
int res = x264_param_apply_profile(&encp->x_params, params->software_h264_profile);
7377
if (res < 0) {
7478
set_error("x264_param_apply_profile() failed");
7579
goto failed;
@@ -103,7 +107,7 @@ void encoder_soft_h264_encode(encoder_soft_h264_t *enc, uint8_t *buffer_mapped,
103107
encp->x_pic_in.img.plane[0] = buffer_mapped; // Y
104108
encp->x_pic_in.img.plane[1] = encp->x_pic_in.img.plane[0] + encp->x_pic_in.img.i_stride[0] * encp->params->height; // U
105109
encp->x_pic_in.img.plane[2] = encp->x_pic_in.img.plane[1] + (encp->x_pic_in.img.i_stride[0] / 2) * (encp->params->height / 2); // V
106-
encp->x_pic_in.i_pts = encp->next_pts++;
110+
encp->x_pic_in.i_pts = (int64_t)timestamp;
107111

108112
pthread_mutex_lock(&encp->mutex);
109113

@@ -113,7 +117,9 @@ void encoder_soft_h264_encode(encoder_soft_h264_t *enc, uint8_t *buffer_mapped,
113117

114118
pthread_mutex_unlock(&encp->mutex);
115119

116-
encp->output_cb(nal->p_payload, frame_size, timestamp);
120+
if (nal != NULL) {
121+
encp->output_cb(nal->p_payload, frame_size, (uint64_t)encp->x_pic_out.i_pts);
122+
}
117123
}
118124

119125
void encoder_soft_h264_reload_params(encoder_soft_h264_t *enc, const parameters_t *params) {

main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ int main() {
145145
ok = encoder_jpeg_create(
146146
params.secondary_width,
147147
params.secondary_height,
148-
params.secondary_quality,
148+
params.secondary_mjpeg_quality,
149149
camera_get_secondary_stride(cam),
150150
on_jpeg_output,
151151
&enc_jpeg);

parameters.c

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#include <stdarg.h>
55
#include <stdio.h>
66

7-
#include <linux/videodev2.h>
8-
97
#include "base64.h"
108
#include "parameters.h"
119

@@ -134,34 +132,22 @@ bool parameters_unserialize(parameters_t *params, const uint8_t *buf, size_t buf
134132
params->idr_period = atoi(val);
135133
} else if (strcmp(key, "Bitrate") == 0) {
136134
params->bitrate = atoi(val);
137-
} else if (strcmp(key, "Profile") == 0) {
138-
char *decoded_val = base64_decode(val);
139-
if (strcmp(decoded_val, "baseline") == 0) {
140-
params->profile = V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE;
141-
} else if (strcmp(decoded_val, "main") == 0) {
142-
params->profile = V4L2_MPEG_VIDEO_H264_PROFILE_MAIN;
143-
} else {
144-
params->profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
145-
}
146-
free(decoded_val);
147-
} else if (strcmp(key, "Level") == 0) {
148-
char *decoded_val = base64_decode(val);
149-
if (strcmp(decoded_val, "4.0") == 0) {
150-
params->level = V4L2_MPEG_VIDEO_H264_LEVEL_4_0;
151-
} else if (strcmp(decoded_val, "4.1") == 0) {
152-
params->level = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
153-
} else {
154-
params->level = V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
155-
}
156-
free(decoded_val);
135+
} else if (strcmp(key, "HardwareH264Profile") == 0) {
136+
params->hardware_h264_profile = base64_decode(val);
137+
} else if (strcmp(key, "HardwareH264Level") == 0) {
138+
params->hardware_h264_level = base64_decode(val);
139+
} else if (strcmp(key, "SoftwareH264Profile") == 0) {
140+
params->software_h264_profile = base64_decode(val);
141+
} else if (strcmp(key, "SoftwareH264Level") == 0) {
142+
params->software_h264_level = base64_decode(val);
157143
} else if (strcmp(key, "SecondaryWidth") == 0) {
158144
params->secondary_width = atoi(val);
159145
} else if (strcmp(key, "SecondaryHeight") == 0) {
160146
params->secondary_height = atoi(val);
161147
} else if (strcmp(key, "SecondaryFPS") == 0) {
162148
params->secondary_fps = atof(val);
163-
} else if (strcmp(key, "SecondaryQuality") == 0) {
164-
params->secondary_quality = atoi(val);
149+
} else if (strcmp(key, "SecondaryMJPEGQuality") == 0) {
150+
params->secondary_mjpeg_quality = atoi(val);
165151
}
166152
}
167153

parameters.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,14 @@ typedef struct {
4343
char *codec;
4444
unsigned int idr_period;
4545
unsigned int bitrate;
46-
unsigned int profile;
47-
unsigned int level;
46+
char *hardware_h264_profile;
47+
char *hardware_h264_level;
48+
char *software_h264_profile;
49+
char *software_h264_level;
4850
unsigned int secondary_width;
4951
unsigned int secondary_height;
5052
float secondary_fps;
51-
unsigned int secondary_quality;
53+
unsigned int secondary_mjpeg_quality;
5254

5355
// private
5456
unsigned int buffer_count;

0 commit comments

Comments
 (0)