diff --git a/buffer.c b/buffer.c index 12e42c7..81fb25d 100644 --- a/buffer.c +++ b/buffer.c @@ -19,16 +19,15 @@ buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int index) { if (buf_list->do_mplanes) { buf->v4l2_buffer.length = 1; buf->v4l2_buffer.m.planes = &buf->v4l2_plane; + buf->v4l2_plane.data_offset = 0; } - if (!buf_list->do_mmap) { - // nothing to do here + if (buf_list->do_mmap) { + buf->v4l2_buffer.memory = V4L2_MEMORY_MMAP; + } else { buf->v4l2_buffer.memory = V4L2_MEMORY_DMABUF; - return buf; } - buf->v4l2_buffer.memory = V4L2_MEMORY_MMAP; - E_XIOCTL(buf_list, dev->fd, VIDIOC_QUERYBUF, &buf->v4l2_buffer, "Cannot query buffer %d", index); if (buf_list->do_mplanes) { @@ -39,9 +38,11 @@ buffer_t *buffer_open(const char *name, buffer_list_t *buf_list, int index) { buf->length = buf->v4l2_buffer.length; } - buf->start = mmap(NULL, buf->length, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, buf->offset); - if (buf->start == MAP_FAILED) { - goto error; + if (buf_list->do_mmap) { + buf->start = mmap(NULL, buf->length, PROT_READ | PROT_WRITE, MAP_SHARED, dev->fd, buf->offset); + if (buf->start == MAP_FAILED) { + goto error; + } } if (buf_list->do_dma) { diff --git a/buffer_list.c b/buffer_list.c index 7985688..dd11940 100644 --- a/buffer_list.c +++ b/buffer_list.c @@ -77,7 +77,7 @@ int buffer_list_set_format(buffer_list_t *buf_list, unsigned width, unsigned hei fmt->fmt.pix_mp.pixelformat = format; fmt->fmt.pix_mp.field = V4L2_FIELD_ANY; fmt->fmt.pix_mp.num_planes = 1; - //fmt->fmt.pix_mp.plane_fmt[0].bytesperline = fourcc_to_stride(width, format); + //fmt->fmt.pix_mp.plane_fmt[0].bytesperline = width; // fourcc_to_stride(width, format); } else { fmt->fmt.pix.colorspace = V4L2_COLORSPACE_RAW; fmt->fmt.pix.width = width; @@ -184,7 +184,9 @@ int buffer_list_stream(buffer_list_t *buf_list, bool do_on) // re-enqueue buffers on stream start if (buf_list->streaming && buf_list->do_capture && !buf->enqueued && buf->mmap_reflinks == 1) { - buffer_consumed(buf); + if (buf_list->do_mmap) { + buffer_consumed(buf); + } } } diff --git a/buffer_queue.c b/buffer_queue.c index 81ce415..613d2aa 100644 --- a/buffer_queue.c +++ b/buffer_queue.c @@ -39,6 +39,7 @@ bool buffer_consumed(buffer_t *buf) if (buf->buf_list->do_mplanes) { buf->v4l2_plane.bytesused = buf->used; buf->v4l2_plane.length = buf->length; + buf->v4l2_plane.data_offset = 0; } else { buf->v4l2_buffer.bytesused = buf->used; } diff --git a/main_decode.c b/main_decode.c new file mode 100644 index 0000000..9fb89c6 --- /dev/null +++ b/main_decode.c @@ -0,0 +1,150 @@ +#include "buffer.h" +#include "buffer_list.h" +#include "device.h" +#include "links.h" +#include "v4l2.h" +#include "http.h" + +#include + +int camera_width = 1280; +int camera_height = 720; +int camera_format = V4L2_PIX_FMT_SRGGB10P; +int camera_nbufs = 1; +bool camera_use_low = true; + +device_t *camera = NULL; +device_t *isp_yuuv = NULL; +device_t *codec_jpeg = NULL; +device_t *codec_h264 = NULL; + +int open_isp(buffer_list_t *src, const char *srgb_path, const char *yuuv_path, const char *yuuv_low_path) +{ + if (device_open_buffer_list(isp_yuuv, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs) < 0 || + device_open_buffer_list(isp_yuuv, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_YUYV, camera_nbufs) < 0) { + return -1; + } + + return 0; +} + +int open_jpeg(buffer_list_t *src, const char *tmp) +{ + DEVICE_SET_OPTION2(codec_jpeg, JPEG, COMPRESSION_QUALITY, 80); + + if (device_open_buffer_list(codec_jpeg, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs) < 0 || + device_open_buffer_list(codec_jpeg, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_JPEG, camera_nbufs) < 0) { + return -1; + } + return 0; +} + +int open_h264(buffer_list_t *src, const char *tmp) +{ + DEVICE_SET_OPTION2(codec_h264, MPEG_VIDEO, BITRATE, 5000 * 1000); + DEVICE_SET_OPTION2(codec_h264, MPEG_VIDEO, H264_I_PERIOD, 30); + DEVICE_SET_OPTION2(codec_h264, MPEG_VIDEO, H264_LEVEL, V4L2_MPEG_VIDEO_H264_LEVEL_4_0); + DEVICE_SET_OPTION2(codec_h264, MPEG_VIDEO, REPEAT_SEQ_HEADER, 1); + DEVICE_SET_OPTION2(codec_h264, MPEG_VIDEO, H264_MIN_QP, 16); + DEVICE_SET_OPTION2(codec_h264, MPEG_VIDEO, H264_MIN_QP, 32); + + if (device_open_buffer_list(codec_h264, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs) < 0 || + device_open_buffer_list(codec_h264, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_H264, camera_nbufs) < 0) { + return -1; + } + return 0; +} + +int open_camera() +{ + camera = device_open("CAMERA", "/dev/video0"); + + if (device_open_buffer_list(camera, true, camera_width, camera_height, camera_format, camera_nbufs) < 0) { + return -1; + } + + DEVICE_SET_OPTION(camera, EXPOSURE, 1148); + DEVICE_SET_OPTION(camera, ANALOGUE_GAIN, 938); + DEVICE_SET_OPTION(camera, DIGITAL_GAIN, 256); + + isp_yuuv = device_open("ISP-YUUV", "/dev/video12"); + codec_jpeg = device_open("JPEG", "/dev/video31"); + codec_h264 = device_open("H264", "/dev/video11"); + //codec_h264->allow_dma = false; + + if (open_isp(camera->capture_list, "/dev/video13", "/dev/video14", "/dev/video15") < 0) { + return -1; + } + if (open_jpeg(camera_use_low ? isp_yuuv->capture_list : isp_yuuv->capture_list, "/dev/video31") < 0) { + return -1; + } + if (open_h264(camera_use_low ? isp_yuuv->capture_list : isp_yuuv->capture_list, "/dev/video11") < 0) { + return -1; + } + + return 0; +} + +bool check_streaming() +{ + return http_jpeg_needs_buffer() || http_h264_needs_buffer(); +} + +int main(int argc, char *argv[]) +{ + if (open_camera() < 0) { + return -1; + } + + link_t links[] = { + { + camera, + { isp_yuuv }, + { NULL, check_streaming } + }, + { + isp_yuuv, + { + codec_jpeg, + }, + { NULL, NULL } + }, + { + codec_jpeg, + { }, + { http_jpeg_capture, http_jpeg_needs_buffer } + }, + { + // codec_h264, + // { }, + // { http_h264_capture, http_h264_needs_buffer } + }, + { NULL } + }; + + http_method_t http_methods[] = { + { "GET / ", http_index }, + { "GET /snapshot ", http_snapshot }, + { "GET /stream ", http_stream }, + { "GET /?action=snapshot ", http_snapshot }, + { "GET /?action=stream ", http_stream }, + { "GET /video ", http_video_html }, + { "GET /video.h264 ", http_video }, + { "GET /jmuxer.min.js ", http_jmuxer_js }, + { NULL, NULL } + }; + + sigaction(SIGPIPE, &(struct sigaction){SIG_IGN}, NULL); + + int http_fd = http_server(9092, 5, http_methods); + + bool running = false; + links_loop(links, &running); + + close(http_fd); + +error: + device_close(isp_yuuv); + device_close(camera); + return 0; +} diff --git a/main.c b/main_isp.c.bak similarity index 89% rename from main.c rename to main_isp.c.bak index 3386e27..38853d1 100644 --- a/main.c +++ b/main_isp.c.bak @@ -7,11 +7,11 @@ #include -int camera_width = 1920; -int camera_height = 1080; +int camera_width = 1280; +int camera_height = 720; int camera_format = V4L2_PIX_FMT_SRGGB10P; -int camera_nbufs = 4; -bool camera_use_low = false; +int camera_nbufs = 1; +bool camera_use_low = true; device_t *camera = NULL; device_t *isp_srgb = NULL; @@ -40,7 +40,7 @@ int open_jpeg(buffer_list_t *src, const char *tmp) DEVICE_SET_OPTION2(codec_jpeg, JPEG, COMPRESSION_QUALITY, 80); if (device_open_buffer_list(codec_jpeg, false, src->fmt_width, src->fmt_height, src->fmt_format, camera_nbufs) < 0 || - device_open_buffer_list(codec_jpeg, true, src->fmt_width, src->fmt_height, V4L2_PIX_FMT_JPEG, camera_nbufs) < 0) { + device_open_buffer_list(codec_jpeg, true, codec_jpeg->output_list->fmt_width, codec_jpeg->output_list->fmt_height, V4L2_PIX_FMT_JPEG, camera_nbufs) < 0) { return -1; } return 0; @@ -81,9 +81,9 @@ int open_camera() isp_yuuv_low = device_open("ISP-YUUV-LOW", "/dev/video15"); isp_yuuv_low->output_device = isp_srgb; codec_jpeg = device_open("JPEG", "/dev/video31"); - codec_jpeg->allow_dma = false; + //codec_jpeg->allow_dma = false; codec_h264 = device_open("H264", "/dev/video11"); - codec_h264->allow_dma = false; + //codec_h264->allow_dma = false; if (open_isp(camera->capture_list, "/dev/video13", "/dev/video14", "/dev/video15") < 0) { return -1; @@ -119,7 +119,7 @@ int main(int argc, char *argv[]) isp_yuuv, { camera_use_low ? NULL : codec_jpeg, - camera_use_low ? NULL : codec_h264, + //camera_use_low ? NULL : codec_h264, }, { NULL, NULL } }, @@ -127,7 +127,7 @@ int main(int argc, char *argv[]) isp_yuuv_low, { camera_use_low ? codec_jpeg : NULL, - camera_use_low ? codec_h264 : NULL, + //camera_use_low ? codec_h264 : NULL, }, { NULL, NULL } }, @@ -137,9 +137,9 @@ int main(int argc, char *argv[]) { http_jpeg_capture, http_jpeg_needs_buffer } }, { - codec_h264, - { }, - { http_h264_capture, http_h264_needs_buffer } + // codec_h264, + // { }, + // { http_h264_capture, http_h264_needs_buffer } }, { NULL } }; diff --git a/v4l2.c b/v4l2.c index 7cddd32..09f66c3 100644 --- a/v4l2.c +++ b/v4l2.c @@ -57,6 +57,9 @@ unsigned fourcc_to_stride(unsigned width, unsigned format) case V4L2_PIX_FMT_RGB565: return align_size(width * 2, 32); + case V4L2_PIX_FMT_YUV420: + return align_size(width * 3 / 2, 32); + case V4L2_PIX_FMT_RGB24: return align_size(width * 3, 32);