Update Portuguese translation
[gegl.git] / examples / gegl-video.c
bloba1c6f7c403a8ff8547c561d87391aa2579340698
1 /*
2 * gegl-video <video-file|frame-folder|frames|edl>
4 * --output-frames path/image- --frame-extension png
5 * --output-video path/video.avi
6 * --play (default)
7 * -- gegl:threshold value=0.3
9 * the edl,. should be a list of frames.. and video with frame start->end bits
10 * 0001.png
11 * 0002.png
12 * 0003.png
13 * 0004.png
14 * foo.avi 3-210
15 * clip2.avi
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.
22 #include <gegl.h>
23 #include <gegl-audio-fragment.h>
24 #include <glib/gprintf.h>
25 #include <gexiv2/gexiv2.h>
26 #include <stdint.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <math.h>
31 int frame_start = 0;
32 int frame_end = 0;
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;
40 void
41 gegl_meta_set_audio (const char *path,
42 GeglAudioFragment *audio);
43 void
44 gegl_meta_get_audio (const char *path,
45 GeglAudioFragment *audio);
47 void usage(void);
48 void usage(void)
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"
59 "\n"
60 "Options can also follow then video (and thumb) arguments.\n"
61 "\n");
62 exit (0);
65 static void parse_args (int argc, char **argv)
67 int i;
68 int stage = 0;
69 for (i = 1; i < argc; i++)
71 if (g_str_equal (argv[i], "-p") ||
72 g_str_equal (argv[i], "--progress"))
74 show_progress = 1;
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);
80 i++;
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;
86 i++;
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]);
92 i++;
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);
98 i++;
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]);
104 i++;
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);
110 i++;
112 else if (g_str_equal (argv[i], "-h") ||
113 g_str_equal (argv[i], "--help"))
115 usage();
117 else if (stage == 0)
119 video_path = g_strdup (argv[i]);
120 stage = 1;
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)
135 if (video_frame)
137 g_object_unref (video_frame);
139 video_frame = NULL;
140 gegl_node_set (load, "frame", frame, NULL);
141 gegl_node_process (store);
144 GeglNode *translate = NULL;
146 gint
147 main (gint argc,
148 gchar **argv)
150 if (argc < 2)
151 usage();
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",
163 "frame", 0,
164 "path", video_path,
165 NULL);
166 gegl_node_link_many (load, store, NULL);
168 decode_frame_no (0);
171 int frames = 0;
172 double frame_rate = 0;
173 gegl_node_get (load, "frames", &frames, NULL);
174 gegl_node_get (load, "frame-rate", &frame_rate, NULL);
176 if (frame_end == 0)
177 frame_end = frames;
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);
187 gint frame;
188 for (frame = frame_start; frame <= frame_end; frame++)
190 if (show_progress)
192 fprintf (stdout, "\r%2.1f%% %i/%i (%i)",
193 (frame-frame_start) * 100.0 / (frame_end-frame_start),
194 frame-frame_start,
195 frame_end-frame_start,
196 frame);
197 fflush (stdout);
200 decode_frame_no (frame);
202 GeglAudioFragment *audio;
203 gdouble fps;
204 gegl_node_get (load, "audio", &audio,
205 "frame-rate", &fps, NULL);
207 if (frame_path)
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",
215 "path", path, NULL);
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);
220 g_free (path);
222 g_object_unref (audio);
226 if (show_progress)
227 fprintf (stdout, "\n");
230 if (video_frame)
231 g_object_unref (video_frame);
232 video_frame = NULL;
233 g_object_unref (gegl_decode);
235 gegl_exit ();
236 return 0;
239 void
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);
246 if (error)
248 g_warning ("%s", error->message);
250 else
252 int i, c;
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);
271 if (error)
272 g_warning ("%s", error->message);
273 g_string_free (str, TRUE);
275 g_object_unref (e2m);
278 void
279 gegl_meta_get_audio (const char *path,
280 GeglAudioFragment *audio)
282 //gchar *ret = NULL;
283 GError *error = NULL;
284 GExiv2Metadata *e2m = gexiv2_metadata_new ();
285 gexiv2_metadata_open_path (e2m, path, &error);
286 if (!error)
288 gchar *ret = gexiv2_metadata_try_get_tag_string (e2m, "Xmp.xmp.GeglAudio", &error);
289 fprintf (stderr, "should parse audio\n");
290 g_free (ret);
292 else
293 g_warning ("%s", error->message);
294 g_object_unref (e2m);