rpicamera: allow to change bitrate and IDR period dynamically (#2703) (#2764)

This commit is contained in:
Alessandro Ros 2023-11-30 21:43:19 +01:00 committed by GitHub
parent 6ca59e0ed8
commit 0e5e3324a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 35 additions and 15 deletions

View File

@ -29,6 +29,8 @@ func pathConfCanBeUpdated(oldPathConf *conf.Path, newPathConf *conf.Path) bool {
clone.RPICameraGain = newPathConf.RPICameraGain
clone.RPICameraEV = newPathConf.RPICameraEV
clone.RPICameraFPS = newPathConf.RPICameraFPS
clone.RPICameraIDRPeriod = newPathConf.RPICameraIDRPeriod
clone.RPICameraBitrate = newPathConf.RPICameraBitrate
return newPathConf.Equal(clone)
}

View File

@ -111,6 +111,27 @@ static void *output_thread(void *userdata) {
return NULL;
}
static bool fill_dynamic_params(int fd, const parameters_t *params) {
struct v4l2_control ctrl = {0};
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
ctrl.value = params->idr_period;
int res = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
if (res != 0) {
set_error("unable to set IDR period");
return false;
}
ctrl.id = V4L2_CID_MPEG_VIDEO_BITRATE;
ctrl.value = params->bitrate;
res = ioctl(fd, VIDIOC_S_CTRL, &ctrl);
if (res != 0) {
set_error("unable to set bitrate");
return false;
}
return true;
}
bool encoder_create(const parameters_t *params, int stride, int colorspace, encoder_output_cb output_cb, encoder_t **enc) {
*enc = malloc(sizeof(encoder_priv_t));
encoder_priv_t *encp = (encoder_priv_t *)(*enc);
@ -122,18 +143,15 @@ bool encoder_create(const parameters_t *params, int stride, int colorspace, enco
goto failed;
}
struct v4l2_control ctrl = {0};
ctrl.id = V4L2_CID_MPEG_VIDEO_BITRATE;
ctrl.value = params->bitrate;
int res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
if (res != 0) {
set_error("unable to set bitrate");
bool res2 = fill_dynamic_params(encp->fd, params);
if (!res2) {
goto failed;
}
struct v4l2_control ctrl = {0};
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_PROFILE;
ctrl.value = params->profile;
res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
int res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
if (res != 0) {
set_error("unable to set profile");
goto failed;
@ -147,14 +165,6 @@ bool encoder_create(const parameters_t *params, int stride, int colorspace, enco
goto failed;
}
ctrl.id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
ctrl.value = params->idr_period;
res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
if (res != 0) {
set_error("unable to set IDR period");
goto failed;
}
ctrl.id = V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER;
ctrl.value = 0;
res = ioctl(encp->fd, VIDIOC_S_CTRL, &ctrl);
@ -319,3 +329,9 @@ void encoder_encode(encoder_t *enc, int buffer_fd, size_t size, int64_t timestam
// it happens when the raspberry is under pressure. do not exit.
}
}
void encoder_reload_params(encoder_t *enc, const parameters_t *params) {
encoder_priv_t *encp = (encoder_priv_t *)enc;
fill_dynamic_params(encp->fd, params);
}

View File

@ -10,5 +10,6 @@ typedef void (*encoder_output_cb)(uint64_t ts, const uint8_t *buf, uint64_t size
const char *encoder_get_error();
bool encoder_create(const parameters_t *params, int stride, int colorspace, encoder_output_cb output_cb, encoder_t **enc);
void encoder_encode(encoder_t *enc, int buffer_fd, size_t size, int64_t timestamp_us);
void encoder_reload_params(encoder_t *enc, const parameters_t *params);
#endif

View File

@ -106,6 +106,7 @@ int main() {
continue;
}
camera_reload_params(cam, &params);
encoder_reload_params(enc, &params);
parameters_destroy(&params);
}
}