diff --git a/python/frame.c b/python/frame.c new file mode 120000 index 0000000..594f913 --- /dev/null +++ b/python/frame.c @@ -0,0 +1 @@ +../src/libs/frame.c \ No newline at end of file diff --git a/python/frame.h b/python/frame.h new file mode 120000 index 0000000..3a7efc5 --- /dev/null +++ b/python/frame.h @@ -0,0 +1 @@ +../src/libs/frame.h \ No newline at end of file diff --git a/python/memsinksh.h b/python/memsinksh.h new file mode 120000 index 0000000..191992e --- /dev/null +++ b/python/memsinksh.h @@ -0,0 +1 @@ +../src/libs/memsinksh.h \ No newline at end of file diff --git a/python/setup.py b/python/setup.py index 5c06650..b42d671 100644 --- a/python/setup.py +++ b/python/setup.py @@ -1,3 +1,5 @@ +import os + from distutils.core import Extension from distutils.core import setup @@ -16,11 +18,8 @@ if __name__ == "__main__": "ustreamer", libraries=["rt", "m", "pthread"], undef_macros=["NDEBUG"], - sources=["ustreamer.c"], - depends=[ - "../src/libs/tools.h", - "../src/libs/memsinksh.h", - ], + sources=[name for name in os.listdir(".") if name.endswith(".c")], + depends=[name for name in os.listdir(".") if name.endswith(".h")], ), ], ) diff --git a/python/tools.h b/python/tools.h new file mode 120000 index 0000000..0f7430d --- /dev/null +++ b/python/tools.h @@ -0,0 +1 @@ +../src/libs/tools.h \ No newline at end of file diff --git a/python/ustreamer.c b/python/ustreamer.c index 1b73294..10843f3 100644 --- a/python/ustreamer.c +++ b/python/ustreamer.c @@ -13,31 +13,11 @@ #include -#include "../src/libs/tools.h" // Just a header without C-sources -#include "../src/libs/memsinksh.h" // No sources again +#include "tools.h" +#include "frame.h" +#include "memsinksh.h" -typedef struct { - uint64_t id; - long double ts; - - uint8_t *data; - size_t used; - size_t allocated; - - unsigned width; - unsigned height; - unsigned format; - unsigned stride; - - bool online; - bool key; - - long double grab_ts; - long double encode_begin_ts; - long double encode_end_ts; -} tmp_frame_s; - typedef struct { PyObject_HEAD @@ -49,12 +29,14 @@ typedef struct { int fd; memsink_shared_s *mem; - tmp_frame_s *tmp_frame; + uint64_t frame_id; + long double frame_ts; + frame_s *frame; } MemsinkObject; -#define MEM(_next) self->mem->_next -#define TMP(_next) self->tmp_frame->_next +#define MEM(_next) self->mem->_next +#define FRAME(_next) self->frame->_next static void MemsinkObject_destroy_internals(MemsinkObject *self) { @@ -66,12 +48,9 @@ static void MemsinkObject_destroy_internals(MemsinkObject *self) { close(self->fd); self->fd = -1; } - if (self->tmp_frame) { - if (TMP(data)) { - free(TMP(data)); - } - free(self->tmp_frame); - self->tmp_frame = NULL; + if (self->frame) { + frame_destroy(self->frame); + self->frame = NULL; } } @@ -99,9 +78,7 @@ static int MemsinkObject_init(MemsinkObject *self, PyObject *args, PyObject *kwa # undef SET_DOUBLE - A_CALLOC(self->tmp_frame, 1); - TMP(allocated) = 512 * 1024; - A_REALLOC(TMP(data), TMP(allocated)); + self->frame = frame_init("memsink_client"); if ((self->fd = shm_open(self->obj, O_RDWR, 0)) == -1) { PyErr_SetFromErrno(PyExc_OSError); @@ -177,24 +154,16 @@ static int wait_frame(MemsinkObject *self) { RETURN_OS_ERROR; } else if (retval == 0) { - if (MEM(magic) == MEMSINK_MAGIC && MEM(version) == MEMSINK_VERSION && TMP(id) != MEM(id)) { + if (MEM(magic) == MEMSINK_MAGIC && MEM(version) == MEMSINK_VERSION && MEM(id) != self->frame_id) { if (self->drop_same_frames > 0) { -# define CMP(_field) (TMP(_field) == MEM(_field)) if ( - CMP(used) - && CMP(width) - && CMP(height) - && CMP(format) - && CMP(stride) - && CMP(online) - && CMP(key) - && (TMP(ts) + self->drop_same_frames > now) - && !memcmp(TMP(data), MEM(data), MEM(used)) + FRAME_COMPARE_META_USED_NOTS(self->mem, self->frame) + && (self->frame_ts + self->drop_same_frames > now) + && !memcmp(FRAME(data), MEM(data), MEM(used)) ) { - TMP(id) = MEM(id); + self->frame_id = MEM(id); goto drop; } -# undef CMP } Py_BLOCK_THREADS @@ -236,30 +205,11 @@ static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUS default: return NULL; } -# define COPY(_field) TMP(_field) = MEM(_field) - COPY(width); - COPY(height); - COPY(format); - COPY(stride); - COPY(online); - COPY(key); - COPY(grab_ts); - COPY(encode_begin_ts); - COPY(encode_end_ts); - COPY(used); -# undef COPY - - if (TMP(allocated) < MEM(used)) { - size_t size = MEM(used) + (512 * 1024); - A_REALLOC(TMP(data), size); - TMP(allocated) = size; - } - memcpy(TMP(data), MEM(data), MEM(used)); - TMP(used) = MEM(used); - - TMP(id) = MEM(id); - TMP(ts) = get_now_monotonic(); - MEM(last_client_ts) = TMP(ts); + frame_set_data(self->frame, MEM(data), MEM(used)); + FRAME_COPY_META(self->mem, self->frame); + self->frame_id = MEM(id); + self->frame_ts = get_now_monotonic(); + MEM(last_client_ts) = self->frame_ts; if (flock(self->fd, LOCK_UN) < 0) { return PyErr_SetFromErrno(PyExc_OSError); @@ -281,7 +231,7 @@ static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUS } \ Py_DECREF(_tmp); \ } -# define SET_NUMBER(_key, _from, _to) SET_VALUE(#_key, Py##_to##_From##_from(TMP(_key))) +# define SET_NUMBER(_key, _from, _to) SET_VALUE(#_key, Py##_to##_From##_from(FRAME(_key))) SET_NUMBER(width, Long, Long); SET_NUMBER(height, Long, Long); @@ -292,7 +242,7 @@ static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUS SET_NUMBER(grab_ts, Double, Float); SET_NUMBER(encode_begin_ts, Double, Float); SET_NUMBER(encode_end_ts, Double, Float); - SET_VALUE("data", PyBytes_FromStringAndSize((const char *)TMP(data), TMP(used))); + SET_VALUE("data", PyBytes_FromStringAndSize((const char *)FRAME(data), FRAME(used))); # undef SET_NUMBER # undef SET_VALUE @@ -376,5 +326,5 @@ PyMODINIT_FUNC PyInit_ustreamer(void) { // cppcheck-suppress unusedFunction return module; } -#undef TMP +#undef FRAME #undef MEM diff --git a/src/libs/frame.c b/src/libs/frame.c index 32c3f97..3b878a1 100644 --- a/src/libs/frame.c +++ b/src/libs/frame.c @@ -43,8 +43,8 @@ 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->name, frame->allocated, size, size - frame->allocated); + //LOG_DEBUG("Increasing frame buffer '%s': %zu -> %zu (+%zu)", + // frame->name, frame->allocated, size, size - frame->allocated); A_REALLOC(frame->data, size); frame->allocated = size; } @@ -65,44 +65,18 @@ void frame_append_data(frame_s *frame, const uint8_t *data, size_t size) { frame->used = new_used; } -#define COPY(_field) dest->_field = src->_field - void frame_copy(const frame_s *src, frame_s *dest) { assert(dest->managed); frame_set_data(dest, src->data, src->used); - COPY(used); - frame_copy_meta(src, dest); + FRAME_COPY_META(src, dest); } -void frame_copy_meta(const frame_s *src, frame_s *dest) { - // Don't copy the name - COPY(width); - COPY(height); - COPY(format); - COPY(stride); - COPY(online); - COPY(key); - COPY(grab_ts); - COPY(encode_begin_ts); - COPY(encode_end_ts); -} - -#undef COPY - bool frame_compare(const frame_s *a, const frame_s *b) { -# define CMP(_field) (a->_field == b->_field) return ( a->allocated && b->allocated - && CMP(used) - && CMP(width) - && CMP(height) - && CMP(format) - && CMP(stride) - && CMP(online) - && CMP(key) + && FRAME_COMPARE_META_USED_NOTS(a, b) && !memcmp(a->data, b->data, b->used) ); -# undef CMP } unsigned frame_get_padding(const frame_s *frame) { diff --git a/src/libs/frame.h b/src/libs/frame.h index 2064546..e46b199 100644 --- a/src/libs/frame.h +++ b/src/libs/frame.h @@ -32,7 +32,7 @@ #include #include "tools.h" -#include "logging.h" +//#include "logging.h" typedef struct { @@ -61,6 +61,29 @@ typedef struct { } frame_s; +#define FRAME_COPY_META(_src, _dest) { \ + _dest->width = _src->width; \ + _dest->height = _src->height; \ + _dest->format = _src->format; \ + _dest->stride = _src->stride; \ + _dest->online = _src->online; \ + _dest->key = _src->key; \ + _dest->grab_ts = _src->grab_ts; \ + _dest->encode_begin_ts = _src->encode_begin_ts; \ + _dest->encode_end_ts = _src->encode_end_ts; \ + } + +#define FRAME_COMPARE_META_USED_NOTS(_a, _b) ( \ + _a->used == _b->used \ + && _a->width == _b->width \ + && _a->height == _b->height \ + && _a->format == _b->format \ + && _a->stride == _b->stride \ + && _a->online == _b->online \ + && _a->key == _b->key \ + ) + + frame_s *frame_init(const char *name); void frame_destroy(frame_s *frame); @@ -69,7 +92,6 @@ void frame_set_data(frame_s *frame, const uint8_t *data, size_t size); void frame_append_data(frame_s *frame, const uint8_t *data, size_t size); void frame_copy(const frame_s *src, frame_s *dest); -void frame_copy_meta(const frame_s *src, frame_s *dest); bool frame_compare(const frame_s *a, const frame_s *b); unsigned frame_get_padding(const frame_s *frame); diff --git a/src/libs/memsink.c b/src/libs/memsink.c index bfea9b3..bddf2a0 100644 --- a/src/libs/memsink.c +++ b/src/libs/memsink.c @@ -93,7 +93,7 @@ void memsink_destroy(memsink_s *sink) { } bool memsink_server_check(memsink_s *sink, const frame_s *frame) { - // Возвращает true, если если клиенты ИЛИ изменились метаданные + // Возвращает true, если есть клиенты ИЛИ изменились метаданные assert(sink->server); @@ -108,9 +108,7 @@ bool memsink_server_check(memsink_s *sink, const frame_s *frame) { sink->has_clients = (sink->mem->last_client_ts + sink->client_ttl > get_now_monotonic()); -# define NEQ(_field) (sink->mem->_field != frame->_field) - bool retval = (sink->has_clients || NEQ(width) || NEQ(height) || NEQ(format) || NEQ(stride) || NEQ(online) || NEQ(key)); -# undef NEQ + bool retval = (sink->has_clients || !FRAME_COMPARE_META_USED_NOTS(sink->mem, frame)); if (flock(sink->fd, LOCK_UN) < 0) { LOG_PERROR("%s-sink: Can't unlock memory", sink->name); @@ -133,24 +131,16 @@ int memsink_server_put(memsink_s *sink, const frame_s *frame) { if (flock_timedwait_monotonic(sink->fd, 1) == 0) { LOG_VERBOSE("%s-sink: >>>>> Exposing new frame ...", sink->name); -# define COPY(_field) sink->mem->_field = frame->_field sink->last_id = get_now_id(); sink->mem->id = sink->last_id; - COPY(used); - COPY(width); - COPY(height); - COPY(format); - COPY(stride); - COPY(online); - COPY(key); - COPY(grab_ts); - COPY(encode_begin_ts); - COPY(encode_end_ts); - sink->has_clients = (sink->mem->last_client_ts + sink->client_ttl > get_now_monotonic()); + memcpy(sink->mem->data, frame->data, frame->used); + sink->mem->used = frame->used; + FRAME_COPY_META(frame, sink->mem); + sink->mem->magic = MEMSINK_MAGIC; sink->mem->version = MEMSINK_VERSION; -# undef COPY + sink->has_clients = (sink->mem->last_client_ts + sink->client_ttl > get_now_monotonic()); if (flock(sink->fd, LOCK_UN) < 0) { LOG_PERROR("%s-sink: Can't unlock memory", sink->name); @@ -189,19 +179,9 @@ int memsink_client_get(memsink_s *sink, frame_s *frame) { // cppcheck-suppress u goto done; } if (sink->mem->id != sink->last_id) { // When updated -# define COPY(_field) frame->_field = sink->mem->_field sink->last_id = sink->mem->id; - COPY(width); - COPY(height); - COPY(format); - COPY(stride); - COPY(online); - COPY(key); - COPY(grab_ts); - COPY(encode_begin_ts); - COPY(encode_end_ts); frame_set_data(frame, sink->mem->data, sink->mem->used); -# undef COPY + FRAME_COPY_META(sink->mem, frame); retval = 0; } sink->mem->last_client_ts = get_now_monotonic(); diff --git a/src/libs/unjpeg.c b/src/libs/unjpeg.c index d6b4691..1f07be8 100644 --- a/src/libs/unjpeg.c +++ b/src/libs/unjpeg.c @@ -57,7 +57,7 @@ int unjpeg(const frame_s *src, frame_s *dest, bool decode) { jpeg_start_decompress(&jpeg); - frame_copy_meta(src, dest); + FRAME_COPY_META(src, dest); dest->format = V4L2_PIX_FMT_RGB24; dest->width = jpeg.output_width; dest->height = jpeg.output_height; diff --git a/src/ustreamer/encoder.c b/src/ustreamer/encoder.c index db90cd6..b8d0fad 100644 --- a/src/ustreamer/encoder.c +++ b/src/ustreamer/encoder.c @@ -244,7 +244,7 @@ static bool _worker_run_job(worker_s *wr) { assert(ER(type) != ENCODER_TYPE_UNKNOWN); assert(src->used > 0); - frame_copy_meta(src, dest); + FRAME_COPY_META(src, dest); dest->format = V4L2_PIX_FMT_JPEG; dest->stride = 0; dest->encode_begin_ts = get_now_monotonic(); diff --git a/src/ustreamer/h264/encoder.c b/src/ustreamer/h264/encoder.c index a49bc07..1fe5ddb 100644 --- a/src/ustreamer/h264/encoder.c +++ b/src/ustreamer/h264/encoder.c @@ -267,7 +267,7 @@ int h264_encoder_compress(h264_encoder_s *enc, const frame_s *src, int src_vcsm_ assert(enc->format == src->format); assert(enc->stride == src->stride); - frame_copy_meta(src, dest); + FRAME_COPY_META(src, dest); dest->encode_begin_ts = get_now_monotonic(); dest->format = V4L2_PIX_FMT_H264; dest->stride = 0;