diff --git a/src/common/frame.c b/src/common/frame.c index 740beff..88a33fe 100644 --- a/src/common/frame.c +++ b/src/common/frame.c @@ -82,6 +82,7 @@ void frame_copy_meta(const frame_s *src, frame_s *dest) { COPY(width); COPY(height); COPY(format); + COPY(online); COPY(grab_ts); COPY(encode_begin_ts); COPY(encode_end_ts); @@ -96,3 +97,20 @@ bool frame_compare(const frame_s *a, const frame_s *b) { && !memcmp(a->data, b->data, b->used) ); } + +const char *fourcc_to_string(unsigned format, char *buf, size_t size) { + assert(size >= 8); + buf[0] = format & 0x7F; + buf[1] = (format >> 8) & 0x7F; + buf[2] = (format >> 16) & 0x7F; + buf[3] = (format >> 24) & 0x7F; + if (format & ((unsigned)1 << 31)) { + buf[4] = '-'; + buf[5] = 'B'; + buf[6] = 'E'; + buf[7] = '\0'; + } else { + buf[4] = '\0'; + } + return buf; +} diff --git a/src/common/frame.h b/src/common/frame.h index 509233d..43a7544 100644 --- a/src/common/frame.h +++ b/src/common/frame.h @@ -42,6 +42,7 @@ typedef struct { unsigned width; unsigned height; unsigned format; + bool online; long double grab_ts; long double encode_begin_ts; @@ -61,3 +62,5 @@ 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); + +const char *fourcc_to_string(unsigned format, char *buf, size_t size); diff --git a/src/rawsink/rawsink.c b/src/rawsink/rawsink.c index 590647f..b1e4287 100644 --- a/src/rawsink/rawsink.c +++ b/src/rawsink/rawsink.c @@ -27,7 +27,7 @@ static int _sem_timedwait_monotonic(sem_t *sem, long double timeout); static int _flock_timedwait_monotonic(int fd, long double timeout); -rawsink_s *rawsink_init(const char *name, bool server, mode_t mode, bool rm, unsigned timeout) { +rawsink_s *rawsink_open(const char *name, bool server, mode_t mode, bool rm, unsigned timeout) { rawsink_s *rawsink; int flags = (server ? O_RDWR | O_CREAT : O_RDWR); @@ -91,11 +91,11 @@ rawsink_s *rawsink_init(const char *name, bool server, mode_t mode, bool rm, uns return rawsink; error: - rawsink_destroy(rawsink); + rawsink_close(rawsink); return NULL; } -void rawsink_destroy(rawsink_s *rawsink) { +void rawsink_close(rawsink_s *rawsink) { if (rawsink->sig_sem != SEM_FAILED) { if (sem_close(rawsink->sig_sem) < 0) { LOG_PERROR("Can't close RAW sink signal semaphore"); @@ -149,9 +149,10 @@ int rawsink_server_put(rawsink_s *rawsink, frame_s *frame) { # define COPY(_field) rawsink->mem->_field = frame->_field COPY(used); - COPY(format); COPY(width); COPY(height); + COPY(format); + COPY(online); COPY(grab_ts); memcpy(rawsink->mem->data, frame->data, frame->used); # undef COPY @@ -198,6 +199,7 @@ int rawsink_client_get(rawsink_s *rawsink, frame_s *frame) { // cppcheck-suppres COPY(width); COPY(height); COPY(format); + COPY(online); COPY(grab_ts); frame_set_data(frame, rawsink->mem->data, rawsink->mem->used); # undef COPY diff --git a/src/rawsink/rawsink.h b/src/rawsink/rawsink.h index 446412f..114e11c 100644 --- a/src/rawsink/rawsink.h +++ b/src/rawsink/rawsink.h @@ -51,6 +51,7 @@ typedef struct { unsigned width; unsigned height; unsigned format; + bool online; long double grab_ts; uint8_t data[RAWSINK_MAX_DATA]; } rawsink_shared_s; @@ -69,8 +70,8 @@ typedef struct { } rawsink_s; -rawsink_s *rawsink_init(const char *name, bool server, mode_t mode, bool rm, unsigned timeout); -void rawsink_destroy(rawsink_s *rawsink); +rawsink_s *rawsink_open(const char *name, bool server, mode_t mode, bool rm, unsigned timeout); +void rawsink_close(rawsink_s *rawsink); int rawsink_server_put(rawsink_s *rawsink, frame_s *frame); int rawsink_client_get(rawsink_s *rawsink, frame_s *frame); diff --git a/src/ustreamer/device.c b/src/ustreamer/device.c index ceaaa25..2887bd1 100644 --- a/src/ustreamer/device.c +++ b/src/ustreamer/device.c @@ -73,7 +73,6 @@ static void _device_set_control( device_s *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, int value, bool quiet); -static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format); static const char *_format_to_string_nullable(unsigned format); static const char *_format_to_string_supported(unsigned format); static const char *_standard_to_string(v4l2_std_id standard); @@ -325,6 +324,7 @@ int device_grab_buffer(device_s *dev) { HW(raw.width) = RUN(width); HW(raw.height) = RUN(height); HW(raw.format) = RUN(format); + HW(raw.online) = true; memcpy(&HW(buf_info), &buf_info, sizeof(struct v4l2_buffer)); HW(raw.grab_ts) = get_now_monotonic(); @@ -505,7 +505,7 @@ static int _device_open_format(device_s *dev) { LOG_INFO("Falling back to pixelformat=%s", format_str_nullable); } else { LOG_ERROR("Unsupported pixelformat=%s (fourcc)", - _format_to_string_fourcc(format_obtained_str, 8, fmt.fmt.pix.pixelformat)); + fourcc_to_string(fmt.fmt.pix.pixelformat, format_obtained_str, 8)); return -1; } } @@ -818,23 +818,6 @@ static void _device_set_control( } } -static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format) { - assert(size >= 8); - buf[0] = format & 0x7F; - buf[1] = (format >> 8) & 0x7F; - buf[2] = (format >> 16) & 0x7F; - buf[3] = (format >> 24) & 0x7F; - if (format & ((unsigned)1 << 31)) { - buf[4] = '-'; - buf[5] = 'B'; - buf[6] = 'E'; - buf[7] = '\0'; - } else { - buf[4] = '\0'; - } - return buf; -} - static const char *_format_to_string_nullable(unsigned format) { for (unsigned index = 0; index < ARRAY_LEN(_FORMATS); ++index) { if (format == _FORMATS[index].format) { diff --git a/src/ustreamer/encoder.c b/src/ustreamer/encoder.c index a42e58b..ddfa1a8 100644 --- a/src/ustreamer/encoder.c +++ b/src/ustreamer/encoder.c @@ -213,8 +213,10 @@ int encoder_compress(encoder_s *encoder, unsigned worker_number, frame_s *src, f assert(ER(type) != ENCODER_TYPE_UNKNOWN); assert(src->used > 0); - dest->grab_ts = src->grab_ts; + frame_copy_meta(src, dest); + dest->format = V4L2_PIX_FMT_JPEG; dest->encode_begin_ts = get_now_monotonic(); + dest->used = 0; if (ER(type) == ENCODER_TYPE_CPU) { LOG_VERBOSE("Compressing buffer using CPU"); @@ -239,11 +241,6 @@ int encoder_compress(encoder_s *encoder, unsigned worker_number, frame_s *src, f # endif dest->encode_end_ts = get_now_monotonic(); - - dest->width = src->width; - dest->height = src->height; - dest->format = V4L2_PIX_FMT_JPEG; - return 0; # pragma GCC diagnostic ignored "-Wunused-label" diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index 54910d7..58d9f6a 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -352,7 +352,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) encoder_quality, (server->fake_width ? server->fake_width : EX(frame->width)), (server->fake_height ? server->fake_height : EX(frame->height)), - bool_to_string(EX(online)), + bool_to_string(EX(frame->online)), STREAM(dev->desired_fps), EX(captured_fps), EX(queued_fps), @@ -407,7 +407,7 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv ADD_TIME_HEADER("X-Timestamp", get_now_real()); - ADD_HEADER("X-UStreamer-Online", bool_to_string(EX(online))); + ADD_HEADER("X-UStreamer-Online", bool_to_string(EX(frame->online))); ADD_UNSIGNED_HEADER("X-UStreamer-Dropped", EX(dropped)); ADD_UNSIGNED_HEADER("X-UStreamer-Width", EX(frame->width)); ADD_UNSIGNED_HEADER("X-UStreamer-Height", EX(frame->height)); @@ -603,7 +603,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c "X-UStreamer-Expose-End-Time: %.06Lf" RN "X-UStreamer-Send-Time: %.06Lf" RN RN, - bool_to_string(EX(online)), + bool_to_string(EX(frame->online)), EX(dropped), EX(frame->width), EX(frame->height), @@ -761,12 +761,12 @@ static void _http_exposed_refresh(UNUSED int fd, UNUSED short what, void *v_serv frame_updated && server->notify_parent && ( - EX(notify_last_online) != EX(online) + EX(notify_last_online) != EX(frame->online) || EX(notify_last_width) != EX(frame->width) || EX(notify_last_height) != EX(frame->height) ) ) { - EX(notify_last_online) = EX(online); + EX(notify_last_online) = EX(frame->online); EX(notify_last_width) = EX(frame->width); EX(notify_last_height) = EX(frame->height); process_notify_parent(); @@ -778,12 +778,12 @@ static bool _expose_new_frame(server_s *server) { A_MUTEX_LOCK(&STREAM(video->mutex)); - LOG_DEBUG("HTTP: Updating exposed frame (online=%d) ...", STREAM(video->online)); + LOG_DEBUG("HTTP: Updating exposed frame (online=%d) ...", STREAM(video->frame->online)); EX(captured_fps) = STREAM(video->captured_fps); EX(expose_begin_ts) = get_now_monotonic(); - if (server->drop_same_frames && STREAM(video->online)) { + if (server->drop_same_frames && STREAM(video->frame->online)) { bool need_drop = false; bool maybe_same = false; if ( @@ -805,13 +805,12 @@ static bool _expose_new_frame(server_s *server) { frame_copy(STREAM(video->frame), EX(frame)); - EX(online) = STREAM(video->online); EX(dropped) = 0; EX(expose_cmp_ts) = EX(expose_begin_ts); EX(expose_end_ts) = get_now_monotonic(); LOG_VERBOSE("HTTP: Exposed frame: online=%d, exp_time=%.06Lf", - EX(online), EX(expose_end_ts) - EX(expose_begin_ts)); + EX(frame->online), EX(expose_end_ts) - EX(expose_begin_ts)); updated = true; not_updated: diff --git a/src/ustreamer/http/server.h b/src/ustreamer/http/server.h index f2b3ec5..d73864c 100644 --- a/src/ustreamer/http/server.h +++ b/src/ustreamer/http/server.h @@ -97,7 +97,6 @@ typedef struct { frame_s *frame; unsigned captured_fps; unsigned queued_fps; - bool online; unsigned dropped; long double expose_begin_ts; long double expose_cmp_ts; diff --git a/src/ustreamer/options.c b/src/ustreamer/options.c index 50e9dc9..9fdc520 100644 --- a/src/ustreamer/options.c +++ b/src/ustreamer/options.c @@ -232,7 +232,7 @@ options_s *options_init(int argc, char *argv[]) { void options_destroy(options_s *options) { # ifdef WITH_RAWSINK if (options->rawsink) { - rawsink_destroy(options->rawsink); + rawsink_close(options->rawsink); } # endif if (options->blank) { @@ -463,7 +463,7 @@ int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_ # ifdef WITH_RAWSINK if (rawsink_name && rawsink_name[0] != '\0') { - options->rawsink = rawsink_init( + options->rawsink = rawsink_open( rawsink_name, true, rawsink_mode, diff --git a/src/ustreamer/stream.c b/src/ustreamer/stream.c index 45b2719..e54a233 100644 --- a/src/ustreamer/stream.c +++ b/src/ustreamer/stream.c @@ -326,7 +326,7 @@ static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned capt LOG_DEBUG("Exposed ALIVE video frame"); } else { - if (VID(online)) { // Если переходим из online в offline + if (VID(frame->online)) { // Если переходим из online в offline if (stream->last_as_blank < 0) { // Если last_as_blank выключен, просто покажем старую картинку new = stream->blank; LOG_INFO("Changed video frame to BLANK"); @@ -360,7 +360,7 @@ static bool _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned capt frame = NULL; changed = true; } - VID(online) = frame; + VID(frame->online) = frame; VID(captured_fps) = captured_fps; atomic_store(&VID(updated), true); A_MUTEX_UNLOCK(&VID(mutex)); diff --git a/src/ustreamer/stream.h b/src/ustreamer/stream.h index 72f490d..cb3ede1 100644 --- a/src/ustreamer/stream.h +++ b/src/ustreamer/stream.h @@ -55,7 +55,6 @@ typedef struct { typedef struct { frame_s *frame; - bool online; unsigned captured_fps; atomic_bool updated; long double last_as_blank_ts;