From f0d8834b4a356fffaf0a2d44c9c6e12984cdabb2 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 1 May 2024 22:47:40 +0200 Subject: [PATCH] Pipe for scripts<->application communication, write UYVY files Got pipe to work between movie subprocess and main code. We use it to display progress from the scripts. Write "gstreamer raw" files, that can be worked with easily from gstreamer. --- movie.sh.in | 7 ++- src/main.c | 6 +++ src/main.h | 4 +- src/process_pipeline.c | 99 +++++++++++++++++++++++++++++++++++++----- 4 files changed, 102 insertions(+), 14 deletions(-) diff --git a/movie.sh.in b/movie.sh.in index 43d5ba8..2382fb2 100755 --- a/movie.sh.in +++ b/movie.sh.in @@ -22,8 +22,8 @@ jpegize() { done for DNG in *.dng; do - PERC=$[(100*$I)/$NUM] - echo $PERC + PERC=$[(50*$I)/$NUM] + echo Message: ${PERC}% BASE=${DNG%%.dng} # -w Use camera white balance # +M use embedded color matrix @@ -67,10 +67,13 @@ elif [ "-$1" == "-stop" ]; then mkdir $GIGA_DIR/sm kill `cat $2/audio.pid` jpegize $2 # | zenity --progress "--text=Converting, phase 1, dng -> jpeg" --time-remaining + echo Message: Mp cd $GIGA_DIR/sm @LIBEXECDIR@/mpegize.py convertall $GIGA_DIR/ $FPS + echo Message: Cl mv $GIGA_DIR/smo/*.mp4 $DEST_NAME rm -r $GIGA_DIR + echo Message: Ok else echo "Unrecognized command" fi diff --git a/src/main.c b/src/main.c index 400a952..a5ab0b5 100644 --- a/src/main.c +++ b/src/main.c @@ -914,6 +914,12 @@ notify_movie_progress(void) gtk_button_set_label(GTK_BUTTON(movie), "Rec"); } +void +notify_movie_message(gchar *msg) +{ + gtk_button_set_label(GTK_BUTTON(movie), msg); +} + void on_movie_clicked(GtkWidget *widget, gpointer user_data) { diff --git a/src/main.h b/src/main.h index b21ad56..c0ea8ee 100644 --- a/src/main.h +++ b/src/main.h @@ -34,4 +34,6 @@ void mp_main_set_zbar_result(MPZBarScanResult *result); int remap(int value, int input_min, int input_max, int output_min, int output_max); -bool check_window_active(); \ No newline at end of file +bool check_window_active(); + +void notify_movie_message(gchar *msg); diff --git a/src/process_pipeline.c b/src/process_pipeline.c index 50e84f4..3f5a314 100644 --- a/src/process_pipeline.c +++ b/src/process_pipeline.c @@ -638,18 +638,56 @@ format_movie_name(char *capture_fname) int movie_recording; static char movie_fname[255]; +static char stdout_buf[1024]; -static void -on_movie_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb) -{ - notify_movie_progress(); +static void on_read_complete(GObject *source_object, GAsyncResult *res, gpointer user_data) { + GInputStream *stream = G_INPUT_STREAM(source_object); + GError *error = NULL; + gssize bytes_read; + + // Read the output from the stream + bytes_read = g_input_stream_read_finish(stream, res, &error); + + if (bytes_read == 0) { + // End of file reached, close the stream + g_input_stream_close(stream, NULL, NULL); + g_object_unref(stream); + notify_movie_progress(); + return; + } + if (bytes_read < 0) { + // Error occurred + g_print("Error reading subprocess output: %s\n", error->message); + g_error_free(error); + g_object_unref(stream); + return; + } + + //g_print("Got buffer: %.*s", (int)bytes_read, stdout_buf); + stdout_buf[bytes_read] = 0; + + { + char msg[] = "Message: "; + int l = sizeof(msg); + if (!strncmp(stdout_buf, msg, l-1)) { + char *c = strchr(stdout_buf, '\n'); + if (!c) + return; + *c = 0; + notify_movie_message(strdup(stdout_buf + l - 1)); + } + } + + // Continue reading asynchronously + g_input_stream_read_async(stream, stdout_buf, sizeof(stdout_buf), G_PRIORITY_DEFAULT, NULL, + on_read_complete, NULL); } static void spawn_movie(char *cmd) { g_autoptr(GError) error = NULL; - GSubprocess *proc = g_subprocess_new(0, + GSubprocess *proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE, &error, movie_script, cmd, @@ -664,8 +702,14 @@ spawn_movie(char *cmd) return; } - g_subprocess_communicate_utf8_async( - proc, NULL, NULL, (GAsyncReadyCallback)on_movie_finished, NULL); + + GInputStream *stdout_stream; + // Get the stdout stream of the subprocess + stdout_stream = g_subprocess_get_stdout_pipe(proc); + + // Read the output of the subprocess asynchronously + g_input_stream_read_async(stdout_stream, stdout_buf, sizeof(stdout_buf), G_PRIORITY_DEFAULT, NULL, + on_read_complete, NULL); } @@ -687,6 +731,28 @@ on_movie_stop(void) spawn_movie("stop"); } +static void +save_grw(const uint8_t *image, char *fname) +{ + FILE *outfile; + if ((outfile = fopen(fname, "wb")) == NULL) { + g_printerr("grw open %s: error %d, %s\n", + fname, + errno, + strerror(errno)); + return; + } + int width = state_proc.mode->width; + int height = state_proc.mode->height; + int size = width*height*2; + fwrite(image, size, 1, outfile); + char buf[1024]; + buf[0] = 0; + int header = sprintf(buf+1, "Caps: video/x-raw,format=YUY2,width=%d,height=%d\nSize: %d\nGRW", width, height, size); + fwrite(buf, header+1, 1, outfile); + fclose(outfile); +} + static void save_jpeg(const uint8_t *image, char *fname) { @@ -707,9 +773,8 @@ save_jpeg(const uint8_t *image, char *fname) jpeg_create_compress(&cinfo); jpeg_stdio_dest(&cinfo, outfile); - //printf("Saving jpeg, %d x %d\n", cinfo.image_width, cinfo.image_height); cinfo.image_width = state_proc.mode->width & -1; - cinfo.image_height = state_proc.mode->height & -1; // FIXME? + cinfo.image_height = state_proc.mode->height & -1; cinfo.input_components = 3; cinfo.in_color_space = JCS_YCbCr; jpeg_set_defaults(&cinfo); @@ -1005,8 +1070,20 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer) if (movie_recording) { char name[1024]; - get_name(name, burst_dir, "dng"); - save_dng(image, name, 1); + + switch (state_proc.mode->v4l_pixfmt) { + case V4L2_PIX_FMT_UYVY: + case V4L2_PIX_FMT_YUYV: + case V4L2_PIX_FMT_YVYU: + case V4L2_PIX_FMT_VYUY: + get_name(name, burst_dir, "grw"); + save_grw(image, name); + break; + default: + get_name(name, burst_dir, "dng"); + save_dng(image, name, 1); + break; + } } MPZBarImage *zbar_image = mp_zbar_image_new(image,