2 * gegl-video <video-file|frame-folder|frames|edl>
4 * --output-frames path/image- --frame-extension png
5 * --output-video path/video.avi
7 * -- gegl:threshold value=0.3
9 * the edl,. should be a list of frames.. and video with frame start->end bits
17 * image folders are folder containing image files to be played in sequence
18 * each image file contains its own embedded PCM data, facilitating easy re-assembly.
23 #include <gegl-audio-fragment.h>
24 #include <glib/gprintf.h>
25 #include <gexiv2/gexiv2.h>
34 char *frame_extension
= ".png";
35 char *frame_path
= NULL
;
36 char *video_path
= NULL
;
37 int output_frame_no
= -1;
38 int show_progress
= 0;
41 gegl_meta_set_audio (const char *path
,
42 GeglAudioFragment
*audio
);
44 gegl_meta_get_audio (const char *path
,
45 GeglAudioFragment
*audio
);
50 printf ("usage: negl [options] <video> [thumb]\n\n"
51 " -p, --progress - display info about current frame/progress in terminal\n"
52 " -s <frame>, --start-frame <frame>\n"
53 " - first frame to extract analysis from (default 0)\n"
54 " -e <frame>, --end-frame <frame>\n"
55 " - last frame to extract analysis from (default is 0 which means auto end)\n"
56 " -of <output_path_prefix>, --output-path <path_prefix>\n"
57 " -fe <.ext> --frame-extension <.ext>\n"
58 " - .png or .jpg are supported file formats, .jpg default\n"
60 "Options can also follow then video (and thumb) arguments.\n"
65 static void parse_args (int argc
, char **argv
)
69 for (i
= 1; i
< argc
; i
++)
71 if (g_str_equal (argv
[i
], "-p") ||
72 g_str_equal (argv
[i
], "--progress"))
76 else if (g_str_equal (argv
[i
], "-s") ||
77 g_str_equal (argv
[i
], "--start-frame"))
79 frame_start
= g_ascii_strtod (argv
[i
+1], NULL
);
82 else if (g_str_equal (argv
[i
], "-c") ||
83 g_str_equal (argv
[i
], "--frame-count"))
85 frame_end
= frame_start
+ g_ascii_strtod (argv
[i
+1], NULL
) - 1;
88 else if (g_str_equal (argv
[i
], "--output-frames") ||
89 g_str_equal (argv
[i
], "-of"))
91 frame_path
= g_strdup (argv
[i
+1]);
94 else if (g_str_equal (argv
[i
], "--output-frame-start") ||
95 g_str_equal (argv
[i
], "-ofs`"))
97 output_frame_no
= g_ascii_strtod (argv
[i
+1], NULL
);
100 else if (g_str_equal (argv
[i
], "--frame-extension") ||
101 g_str_equal (argv
[i
], "-fe"))
103 frame_extension
= g_strdup (argv
[i
+1]);
106 else if (g_str_equal (argv
[i
], "-e") ||
107 g_str_equal (argv
[i
], "--end-frame"))
109 frame_end
= g_ascii_strtod (argv
[i
+1], NULL
);
112 else if (g_str_equal (argv
[i
], "-h") ||
113 g_str_equal (argv
[i
], "--help"))
119 video_path
= g_strdup (argv
[i
]);
125 GeglNode
*gegl_decode
= NULL
;
126 GeglNode
*display
= NULL
;
128 GeglBuffer
*previous_video_frame
= NULL
;
129 GeglBuffer
*video_frame
= NULL
;
131 GeglNode
*store
, *load
;
133 static void decode_frame_no (int frame
)
137 g_object_unref (video_frame
);
140 gegl_node_set (load
, "frame", frame
, NULL
);
141 gegl_node_process (store
);
144 GeglNode
*translate
= NULL
;
153 gegl_init (&argc
, &argv
);
154 parse_args (argc
, argv
);
156 gegl_decode
= gegl_node_new ();
158 store
= gegl_node_new_child (gegl_decode
,
159 "operation", "gegl:buffer-sink",
160 "buffer", &video_frame
, NULL
);
161 load
= gegl_node_new_child (gegl_decode
,
162 "operation", "gegl:ff-load",
166 gegl_node_link_many (load
, store
, NULL
);
172 double frame_rate
= 0;
173 gegl_node_get (load
, "frames", &frames
, NULL
);
174 gegl_node_get (load
, "frame-rate", &frame_rate
, NULL
);
180 if (output_frame_no
== -1)
181 output_frame_no
= frame_start
;
183 printf ("frames: %i - %i\n", frame_start
, frame_end
);
184 printf ("video: %s\n", video_path
);
188 for (frame
= frame_start
; frame
<= frame_end
; frame
++)
192 fprintf (stdout
, "\r%2.1f%% %i/%i (%i)",
193 (frame
-frame_start
) * 100.0 / (frame_end
-frame_start
),
195 frame_end
-frame_start
,
200 decode_frame_no (frame
);
202 GeglAudioFragment
*audio
;
204 gegl_node_get (load
, "audio", &audio
,
205 "frame-rate", &fps
, NULL
);
209 char *path
= g_strdup_printf ("%s%07i%s", frame_path
, output_frame_no
++, frame_extension
);
210 GeglNode
*save_graph
= gegl_node_new ();
211 GeglNode
*readbuf
, *save
;
213 readbuf
= gegl_node_new_child (save_graph
, "operation", "gegl:buffer-source", "buffer", video_frame
, NULL
);
214 save
= gegl_node_new_child (save_graph
, "operation", "gegl:save",
216 gegl_node_link_many (readbuf
, save
, NULL
);
217 gegl_node_process (save
);
218 g_object_unref (save_graph
);
219 gegl_meta_set_audio (path
, audio
);
222 g_object_unref (audio
);
227 fprintf (stdout
, "\n");
231 g_object_unref (video_frame
);
233 g_object_unref (gegl_decode
);
240 gegl_meta_set_audio (const char *path
,
241 GeglAudioFragment
*audio
)
243 GError
*error
= NULL
;
244 GExiv2Metadata
*e2m
= gexiv2_metadata_new ();
245 gexiv2_metadata_open_path (e2m
, path
, &error
);
248 g_warning ("%s", error
->message
);
253 GString
*str
= g_string_new ("");
254 int sample_count
= gegl_audio_fragment_get_sample_count (audio
);
255 int channels
= gegl_audio_fragment_get_channels (audio
);
256 if (gexiv2_metadata_try_has_tag (e2m
, "Xmp.xmp.GEGL", &error
))
257 gexiv2_metadata_try_clear_tag (e2m
, "Xmp.xmp.GEGL", &error
);
259 g_string_append_printf (str
, "%i %i %i %i",
260 gegl_audio_fragment_get_sample_rate (audio
),
261 gegl_audio_fragment_get_channels (audio
),
262 gegl_audio_fragment_get_channel_layout (audio
),
263 gegl_audio_fragment_get_sample_count (audio
));
265 for (i
= 0; i
< sample_count
; i
++)
266 for (c
= 0; c
< channels
; c
++)
267 g_string_append_printf (str
, " %0.5f", audio
->data
[c
][i
]);
269 gexiv2_metadata_try_set_tag_string (e2m
, "Xmp.xmp.GeglAudio", str
->str
, &error
);
270 gexiv2_metadata_save_file (e2m
, path
, &error
);
272 g_warning ("%s", error
->message
);
273 g_string_free (str
, TRUE
);
275 g_object_unref (e2m
);
279 gegl_meta_get_audio (const char *path
,
280 GeglAudioFragment
*audio
)
283 GError
*error
= NULL
;
284 GExiv2Metadata
*e2m
= gexiv2_metadata_new ();
285 gexiv2_metadata_open_path (e2m
, path
, &error
);
288 gchar
*ret
= gexiv2_metadata_try_get_tag_string (e2m
, "Xmp.xmp.GeglAudio", &error
);
289 fprintf (stderr
, "should parse audio\n");
293 g_warning ("%s", error
->message
);
294 g_object_unref (e2m
);