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.
This commit is contained in:
Pavel Machek
2024-05-01 22:47:40 +02:00
parent df7e7e9eed
commit f0d8834b4a
4 changed files with 102 additions and 14 deletions

View File

@@ -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,