Browse Source

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.
Pavel Machek 1 year ago
parent
commit
f0d8834b4a
4 changed files with 102 additions and 14 deletions
  1. 5 2
      movie.sh.in
  2. 6 0
      src/main.c
  3. 3 1
      src/main.h
  4. 88 11
      src/process_pipeline.c

+ 5 - 2
movie.sh.in

@@ -22,8 +22,8 @@ jpegize() {
 	done
 	done
 
 
 	for DNG in *.dng; do
 	for DNG in *.dng; do
-		PERC=$[(100*$I)/$NUM]
-		echo $PERC
+		PERC=$[(50*$I)/$NUM]
+		echo Message: ${PERC}%
 		BASE=${DNG%%.dng}
 		BASE=${DNG%%.dng}
 		# -w		Use camera white balance
 		# -w		Use camera white balance
 		# +M		use embedded color matrix
 		# +M		use embedded color matrix
@@ -67,10 +67,13 @@ elif [ "-$1" == "-stop" ]; then
 	mkdir $GIGA_DIR/sm
 	mkdir $GIGA_DIR/sm
 	kill `cat $2/audio.pid`
 	kill `cat $2/audio.pid`
 	jpegize $2 # | zenity --progress "--text=Converting, phase 1, dng -> jpeg" --time-remaining
 	jpegize $2 # | zenity --progress "--text=Converting, phase 1, dng -> jpeg" --time-remaining
+	echo Message: Mp
 	cd $GIGA_DIR/sm
 	cd $GIGA_DIR/sm
 	@LIBEXECDIR@/mpegize.py convertall $GIGA_DIR/ $FPS
 	@LIBEXECDIR@/mpegize.py convertall $GIGA_DIR/ $FPS
+	echo Message: Cl
 	mv $GIGA_DIR/smo/*.mp4 $DEST_NAME
 	mv $GIGA_DIR/smo/*.mp4 $DEST_NAME
 	rm -r $GIGA_DIR
 	rm -r $GIGA_DIR
+	echo Message: Ok
 else
 else
 	echo "Unrecognized command"
 	echo "Unrecognized command"
 fi
 fi

+ 6 - 0
src/main.c

@@ -914,6 +914,12 @@ notify_movie_progress(void)
 		gtk_button_set_label(GTK_BUTTON(movie), "Rec");
 		gtk_button_set_label(GTK_BUTTON(movie), "Rec");
 }
 }
 
 
+void
+notify_movie_message(gchar *msg)
+{
+	gtk_button_set_label(GTK_BUTTON(movie), msg);
+}
+
 void
 void
 on_movie_clicked(GtkWidget *widget, gpointer user_data)
 on_movie_clicked(GtkWidget *widget, gpointer user_data)
 {
 {

+ 3 - 1
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);
 int remap(int value, int input_min, int input_max, int output_min, int output_max);
 
 
-bool check_window_active();
+bool check_window_active();
+
+void notify_movie_message(gchar *msg);

+ 88 - 11
src/process_pipeline.c

@@ -638,18 +638,56 @@ format_movie_name(char *capture_fname)
 
 
 int movie_recording;
 int movie_recording;
 static char movie_fname[255];
 static char movie_fname[255];
+static char stdout_buf[1024];
+
+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));
+		}
+	}
 
 
-static void
-on_movie_finished(GSubprocess *proc, GAsyncResult *res, GdkTexture *thumb)
-{
-	notify_movie_progress();
+	// Continue reading asynchronously
+	g_input_stream_read_async(stream, stdout_buf, sizeof(stdout_buf), G_PRIORITY_DEFAULT, NULL,
+				  on_read_complete, NULL);
 }
 }
 
 
 static void
 static void
 spawn_movie(char *cmd)
 spawn_movie(char *cmd)
 {
 {
         g_autoptr(GError) error = NULL;
         g_autoptr(GError) error = NULL;
-        GSubprocess *proc = g_subprocess_new(0,
+        GSubprocess *proc = g_subprocess_new(G_SUBPROCESS_FLAGS_STDOUT_PIPE,
                                              &error,
                                              &error,
                                              movie_script,
                                              movie_script,
 					     cmd,
 					     cmd,
@@ -664,8 +702,14 @@ spawn_movie(char *cmd)
                 return;
                 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");
 	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
 static void
 save_jpeg(const uint8_t *image, char *fname)
 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_create_compress(&cinfo);
         jpeg_stdio_dest(&cinfo, outfile);
         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_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.input_components = 3;
         cinfo.in_color_space = JCS_YCbCr;
         cinfo.in_color_space = JCS_YCbCr;
         jpeg_set_defaults(&cinfo);
         jpeg_set_defaults(&cinfo);
@@ -1005,8 +1070,20 @@ process_image(MPPipeline *pipeline, const MPBuffer *buffer)
 
 
 	if (movie_recording) {
 	if (movie_recording) {
 		char name[1024];
 		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,
         MPZBarImage *zbar_image = mp_zbar_image_new(image,