using frame_s as common data storage

This commit is contained in:
Devaev Maxim
2020-12-27 03:10:52 +03:00
parent 3b223f5c49
commit 22d108f7ad
13 changed files with 66 additions and 57 deletions

View File

@@ -28,11 +28,13 @@ frame_s *frame_init(const char *role) {
A_CALLOC(frame, 1);
frame->role = role;
frame->managed = true;
frame_realloc_data(frame, 500 * 1024);
return frame;
}
void frame_destroy(frame_s *frame) {
assert(frame->managed);
if (frame->data) {
free(frame->data);
}
@@ -40,6 +42,7 @@ void frame_destroy(frame_s *frame) {
}
void frame_realloc_data(frame_s *frame, size_t size) {
assert(frame->managed);
if (frame->allocated < size) {
LOG_DEBUG("Increasing frame buffer '%s': %zu -> %zu (+%zu)",
frame->role, frame->allocated, size, size - frame->allocated);
@@ -49,12 +52,15 @@ void frame_realloc_data(frame_s *frame, size_t size) {
}
void frame_set_data(frame_s *frame, const uint8_t *data, size_t size) {
assert(frame->managed);
frame_realloc_data(frame, size);
memcpy(frame->data, data, size);
frame->used = size;
}
void frame_append_data(frame_s *frame, const uint8_t *data, size_t size) {
assert(frame->managed);
size_t new_used = frame->used + size;
frame_realloc_data(frame, new_used);
@@ -63,6 +69,8 @@ void frame_append_data(frame_s *frame, const uint8_t *data, size_t size) {
}
void frame_copy(const frame_s *src, frame_s *dest) {
assert(dest->managed);
frame_set_data(dest, src->data, src->used);
# define COPY(_field) dest->_field = src->_field
@@ -72,6 +80,7 @@ void frame_copy(const frame_s *src, frame_s *dest) {
COPY(width);
COPY(height);
COPY(format);
COPY(grab_ts);
COPY(encode_begin_ts);

View File

@@ -35,14 +35,19 @@
typedef struct {
const char *role;
uint8_t *data;
size_t used;
size_t allocated;
unsigned width;
unsigned height;
unsigned format;
long double grab_ts;
long double encode_begin_ts;
long double encode_end_ts;
bool managed;
} frame_s;

View File

@@ -178,14 +178,14 @@ void device_close(device_s *dev) {
# define HW(_next) RUN(hw_buffers)[index]._next
if (dev->io_method == V4L2_MEMORY_MMAP) {
if (HW(allocated) > 0 && HW(data) != MAP_FAILED) {
if (munmap(HW(data), HW(allocated)) < 0) {
if (HW(raw.allocated) > 0 && HW(raw.data) != MAP_FAILED) {
if (munmap(HW(raw.data), HW(raw.allocated)) < 0) {
LOG_PERROR("Can't unmap device buffer %u", index);
}
}
} else { // V4L2_MEMORY_USERPTR
if (HW(data)) {
free(HW(data));
if (HW(raw.data)) {
free(HW(raw.data));
}
}
A_MUTEX_DESTROY(&HW(grabbed_mutex));
@@ -321,12 +321,12 @@ int device_grab_buffer(device_s *dev) {
HW(grabbed) = true;
A_MUTEX_UNLOCK(&HW(grabbed_mutex));
HW(used) = buf_info.bytesused;
HW(width) = RUN(width);
HW(height) = RUN(height);
HW(format) = RUN(format);
HW(raw.used) = buf_info.bytesused;
HW(raw.width) = RUN(width);
HW(raw.height) = RUN(height);
HW(raw.format) = RUN(format);
memcpy(&HW(buf_info), &buf_info, sizeof(struct v4l2_buffer));
HW(grab_ts) = get_now_monotonic();
HW(raw.grab_ts) = get_now_monotonic();
# undef HW
return buf_info.index;
@@ -625,7 +625,7 @@ static int _device_open_io_method_mmap(device_s *dev) {
A_MUTEX_INIT(&HW(grabbed_mutex));
LOG_DEBUG("Mapping device buffer %u ...", RUN(n_buffers));
if ((HW(data) = mmap(
if ((HW(raw.data) = mmap(
NULL,
buf_info.length,
PROT_READ | PROT_WRITE,
@@ -636,7 +636,7 @@ static int _device_open_io_method_mmap(device_s *dev) {
LOG_PERROR("Can't map device buffer %u", RUN(n_buffers));
return -1;
}
HW(allocated) = buf_info.length;
HW(raw.allocated) = buf_info.length;
# undef HW
}
@@ -672,9 +672,9 @@ static int _device_open_io_method_userptr(device_s *dev) {
for (RUN(n_buffers) = 0; RUN(n_buffers) < req.count; ++RUN(n_buffers)) {
# define HW(_next) RUN(hw_buffers)[RUN(n_buffers)]._next
assert(HW(data) = aligned_alloc(page_size, buf_size));
memset(HW(data), 0, buf_size);
HW(allocated) = buf_size;
assert(HW(raw.data) = aligned_alloc(page_size, buf_size));
memset(HW(raw.data), 0, buf_size);
HW(raw.allocated) = buf_size;
# undef HW
}
@@ -690,8 +690,8 @@ static int _device_open_queue_buffers(device_s *dev) {
buf_info.memory = dev->io_method;
buf_info.index = index;
if (dev->io_method == V4L2_MEMORY_USERPTR) {
buf_info.m.userptr = (unsigned long)RUN(hw_buffers)[index].data;
buf_info.length = RUN(hw_buffers)[index].allocated;
buf_info.m.userptr = (unsigned long)RUN(hw_buffers)[index].raw.data;
buf_info.length = RUN(hw_buffers)[index].raw.allocated;
}
LOG_DEBUG("Calling ioctl(VIDIOC_QBUF) for buffer %u ...", index);

View File

@@ -44,6 +44,7 @@
#include "../common/tools.h"
#include "../common/logging.h"
#include "../common/threading.h"
#include "../common/frame.h"
#include "xioctl.h"
@@ -71,13 +72,7 @@
typedef struct {
uint8_t *data;
size_t used;
size_t allocated;
unsigned width;
unsigned height;
unsigned format;
long double grab_ts;
frame_s raw;
struct v4l2_buffer buf_info;

View File

@@ -207,26 +207,26 @@ void encoder_get_runtime_params(encoder_s *encoder, encoder_type_e *type, unsign
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic push
int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, hw_buffer_s *hw, frame_s *frame) {
int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, frame_s *raw, frame_s *frame) {
#pragma GCC diagnostic pop
assert(ER(type) != ENCODER_TYPE_UNKNOWN);
assert(hw->used > 0);
assert(raw->used > 0);
frame->grab_ts = hw->grab_ts;
frame->grab_ts = raw->grab_ts;
frame->encode_begin_ts = get_now_monotonic();
if (ER(type) == ENCODER_TYPE_CPU) {
LOG_VERBOSE("Compressing buffer using CPU");
cpu_encoder_compress_buffer(hw, frame, ER(quality));
cpu_encoder_compress_buffer(raw, frame, ER(quality));
} else if (ER(type) == ENCODER_TYPE_HW) {
LOG_VERBOSE("Compressing buffer using HW (just copying)");
hw_encoder_compress_buffer(hw, frame);
hw_encoder_compress_buffer(raw, frame);
}
# ifdef WITH_OMX
else if (ER(type) == ENCODER_TYPE_OMX) {
LOG_VERBOSE("Compressing buffer using OMX");
if (omx_encoder_compress_buffer(ER(omxs[worker_number]), hw, frame) < 0) {
if (omx_encoder_compress_buffer(ER(omxs[worker_number]), raw, frame) < 0) {
goto error;
}
}
@@ -240,8 +240,9 @@ int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, hw_buffe
frame->encode_end_ts = get_now_monotonic();
frame->width = hw->width;
frame->height = hw->height;
frame->width = raw->width;
frame->height = raw->height;
// frame->format = V4L2_PIX_FMT_JPEG;
return 0;

View File

@@ -111,4 +111,4 @@ const char *encoder_type_to_string(encoder_type_e type);
void encoder_prepare(encoder_s *encoder, device_s *dev);
void encoder_get_runtime_params(encoder_s *encoder, encoder_type_e *type, unsigned *quality);
int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, hw_buffer_s *hw, frame_s *frame);
int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, frame_s *raw, frame_s *frame);

View File

@@ -58,7 +58,7 @@ static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg);
static void _jpeg_term_destination(j_compress_ptr jpeg);
void cpu_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame, unsigned quality) {
void cpu_encoder_compress_buffer(frame_s *raw, frame_s *frame, unsigned quality) {
// This function based on compress_image_to_jpeg() from mjpg-streamer
struct jpeg_compress_struct jpeg;
@@ -69,8 +69,8 @@ void cpu_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame, unsigned quali
_jpeg_set_picture(&jpeg, frame);
jpeg.image_width = hw->width;
jpeg.image_height = hw->height;
jpeg.image_width = raw->width;
jpeg.image_height = raw->height;
jpeg.input_components = 3;
jpeg.in_color_space = JCS_RGB;
@@ -80,9 +80,9 @@ void cpu_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame, unsigned quali
jpeg_start_compress(&jpeg, TRUE);
# define WRITE_SCANLINES(_format, _func) \
case _format: { _func(&jpeg, hw->data, hw->width, hw->height); break; }
case _format: { _func(&jpeg, raw->data, raw->width, raw->height); break; }
switch (hw->format) {
switch (raw->format) {
// https://www.fourcc.org/yuv.php
WRITE_SCANLINES(V4L2_PIX_FMT_YUYV, _jpeg_write_scanlines_yuyv);
WRITE_SCANLINES(V4L2_PIX_FMT_UYVY, _jpeg_write_scanlines_uyvy);

View File

@@ -33,7 +33,6 @@
#include "../../../common/tools.h"
#include "../../../common/frame.h"
#include "../../device.h"
void cpu_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame, unsigned quality);
void cpu_encoder_compress_buffer(frame_s *raw, frame_s *frame, unsigned quality);

View File

@@ -28,7 +28,7 @@
#include "encoder.h"
void _copy_plus_huffman(const hw_buffer_s *src, frame_s *dest);
void _copy_plus_huffman(const frame_s *src, frame_s *dest);
static bool _is_huffman(const uint8_t *data);
@@ -49,14 +49,14 @@ int hw_encoder_prepare(device_s *dev, unsigned quality) {
return 0;
}
void hw_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame) {
if (hw->format != V4L2_PIX_FMT_MJPEG && hw->format != V4L2_PIX_FMT_JPEG) {
void hw_encoder_compress_buffer(frame_s *raw, frame_s *frame) {
if (raw->format != V4L2_PIX_FMT_MJPEG && raw->format != V4L2_PIX_FMT_JPEG) {
assert(0 && "Unsupported input format for HW encoder");
}
_copy_plus_huffman(hw, frame);
_copy_plus_huffman(raw, frame);
}
void _copy_plus_huffman(const hw_buffer_s *src, frame_s *dest) {
void _copy_plus_huffman(const frame_s *src, frame_s *dest) {
if (!_is_huffman(src->data)) {
const uint8_t *src_ptr = src->data;
const uint8_t *src_end = src->data + src->used;

View File

@@ -39,4 +39,4 @@
int hw_encoder_prepare(device_s *dev, unsigned quality);
void hw_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame);
void hw_encoder_compress_buffer(frame_s *raw, frame_s *frame);

View File

@@ -154,12 +154,12 @@ int omx_encoder_prepare(omx_encoder_s *omx, device_s *dev, unsigned quality) {
return 0;
}
int omx_encoder_compress_buffer(omx_encoder_s *omx, hw_buffer_s *hw, frame_s *frame) {
int omx_encoder_compress_buffer(omx_encoder_s *omx, frame_s *raw, frame_s *frame) {
# define IN(_next) omx->input_buffer->_next
# define OUT(_next) omx->output_buffer->_next
OMX_ERRORTYPE error;
size_t slice_size = (IN(nAllocLen) < hw->used ? IN(nAllocLen) : hw->used);
size_t slice_size = (IN(nAllocLen) < raw->used ? IN(nAllocLen) : raw->used);
size_t pos = 0;
if ((error = OMX_FillThisBuffer(omx->encoder, omx->output_buffer)) != OMX_ErrorNone) {
@@ -195,18 +195,18 @@ int omx_encoder_compress_buffer(omx_encoder_s *omx, hw_buffer_s *hw, frame_s *fr
if (omx->input_required) {
omx->input_required = false;
if (pos == hw->used) {
if (pos == raw->used) {
continue;
}
memcpy(IN(pBuffer), hw->data + pos, slice_size);
memcpy(IN(pBuffer), raw->data + pos, slice_size);
IN(nOffset) = 0;
IN(nFilledLen) = slice_size;
pos += slice_size;
if (pos + slice_size > hw->used) {
slice_size = hw->used - pos;
if (pos + slice_size > raw->used) {
slice_size = raw->used - pos;
}
if ((error = OMX_EmptyThisBuffer(omx->encoder, omx->input_buffer)) != OMX_ErrorNone) {

View File

@@ -71,4 +71,4 @@ omx_encoder_s *omx_encoder_init(void);
void omx_encoder_destroy(omx_encoder_s *omx);
int omx_encoder_prepare(omx_encoder_s *omx, device_s *dev, unsigned quality);
int omx_encoder_compress_buffer(omx_encoder_s *omx, hw_buffer_s *hw, frame_s *frame);
int omx_encoder_compress_buffer(omx_encoder_s *omx, frame_s *raw, frame_s *frame);

View File

@@ -209,15 +209,15 @@ void stream_loop(stream_s *stream) {
LOG_VERBOSE("Fluency: delay=%.03Lf, grab_after=%.03Lf", fluency_delay, grab_after);
# ifdef WITH_RAWSINK
# define HW(_next) DEV(run->hw_buffers[buf_index]._next)
# define RAW(_next) DEV(run->hw_buffers[buf_index].raw._next)
if (stream->rawsink && rawsink_server_put(
stream->rawsink, HW(data), HW(used), HW(format),
HW(width), HW(height), HW(grab_ts), true
stream->rawsink, RAW(data), RAW(used), RAW(format),
RAW(width), RAW(height), RAW(grab_ts), true
) < 0) {
stream->rawsink = NULL;
LOG_ERROR("RAW sink completely disabled due error");
}
# undef HW
# undef RAW
# endif
_workers_pool_assign(pool, ready_wr, buf_index);
@@ -484,7 +484,7 @@ static void *_worker_thread(void *v_worker) {
wr->job_failed = (bool)encoder_compress_buffer(
wr->stream->encoder,
wr->number,
&wr->stream->dev->run->hw_buffers[wr->buf_index],
&wr->stream->dev->run->hw_buffers[wr->buf_index].raw,
wr->frame
);