diff --git a/src/libs/fpsi.c b/src/libs/fpsi.c index 21ce8813..c5300b65 100644 --- a/src/libs/fpsi.c +++ b/src/libs/fpsi.c @@ -48,8 +48,14 @@ void us_fpsi_destroy(us_fpsi_s *fpsi) { free(fpsi); } -void us_fpsi_bump(us_fpsi_s *fpsi, const us_frame_s *frame, bool noop_accum) { - if (frame != NULL) { +void us_fpsi_frame_to_meta(const us_frame_s *frame, us_fpsi_meta_s *meta) { + meta->width = frame->width; + meta->height = frame->height; + meta->online = frame->online; +} + +void us_fpsi_bump(us_fpsi_s *fpsi, const us_fpsi_meta_s *meta, bool noop_accum) { + if (meta != NULL) { assert(fpsi->with_meta); } else { assert(!fpsi->with_meta); @@ -62,10 +68,10 @@ void us_fpsi_bump(us_fpsi_s *fpsi, const us_frame_s *frame, bool noop_accum) { // Fast mutex-less store method ull state = (ull)fpsi->accum & 0xFFFF; if (fpsi->with_meta) { - assert(frame != NULL); - state |= (ull)(frame->width & 0xFFFF) << 16; - state |= (ull)(frame->height & 0xFFFF) << 32; - state |= (ull)(frame->online ? 1 : 0) << 48; + assert(meta != NULL); + state |= (ull)(meta->width & 0xFFFF) << 16; + state |= (ull)(meta->height & 0xFFFF) << 32; + state |= (ull)(meta->online ? 1 : 0) << 48; } atomic_store(&fpsi->state, state); // Сначала инфа atomic_store(&fpsi->state_sec_ts, now_sec_ts); // Потом время, это важно diff --git a/src/libs/fpsi.h b/src/libs/fpsi.h index 219a0a73..d8de201e 100644 --- a/src/libs/fpsi.h +++ b/src/libs/fpsi.h @@ -46,5 +46,6 @@ typedef struct { us_fpsi_s *us_fpsi_init(const char *name, bool with_meta); void us_fpsi_destroy(us_fpsi_s *fpsi); -void us_fpsi_bump(us_fpsi_s *fpsi, const us_frame_s *frame, bool noop_accum); +void us_fpsi_frame_to_meta(const us_frame_s *frame, us_fpsi_meta_s *meta); +void us_fpsi_bump(us_fpsi_s *fpsi, const us_fpsi_meta_s *meta, bool noop_accum); uint us_fpsi_get(us_fpsi_s *fpsi, us_fpsi_meta_s *meta); diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index d2157daa..0dd7c855 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -478,21 +478,25 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) # ifdef WITH_V4P if (stream->drm != NULL) { + us_fpsi_meta_s meta; + const uint fps = us_fpsi_get(stream->run->http->drm_fpsi, &meta); _A_EVBUFFER_ADD_PRINTF(buf, " \"drm\": {\"live\": %s, \"fps\": %u},", - us_bool_to_string(atomic_load(&stream->run->http->drm_live)), - us_fpsi_get(stream->run->http->drm_fpsi, NULL) + us_bool_to_string(meta.online), + fps ); } # endif if (stream->h264_sink != NULL) { + us_fpsi_meta_s meta; + const uint fps = us_fpsi_get(stream->run->http->h264_fpsi, &meta); _A_EVBUFFER_ADD_PRINTF(buf, " \"h264\": {\"bitrate\": %u, \"gop\": %u, \"online\": %s, \"fps\": %u},", stream->h264_bitrate, stream->h264_gop, - us_bool_to_string(atomic_load(&stream->run->http->h264_online)), - us_fpsi_get(stream->run->http->h264_fpsi, NULL) + us_bool_to_string(meta.online), + fps ); } diff --git a/src/ustreamer/stream.c b/src/ustreamer/stream.c index 86290ba4..909f42cf 100644 --- a/src/ustreamer/stream.c +++ b/src/ustreamer/stream.c @@ -98,10 +98,8 @@ us_stream_s *us_stream_init(us_capture_s *cap, us_encoder_s *enc) { us_stream_http_s *http; US_CALLOC(http, 1); # ifdef WITH_V4P - atomic_init(&http->drm_live, false); http->drm_fpsi = us_fpsi_init("DRM", false); # endif - atomic_init(&http->h264_online, false); http->h264_fpsi = us_fpsi_init("H264", false); US_RING_INIT_WITH_ITEMS(http->jpeg_ring, 4, us_frame_init); atomic_init(&http->has_clients, false); @@ -125,7 +123,9 @@ us_stream_s *us_stream_init(us_capture_s *cap, us_encoder_s *enc) { stream->run = run; us_blank_draw(run->blank, "< NO SIGNAL >", cap->width, cap->height); - us_fpsi_bump(http->captured_fpsi, run->blank->raw, true); + us_fpsi_meta_s meta = {0}; + us_fpsi_frame_to_meta(run->blank->raw, &meta); + us_fpsi_bump(http->captured_fpsi, &meta, true); return stream; } @@ -200,7 +200,9 @@ void us_stream_loop(us_stream_s *stream) { default: goto close; // Any error } - us_fpsi_bump(run->http->captured_fpsi, &hw->raw, false); + us_fpsi_meta_s meta = {0}; + us_fpsi_frame_to_meta(&hw->raw, &meta); + us_fpsi_bump(run->http->captured_fpsi, &meta, false); # ifdef WITH_GPIO us_gpio_set_stream_online(true); @@ -459,15 +461,16 @@ static void *_drm_thread(void *v_ctx) { if (stream->drm->run->opened == 0) { CHECK(us_drm_expose_dma(stream->drm, hw)); prev_hw = hw; - atomic_store(&stream->run->http->drm_live, true); - us_fpsi_bump(stream->run->http->drm_fpsi, NULL, false); + us_fpsi_meta_s meta = {.online = true}; // Online means live video + us_fpsi_bump(stream->run->http->drm_fpsi, &meta, false); continue; } CHECK(us_drm_expose_stub(stream->drm, stream->drm->run->opened, ctx->stream->cap)); us_capture_hwbuf_decref(hw); - us_fpsi_bump(stream->run->http->drm_fpsi, NULL, false); + us_fpsi_meta_s meta = {.online = false}; + us_fpsi_bump(stream->run->http->drm_fpsi, &meta, false); SLOWDOWN; } @@ -475,9 +478,8 @@ static void *_drm_thread(void *v_ctx) { close: us_drm_close(stream->drm); US_DELETE(prev_hw, us_capture_hwbuf_decref); - - atomic_store(&stream->run->http->drm_live, false); - + us_fpsi_meta_s meta = {.online = false}; + us_fpsi_bump(stream->run->http->drm_fpsi, &meta, true); SLOWDOWN; # undef SLOWDOWN @@ -573,7 +575,10 @@ static int _stream_init_loop(us_stream_s *stream) { height = stream->cap->height; } us_blank_draw(run->blank, "< NO SIGNAL >", width, height); - us_fpsi_bump(run->http->captured_fpsi, run->blank->raw, true); + + us_fpsi_meta_s meta = {0}; + us_fpsi_frame_to_meta(run->blank->raw, &meta); + us_fpsi_bump(run->http->captured_fpsi, &meta, true); _stream_expose_jpeg(stream, run->blank->jpeg); _stream_expose_raw(stream, run->blank->raw); @@ -594,7 +599,8 @@ static void _stream_drm_ensure_no_signal(us_stream_s *stream) { if (stream->drm == NULL) { return; } - atomic_store(&stream->run->http->drm_live, false); + + const us_fpsi_meta_s meta = {.online = false}; if (stream->drm->run->opened <= 0) { us_drm_close(stream->drm); if (us_drm_open(stream->drm, NULL) < 0) { @@ -604,9 +610,12 @@ static void _stream_drm_ensure_no_signal(us_stream_s *stream) { if (us_drm_ensure_no_signal(stream->drm) < 0) { goto close; } - us_fpsi_bump(stream->run->http->drm_fpsi, NULL, false); + + us_fpsi_bump(stream->run->http->drm_fpsi, &meta, false); return; + close: + us_fpsi_bump(stream->run->http->drm_fpsi, &meta, true); us_drm_close(stream->drm); } #endif @@ -639,26 +648,26 @@ static void _stream_encode_expose_h264(us_stream_s *stream, const us_frame_s *fr return; } - bool online = false; + us_fpsi_meta_s meta = {.online = false}; + if (us_is_jpeg(frame->format)) { if (us_unjpeg(frame, run->h264_tmp_src, true) < 0) { goto done; } frame = run->h264_tmp_src; } - if (run->h264_key_requested) { US_LOG_INFO("H264: Requested keyframe by a sink client"); run->h264_key_requested = false; force_key = true; } if (!us_m2m_encoder_compress(run->h264_enc, frame, run->h264_dest, force_key)) { - online = !us_memsink_server_put(stream->h264_sink, run->h264_dest, &run->h264_key_requested); + meta.online = !us_memsink_server_put(stream->h264_sink, run->h264_dest, &run->h264_key_requested); } us_fpsi_bump(run->http->h264_fpsi, NULL, false); done: - atomic_store(&run->http->h264_online, online); + us_fpsi_bump(run->http->h264_fpsi, &meta, !meta.online); } static void _stream_check_suicide(us_stream_s *stream) {