Skip to content

Commit aa0fe18

Browse files
committed
Merge branch 'dev' into feat/audio-support
Integrate latest dev branch changes including: - HID RPC handshake improvements - Video sleep mode functionality - IPv6 address sorting fixes - OTA update flow improvements - Video stream lifecycle management All audio functionality preserved and tested.
2 parents cc7e608 + d0f1b75 commit aa0fe18

File tree

20 files changed

+428
-98
lines changed

20 files changed

+428
-98
lines changed

internal/native/cgo/ctrl.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const char *jetkvm_ui_event_code_to_name(int code) {
5959

6060
void video_report_format(bool ready, const char *error, u_int16_t width, u_int16_t height, double frame_per_second)
6161
{
62+
state.streaming = video_get_streaming_status();
6263
state.ready = ready;
6364
state.error = error;
6465
state.width = width;
@@ -69,6 +70,13 @@ void video_report_format(bool ready, const char *error, u_int16_t width, u_int16
6970
}
7071
}
7172

73+
void video_send_format_report() {
74+
state.streaming = video_get_streaming_status();
75+
if (video_state_handler != NULL) {
76+
(*video_state_handler)(&state);
77+
}
78+
}
79+
7280
int video_send_frame(const uint8_t *frame, ssize_t len)
7381
{
7482
if (video_handler != NULL) {
@@ -367,6 +375,10 @@ void jetkvm_video_stop() {
367375
video_stop_streaming();
368376
}
369377

378+
uint8_t jetkvm_video_get_streaming_status() {
379+
return video_get_streaming_status();
380+
}
381+
370382
int jetkvm_video_set_quality_factor(float quality_factor) {
371383
if (quality_factor <= 0 || quality_factor > 1) {
372384
return -1;

internal/native/cgo/ctrl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
typedef struct
99
{
1010
bool ready;
11+
uint8_t streaming;
1112
const char *error;
1213
u_int16_t width;
1314
u_int16_t height;
@@ -56,6 +57,7 @@ int jetkvm_video_init(float quality_factor);
5657
void jetkvm_video_shutdown();
5758
void jetkvm_video_start();
5859
void jetkvm_video_stop();
60+
uint8_t jetkvm_video_get_streaming_status();
5961
int jetkvm_video_set_quality_factor(float quality_factor);
6062
float jetkvm_video_get_quality_factor();
6163
int jetkvm_video_set_edid(const char *edid_hex);
@@ -64,6 +66,7 @@ char *jetkvm_video_log_status();
6466
jetkvm_video_state_t *jetkvm_video_get_status();
6567

6668
void video_report_format(bool ready, const char *error, u_int16_t width, u_int16_t height, double frame_per_second);
69+
void video_send_format_report();
6770
int video_send_frame(const uint8_t *frame, ssize_t len);
6871

6972

internal/native/cgo/video.c

Lines changed: 66 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@ static void *venc_read_stream(void *arg)
349349
}
350350

351351
uint32_t detected_width, detected_height;
352-
bool detected_signal = false, streaming_flag = false, streaming_stopped = true;
352+
bool detected_signal = false, streaming_flag = false;
353+
354+
bool streaming_stopped = true;
355+
pthread_mutex_t streaming_stopped_mutex = PTHREAD_MUTEX_INITIALIZER;
353356

354357
pthread_t *streaming_thread = NULL;
355358
pthread_mutex_t streaming_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -370,8 +373,27 @@ void set_streaming_flag(bool flag)
370373
pthread_mutex_lock(&streaming_mutex);
371374
streaming_flag = flag;
372375
pthread_mutex_unlock(&streaming_mutex);
376+
377+
video_send_format_report();
378+
}
379+
380+
void set_streaming_stopped(bool stopped)
381+
{
382+
pthread_mutex_lock(&streaming_stopped_mutex);
383+
streaming_stopped = stopped;
384+
pthread_mutex_unlock(&streaming_stopped_mutex);
385+
386+
video_send_format_report();
373387
}
374388

389+
bool get_streaming_stopped()
390+
{
391+
pthread_mutex_lock(&streaming_stopped_mutex);
392+
bool stopped = streaming_stopped;
393+
pthread_mutex_unlock(&streaming_stopped_mutex);
394+
return stopped;
395+
}
396+
375397
void write_buffer_to_file(const uint8_t *buffer, size_t length, const char *filename)
376398
{
377399
FILE *file = fopen(filename, "wb");
@@ -385,8 +407,7 @@ void *run_video_stream(void *arg)
385407

386408
log_info("running video stream");
387409

388-
streaming_stopped = false;
389-
410+
set_streaming_stopped(false);
390411
while (streaming_flag)
391412
{
392413
if (detected_signal == false)
@@ -528,6 +549,8 @@ void *run_video_stream(void *arg)
528549
uint32_t num = 0;
529550
VIDEO_FRAME_INFO_S stFrame;
530551

552+
553+
531554
while (streaming_flag)
532555
{
533556
FD_ZERO(&fds);
@@ -539,6 +562,7 @@ void *run_video_stream(void *arg)
539562
if (r == 0)
540563
{
541564
log_info("select timeout");
565+
ensure_sleep_mode_disabled();
542566
break;
543567
}
544568
if (r == -1)
@@ -634,7 +658,7 @@ void *run_video_stream(void *arg)
634658

635659
log_info("video stream thread exiting");
636660

637-
streaming_stopped = true;
661+
set_streaming_stopped(true);
638662

639663
return NULL;
640664
}
@@ -670,9 +694,10 @@ void video_start_streaming()
670694
log_info("starting video streaming");
671695
if (streaming_thread != NULL)
672696
{
673-
if (streaming_stopped == true) {
697+
bool stopped = get_streaming_stopped();
698+
if (stopped == true) {
674699
log_error("video streaming already stopped but streaming_thread is not NULL");
675-
assert(streaming_stopped == true);
700+
assert(stopped == true);
676701
}
677702
log_warn("video streaming already started");
678703
return;
@@ -699,6 +724,21 @@ void video_start_streaming()
699724
streaming_thread = new_thread;
700725
}
701726

727+
bool wait_for_streaming_stopped()
728+
{
729+
int attempts = 0;
730+
while (attempts < 30) {
731+
if (get_streaming_stopped() == true) {
732+
log_info("video streaming stopped after %d attempts", attempts);
733+
return true;
734+
}
735+
usleep(100000); // 100ms
736+
attempts++;
737+
}
738+
log_error("video streaming did not stop after 3s");
739+
return false;
740+
}
741+
702742
void video_stop_streaming()
703743
{
704744
if (streaming_thread == NULL) {
@@ -710,14 +750,7 @@ void video_stop_streaming()
710750
set_streaming_flag(false);
711751

712752
log_info("waiting for video streaming thread to exit");
713-
int attempts = 0;
714-
while (!streaming_stopped && attempts < 30) {
715-
usleep(100000); // 100ms
716-
attempts++;
717-
}
718-
if (!streaming_stopped) {
719-
log_error("video streaming thread did not exit after 30s");
720-
}
753+
wait_for_streaming_stopped();
721754

722755
pthread_join(*streaming_thread, NULL);
723756
free(streaming_thread);
@@ -726,13 +759,30 @@ void video_stop_streaming()
726759
log_info("video streaming stopped");
727760
}
728761

762+
uint8_t video_get_streaming_status() {
763+
// streaming flag can be false when stopping streaming
764+
if (get_streaming_flag() == true) return 1;
765+
if (get_streaming_stopped() == false) return 2;
766+
return 0;
767+
}
768+
729769
void video_restart_streaming()
730770
{
731-
if (get_streaming_flag() == true)
771+
uint8_t streaming_status = video_get_streaming_status();
772+
if (streaming_status == 0)
732773
{
733-
log_info("restarting video streaming");
774+
log_info("will not restart video streaming because it's stopped");
775+
return;
776+
}
777+
778+
if (streaming_status == 2) {
734779
video_stop_streaming();
735780
}
781+
782+
if (!wait_for_streaming_stopped()) {
783+
return;
784+
}
785+
736786
video_start_streaming();
737787
}
738788

internal/native/cgo/video.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@ void video_start_streaming();
3131
*/
3232
void video_stop_streaming();
3333

34+
/**
35+
* @brief Get the streaming status of the video
36+
*
37+
* @return uint8_t 1 if the video streaming is active, 2 if the video streaming is stopping, 0 otherwise
38+
*/
39+
uint8_t video_get_streaming_status();
40+
3441
/**
3542
* @brief Set the quality factor of the video
3643
*

internal/native/cgo_linux.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ var (
5757
func jetkvm_go_video_state_handler(state *C.jetkvm_video_state_t) {
5858
videoState := VideoState{
5959
Ready: bool(state.ready),
60+
Streaming: VideoStreamingStatus(state.streaming),
6061
Error: C.GoString(state.error),
6162
Width: int(state.width),
6263
Height: int(state.height),
@@ -168,6 +169,15 @@ func videoStop() {
168169
C.jetkvm_video_stop()
169170
}
170171

172+
func videoGetStreamingStatus() VideoStreamingStatus {
173+
cgoLock.Lock()
174+
defer cgoLock.Unlock()
175+
176+
isStreaming := C.jetkvm_video_get_streaming_status()
177+
178+
return VideoStreamingStatus(isStreaming)
179+
}
180+
171181
func videoLogStatus() string {
172182
cgoLock.Lock()
173183
defer cgoLock.Unlock()

internal/native/cgo_notlinux.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ func videoSetEDID(edid string) error {
123123
return nil
124124
}
125125

126+
func videoGetStreamingStatus() VideoStreamingStatus {
127+
panicPlatformNotSupported()
128+
return VideoStreamingStatusInactive
129+
}
130+
126131
func crash() {
127132
panicPlatformNotSupported()
128133
}

internal/native/chan.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ func (n *Native) handleVideoFrameChan() {
2828
func (n *Native) handleVideoStateChan() {
2929
for {
3030
state := <-videoStateChan
31+
3132
n.onVideoStateChange(state)
3233
}
3334
}

internal/native/grpc_servermethods.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,19 +70,13 @@ func (s *grpcServer) VideoLogStatus(ctx context.Context, req *pb.Empty) (*pb.Vid
7070
}
7171

7272
func (s *grpcServer) VideoStop(ctx context.Context, req *pb.Empty) (*pb.Empty, error) {
73-
procPrefix = "jetkvm: [native]"
74-
setProcTitle(lastProcTitle)
75-
7673
if err := s.native.VideoStop(); err != nil {
7774
return nil, status.Error(codes.Internal, err.Error())
7875
}
7976
return &pb.Empty{}, nil
8077
}
8178

8279
func (s *grpcServer) VideoStart(ctx context.Context, req *pb.Empty) (*pb.Empty, error) {
83-
procPrefix = "jetkvm: [native+video]"
84-
setProcTitle(lastProcTitle)
85-
8680
if err := s.native.VideoStart(); err != nil {
8781
return nil, status.Error(codes.Internal, err.Error())
8882
}

internal/native/native.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,26 @@ type NativeOptions struct {
4040
OnNativeRestart func()
4141
}
4242

43+
type VideoStreamingStatus uint8
44+
45+
const (
46+
VideoStreamingStatusActive VideoStreamingStatus = 1
47+
VideoStreamingStatusStopping VideoStreamingStatus = 2 // video is stopping, but not yet stopped
48+
VideoStreamingStatusInactive VideoStreamingStatus = 0
49+
)
50+
51+
func (s VideoStreamingStatus) String() string {
52+
switch s {
53+
case VideoStreamingStatusActive:
54+
return "active"
55+
case VideoStreamingStatusStopping:
56+
return "stopping"
57+
case VideoStreamingStatusInactive:
58+
return "inactive"
59+
}
60+
return "unknown"
61+
}
62+
4363
func NewNative(opts NativeOptions) *Native {
4464
pid := os.Getpid()
4565
nativeSubLogger := nativeLogger.With().Int("pid", pid).Str("scope", "native").Logger()

internal/native/server.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ func monitorCrashSignal(ctx context.Context, logger *zerolog.Logger, nativeInsta
5454
}
5555
}
5656

57+
func updateProcessTitle(state *VideoState) {
58+
if state == nil {
59+
procPrefix = "jetkvm: [native]"
60+
} else {
61+
var status string
62+
if state.Streaming == VideoStreamingStatusInactive {
63+
status = "inactive"
64+
} else if !state.Ready {
65+
status = "not ready"
66+
} else if state.Error != "" {
67+
status = state.Error
68+
} else {
69+
status = fmt.Sprintf("%s,%dx%d,%.1ffps", state.Streaming.String(), state.Width, state.Height, state.FramePerSecond)
70+
}
71+
procPrefix = fmt.Sprintf("jetkvm: [native+video{%s}]", status)
72+
}
73+
setProcTitle(lastProcTitle)
74+
}
75+
5776
// RunNativeProcess runs the native process mode
5877
func RunNativeProcess(binaryName string) {
5978
appCtx, appCtxCancel := context.WithCancel(context.Background())
@@ -82,6 +101,9 @@ func RunNativeProcess(binaryName string) {
82101
logger.Fatal().Err(err).Msg("failed to write frame to video stream socket")
83102
}
84103
}
104+
nativeOptions.OnVideoStateChange = func(state VideoState) {
105+
updateProcessTitle(&state)
106+
}
85107

86108
// Create native instance
87109
nativeInstance := NewNative(*nativeOptions)

0 commit comments

Comments
 (0)