From 50f2a9eb8723136047027ea0c5c5616efd523322 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Fri, 8 Apr 2022 09:48:52 +0200 Subject: [PATCH] Support lowres capture --- cmd/camera.c | 4 +++ cmd/camera.h | 4 ++- cmd/camera_isp.c | 67 +++++++++++++++++++++++++--------------------- http/http.h | 4 +++ http/http_ffmpeg.c | 4 +-- http/http_h264.c | 18 +++++++++++-- http/http_jpeg.c | 20 +++++++++++--- 7 files changed, 83 insertions(+), 38 deletions(-) diff --git a/cmd/camera.c b/cmd/camera.c index 87a15c4..8c9dddf 100644 --- a/cmd/camera.c +++ b/cmd/camera.c @@ -115,6 +115,10 @@ int camera_set_params(camera_t *camera) // DEVICE_SET_OPTION(camera->camera, VBLANK, 1636); // DEVICE_SET_OPTION(camera->camera, HBLANK, 6906); + // DEVICE_SET_OPTION(camera->isp_srgb, RED_BALANCE, 2120); + // DEVICE_SET_OPTION(camera->isp_srgb, BLUE_BALANCE, 1472); + // DEVICE_SET_OPTION(camera->isp_srgb, DIGITAL_GAIN, 1007); + DEVICE_SET_OPTION2(camera->codec_jpeg, JPEG, COMPRESSION_QUALITY, 80); DEVICE_SET_OPTION2(camera->codec_h264, MPEG_VIDEO, BITRATE, 5000 * 1000); diff --git a/cmd/camera.h b/cmd/camera.h index bbdb0fe..1808452 100644 --- a/cmd/camera.h +++ b/cmd/camera.h @@ -32,9 +32,11 @@ typedef struct camera_s { device_t *legacy_isp; // convert pRAA/YUVU into YUVU device_t *isp_srgb; device_t *isp_yuuv; - device_t *isp_yuuv_low; + device_t *isp_yuuv_lowres; device_t *codec_jpeg; // encode YUVU into JPEG device_t *codec_h264; // encode YUVU into H264 + device_t *codec_jpeg_lowres; // encode YUVU into JPEG + device_t *codec_h264_lowres; // encode YUVU into H264 }; }; diff --git a/cmd/camera_isp.c b/cmd/camera_isp.c index 1f93086..78134c9 100644 --- a/cmd/camera_isp.c +++ b/cmd/camera_isp.c @@ -12,31 +12,22 @@ void write_yuvu(buffer_t *buffer); int camera_configure_isp(camera_t *camera, float high_div, float low_div) { - buffer_list_t *src = camera->camera->capture_list; - camera->isp_srgb = device_open("ISP", "/dev/video13"); camera->isp_yuuv = device_open("ISP-YUUV", "/dev/video14"); - camera->isp_yuuv->output_device = camera->isp_srgb; camera->codec_jpeg = device_open("JPEG", "/dev/video31"); camera->codec_h264 = device_open("H264", "/dev/video11"); - if (device_open_buffer_list_output(camera->isp_srgb, src) < 0 || - device_open_buffer_list_capture(camera->isp_yuuv, src, high_div, V4L2_PIX_FMT_YUYV, true) < 0) { + if (device_open_buffer_list_output(camera->isp_srgb, camera->camera->capture_list) < 0 || + device_open_buffer_list_capture(camera->isp_yuuv, camera->camera->capture_list, high_div, V4L2_PIX_FMT_YUYV, true) < 0) { return -1; } - if (low_div >= 1) { - camera->isp_yuuv_low = device_open("ISP-YUUV-LOW", "/dev/video15"); - camera->isp_yuuv_low->output_device = camera->isp_srgb; + camera->isp_yuuv->output_device = camera->isp_srgb; - if (device_open_buffer_list_capture(camera->isp_yuuv_low, src, low_div, V4L2_PIX_FMT_YUYV, true) < 0) { - return -1; - } + link_t *links = camera->links; + *links++ = (link_t){ camera->camera->capture_list, { camera->isp_srgb->output_list } }; - src = camera->isp_yuuv_low->capture_list; - } else { - src = camera->isp_yuuv->capture_list; - } + buffer_list_t *src = camera->isp_yuuv->capture_list; if (device_open_buffer_list_output(camera->codec_jpeg, src) < 0 || device_open_buffer_list_capture(camera->codec_jpeg, src, 1.0, V4L2_PIX_FMT_JPEG, true) < 0) { @@ -48,22 +39,38 @@ int camera_configure_isp(camera_t *camera, float high_div, float low_div) return -1; } - // DEVICE_SET_OPTION(camera->isp_srgb, RED_BALANCE, 2120); - // DEVICE_SET_OPTION(camera->isp_srgb, BLUE_BALANCE, 1472); - // DEVICE_SET_OPTION(camera->isp_srgb, DIGITAL_GAIN, 1007); - - link_t *links = camera->links; - - *links++ = (link_t){ camera->camera->capture_list, { camera->isp_srgb->output_list } }; - - if (camera->isp_yuuv_low) { - *links++ = (link_t){ camera->isp_yuuv->capture_list, { } }; - *links++ = (link_t){ camera->isp_yuuv_low->capture_list, { camera->codec_jpeg->output_list, camera->codec_h264->output_list }, { write_yuvu } }; - } else { - *links++ = (link_t){ camera->isp_yuuv->capture_list, { camera->codec_jpeg->output_list, camera->codec_h264->output_list }, { write_yuvu } }; - } - + *links++ = (link_t){ camera->isp_yuuv->capture_list, { camera->codec_jpeg->output_list, camera->codec_h264->output_list }, { write_yuvu } }; *links++ = (link_t){ camera->codec_jpeg->capture_list, { }, { http_jpeg_capture, http_jpeg_needs_buffer } }; *links++ = (link_t){ camera->codec_h264->capture_list, { }, { http_h264_capture, http_h264_needs_buffer } }; + + // all done + if (low_div < 1) { + return 0; + } + + camera->isp_yuuv_lowres = device_open("ISP-YUUV-LOW", "/dev/video15"); + camera->codec_jpeg_lowres = device_open("JPEG-LOW", "/dev/video31"); + camera->codec_h264_lowres = device_open("H264-LOW", "/dev/video11"); + + if (device_open_buffer_list_capture(camera->isp_yuuv_lowres, camera->camera->capture_list, low_div, V4L2_PIX_FMT_YUYV, true) < 0) { + return -1; + } + + camera->isp_yuuv_lowres->output_device = camera->isp_srgb; + src = camera->isp_yuuv_lowres->capture_list; + + if (device_open_buffer_list_output(camera->codec_jpeg_lowres, src) < 0 || + device_open_buffer_list_capture(camera->codec_jpeg_lowres, src, 1.0, V4L2_PIX_FMT_JPEG, true) < 0) { + return -1; + } + + if (device_open_buffer_list_output(camera->codec_h264_lowres, src) < 0 || + device_open_buffer_list_capture(camera->codec_h264_lowres, src, 1.0, V4L2_PIX_FMT_H264, true) < 0) { + return -1; + } + + *links++ = (link_t){ camera->isp_yuuv_lowres->capture_list, { camera->codec_jpeg_lowres->output_list, camera->codec_h264_lowres->output_list }, { write_yuvu } }; + *links++ = (link_t){ camera->codec_jpeg_lowres->capture_list, { }, { http_jpeg_lowres_capture, http_jpeg_needs_buffer } }; + *links++ = (link_t){ camera->codec_h264_lowres->capture_list, { }, { http_h264_lowres_capture, http_h264_needs_buffer } }; return 0; } diff --git a/http/http.h b/http/http.h index fac1b64..25f0b06 100644 --- a/http/http.h +++ b/http/http.h @@ -47,12 +47,16 @@ void http_404(http_worker_t *worker, FILE *stream); void http_snapshot(http_worker_t *worker, FILE *stream); void http_stream(http_worker_t *worker, FILE *stream); void http_jpeg_capture(struct buffer_s *buf); +void http_jpeg_lowres_capture(struct buffer_s *buf); bool http_jpeg_needs_buffer(); // H264 bool http_h264_needs_buffer(); void http_h264_capture(buffer_t *buf); +void http_h264_lowres_capture(buffer_t *buf); void http_h264_video(http_worker_t *worker, FILE *stream); void http_mkv_video(http_worker_t *worker, FILE *stream); void http_mp4_video(http_worker_t *worker, FILE *stream); void http_mov_video(http_worker_t *worker, FILE *stream); + +#define HTTP_LOW_RES_PARAM "res=low" diff --git a/http/http_ffmpeg.c b/http/http_ffmpeg.c index 7811380..4b0f167 100644 --- a/http/http_ffmpeg.c +++ b/http/http_ffmpeg.c @@ -13,7 +13,7 @@ #include #include -DECLARE_BUFFER_LOCK(http_h264); +buffer_lock_t *http_h264_buffer_for_res(http_worker_t *worker); static const char *const VIDEO_HEADER = "HTTP/1.0 200 OK\r\n" @@ -307,7 +307,7 @@ static void http_ffmpeg_video(http_worker_t *worker, FILE *stream, const char *c av_dict_set_int(&status.output_opts, "nobuffer", 1, 0); av_dict_set_int(&status.output_opts, "flush_packets", 1, 0); - int n = buffer_lock_write_loop(&http_h264, 0, (buffer_write_fn)http_ffmpeg_video_buf_part, &status); + int n = buffer_lock_write_loop(http_h264_buffer_for_res(worker), 0, (buffer_write_fn)http_ffmpeg_video_buf_part, &status); http_ffmpeg_close_status(&status); if (status.wrote_header) { diff --git a/http/http_h264.c b/http/http_h264.c index 5f72168..1c8af49 100644 --- a/http/http_h264.c +++ b/http/http_h264.c @@ -8,6 +8,7 @@ #include "hw/device.h" DEFINE_BUFFER_LOCK(http_h264, 0); +DEFINE_BUFFER_LOCK(http_h264_lowres, 0); static const char *const VIDEO_HEADER = "HTTP/1.0 200 OK\r\n" @@ -21,9 +22,22 @@ void http_h264_capture(buffer_t *buf) buffer_lock_capture(&http_h264, buf); } +void http_h264_lowres_capture(buffer_t *buf) +{ + buffer_lock_capture(&http_h264_lowres, buf); +} + bool http_h264_needs_buffer() { - return buffer_lock_needs_buffer(&http_h264); + return buffer_lock_needs_buffer(&http_h264) | buffer_lock_needs_buffer(&http_h264_lowres); +} + +buffer_lock_t *http_h264_buffer_for_res(http_worker_t *worker) +{ + if (strstr(worker->client_method, HTTP_LOW_RES_PARAM)) + return &http_h264_lowres; + else + return &http_h264; } typedef struct { @@ -67,7 +81,7 @@ void http_h264_video(http_worker_t *worker, FILE *stream) { http_video_status_t status = { stream }; - int n = buffer_lock_write_loop(&http_h264, 0, (buffer_write_fn)http_video_buf_part, &status); + int n = buffer_lock_write_loop(http_h264_buffer_for_res(worker), 0, (buffer_write_fn)http_video_buf_part, &status); if (status.wrote_header) { return; diff --git a/http/http_jpeg.c b/http/http_jpeg.c index 8950281..2f7e1e3 100644 --- a/http/http_jpeg.c +++ b/http/http_jpeg.c @@ -6,6 +6,7 @@ #include "hw/buffer_lock.h" DEFINE_BUFFER_LOCK(http_jpeg, 1000); +DEFINE_BUFFER_LOCK(http_jpeg_lowres, 1000); #define PART_BOUNDARY "123456789000000000000987654321" #define CONTENT_TYPE "image/jpeg" @@ -31,7 +32,7 @@ static const char *const STREAM_BOUNDARY = "\r\n" bool http_jpeg_needs_buffer() { - return buffer_lock_needs_buffer(&http_jpeg); + return buffer_lock_needs_buffer(&http_jpeg) | buffer_lock_needs_buffer(&http_jpeg_lowres); } void http_jpeg_capture(buffer_t *buf) @@ -39,6 +40,19 @@ void http_jpeg_capture(buffer_t *buf) buffer_lock_capture(&http_jpeg, buf); } +void http_jpeg_lowres_capture(buffer_t *buf) +{ + buffer_lock_capture(&http_jpeg_lowres, buf); +} + +buffer_lock_t *http_jpeg_buffer_for_res(http_worker_t *worker) +{ + if (strstr(worker->client_method, HTTP_LOW_RES_PARAM)) + return &http_jpeg_lowres; + else + return &http_jpeg; +} + int http_snapshot_buf_part(buffer_lock_t *buf_lock, buffer_t *buf, int frame, FILE *stream) { fprintf(stream, "HTTP/1.1 200 OK\r\n"); @@ -51,7 +65,7 @@ int http_snapshot_buf_part(buffer_lock_t *buf_lock, buffer_t *buf, int frame, FI void http_snapshot(http_worker_t *worker, FILE *stream) { - int n = buffer_lock_write_loop(&http_jpeg, 1, (buffer_write_fn)http_snapshot_buf_part, stream); + int n = buffer_lock_write_loop(http_jpeg_buffer_for_res(worker), 1, (buffer_write_fn)http_snapshot_buf_part, stream); if (n <= 0) { http_500_header(stream); @@ -79,7 +93,7 @@ int http_stream_buf_part(buffer_lock_t *buf_lock, buffer_t *buf, int frame, FILE void http_stream(http_worker_t *worker, FILE *stream) { - int n = buffer_lock_write_loop(&http_jpeg, 0, (buffer_write_fn)http_stream_buf_part, stream); + int n = buffer_lock_write_loop(http_jpeg_buffer_for_res(worker), 0, (buffer_write_fn)http_stream_buf_part, stream); if (n == 0) { http_500_header(stream);