Add Video Orientation interface support to v4l2src.
[platform/upstream/gst-plugins-good.git] / tests / icles / v4l2src-test.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <getopt.h>
4
5 #include <gst/gst.h>
6 #include <gst/interfaces/tuner.h>
7 #include <gst/interfaces/colorbalance.h>
8 #include <gst/interfaces/videoorientation.h>
9
10 GstElement *pipeline, *source, *sink;
11 GMainLoop *loop;
12 volatile int exit_read = 0;
13
14 void
15 print_options ()
16 {
17   printf ("\nf - to change the fequency\n");
18   printf ("i - to change the input\n");
19   printf ("n - to change the norm\n");
20   printf ("c - list color balance\n");
21   printf ("v - change video orientarion\n");
22   printf ("e - to exit\n");
23 }
24
25 void
26 run_options (char opt)
27 {
28   switch (opt) {
29     case 'f':
30     {
31       GstTuner *tuner = GST_TUNER (source);
32       GstTunerChannel *channel;
33       guint freq;
34
35       channel = gst_tuner_get_channel (tuner);
36
37       freq = gst_tuner_get_frequency (tuner, channel);
38
39       printf ("\ntype the new frequency (current = %lu) (-1 to cancel): ",
40           freq);
41       scanf ("%u", &freq);
42       if (freq != -1)
43         gst_tuner_set_frequency (tuner, channel, freq);
44     }
45       break;
46     case 'n':
47     {
48       GstTuner *tuner = GST_TUNER (source);
49       const GList *item, *list;
50       const GstTunerNorm *current_norm;
51       GstTunerNorm *norm = NULL;
52       gint index, next_norm;
53
54
55       list = gst_tuner_list_norms (tuner);
56
57       current_norm = gst_tuner_get_norm (tuner);
58
59       printf ("\nlist of norms:\n");
60       for (item = list, index = 0; item != NULL; item = item->next, ++index) {
61         norm = item->data;
62         if (current_norm == norm) {
63           printf (" * %u - %s\n", index, norm->label);
64         } else {
65           printf ("   %u - %s\n", index, norm->label);
66         }
67       }
68       printf ("\ntype the number of norm you want (-1 to cancel): ");
69       scanf ("%d", &next_norm);
70       if (next_norm < 0) {
71         break;
72       }
73       if (index <= next_norm) {
74         printf ("Norm %d not available\n", next_norm);
75         break;
76       }
77       for (item = list, index = 0; item != NULL && index <= next_norm;
78           item = item->next, ++index) {
79         norm = item->data;
80       }
81       if (norm)
82         gst_tuner_set_norm (tuner, norm);
83     }
84       break;
85     case 'i':
86     {
87       GstTuner *tuner = GST_TUNER (source);
88       const GList *item, *list;
89       const GstTunerChannel *current_channel;
90       GstTunerChannel *channel = NULL;
91       gint index, next_channel;
92
93
94       list = gst_tuner_list_channels (tuner);
95
96       current_channel = gst_tuner_get_channel (tuner);
97
98       printf ("\nlist of inputs:\n");
99       for (item = list, index = 0; item != NULL; item = item->next, ++index) {
100         channel = item->data;
101         if (current_channel == channel) {
102           printf (" * %u - %s\n", index, channel->label);
103         } else {
104           printf ("   %u - %s\n", index, channel->label);
105         }
106       }
107       printf ("\ntype the number of input you want (-1 to cancel): ");
108       scanf ("%d", &next_channel);
109       if (next_channel < 0) {
110         break;
111       }
112       if (index <= next_channel) {
113         printf ("Input %d not available\n", next_channel);
114         break;
115       }
116       for (item = list, index = 0; item != NULL && index <= next_channel;
117           item = item->next, ++index) {
118         channel = item->data;
119       }
120       if (channel)
121         gst_tuner_set_channel (tuner, channel);
122     }
123       break;
124     case 'e':
125       gst_element_set_state (pipeline, GST_STATE_NULL);
126       g_main_loop_quit (loop);
127       printf ("Bye\n");
128       g_thread_exit (0);
129       break;
130     case 'c':
131     {
132       GstColorBalance *balance = GST_COLOR_BALANCE (source);
133       const GList *controls;
134       GstColorBalanceChannel *channel;
135       const GList *item;
136       gint index, new_value;
137
138       controls = gst_color_balance_list_channels (balance);
139
140       printf ("\n");
141
142       if (controls == NULL) {
143         printf ("There is no list of colorbalance controls\n");
144         goto done;
145       }
146
147       if (controls) {
148         printf ("list of controls:\n");
149         for (item = controls, index = 0; item != NULL;
150             item = item->next, ++index) {
151           channel = item->data;
152           printf ("   %u - %s (%d - %d) = %d\n", index, channel->label,
153               channel->min_value, channel->max_value,
154               gst_color_balance_get_value (balance, channel));
155         }
156         printf ("\ntype the number of color control you want (-1 to cancel): ");
157         scanf ("%d", &new_value);
158         if (new_value == -1)
159           break;
160         for (item = controls, index = 0; item != NULL && index <= new_value;
161             item = item->next, ++index) {
162           channel = item->data;
163         }
164         printf ("   %u - %s (%d - %d) = %d, type the new value: ", index - 1,
165             channel->label, channel->min_value, channel->max_value,
166             gst_color_balance_get_value (balance, channel));
167         scanf ("%d", &new_value);
168         if (new_value == -1)
169           break;
170         gst_color_balance_set_value (balance, channel, new_value);
171       }
172     }
173     case 'v':
174     {
175       GstVideoOrientation *vidorient = GST_VIDEO_ORIENTATION (source);
176       gboolean flip = FALSE;
177       gint center = 0;
178
179       printf ("\n");
180
181       if (gst_video_orientation_get_hflip (vidorient, &flip)) {
182         gint new_value;
183
184         printf ("Horizontal flip is %s\n", flip ? "on" : "off");
185         printf ("\ntype 1 to toggle (-1 to cancel): ");
186         scanf ("%d", &new_value);
187         if (new_value == 1) {
188           flip = !flip;
189           if (gst_video_orientation_set_hflip (vidorient, flip)) {
190             gst_video_orientation_get_hflip (vidorient, &flip);
191             printf ("Now horizontal flip is %s\n", flip ? "on" : "off");
192           } else {
193             printf ("Error toggling horizontal flip\n");
194           }
195         } else {
196         }
197       } else {
198         printf ("Horizontal flip control not available\n");
199       }
200
201       if (gst_video_orientation_get_vflip (vidorient, &flip)) {
202         gint new_value;
203
204         printf ("\nVertical flip is %s\n", flip ? "on" : "off");
205         printf ("\ntype 1 to toggle (-1 to cancel): ");
206         scanf ("%d", &new_value);
207         if (new_value == 1) {
208           flip = !flip;
209           if (gst_video_orientation_set_vflip (vidorient, flip)) {
210             gst_video_orientation_get_vflip (vidorient, &flip);
211             printf ("Now vertical flip is %s\n", flip ? "on" : "off");
212           } else {
213             printf ("Error toggling vertical flip\n");
214           }
215         } else {
216         }
217       } else {
218         printf ("Vertical flip control not available\n");
219       }
220
221       if (gst_video_orientation_get_hcenter (vidorient, &center)) {
222         printf ("Horizontal center is %d\n", center);
223         printf ("\ntype the new horizontal center value (-1 to cancel): ");
224         scanf ("%d", &center);
225         if (center != -1) {
226           if (gst_video_orientation_set_hcenter (vidorient, center)) {
227             gst_video_orientation_get_hcenter (vidorient, &center);
228             printf ("Now horizontal center is %d\n", center);
229           } else {
230             printf ("Error setting horizontal center\n");
231           }
232         } else {
233         }
234       } else {
235         printf ("Horizontal center control not available\n");
236       }
237
238       if (gst_video_orientation_get_vcenter (vidorient, &center)) {
239         printf ("Vertical center is %d\n", center);
240         printf ("\ntype the new vertical center value (-1 to cancel): ");
241         scanf ("%d", &center);
242         if (center != -1) {
243           if (gst_video_orientation_set_vcenter (vidorient, center)) {
244             gst_video_orientation_get_vcenter (vidorient, &center);
245             printf ("Now vertical center is %d\n", center);
246           } else {
247             printf ("Error setting vertical center\n");
248           }
249         } else {
250         }
251       } else {
252         printf ("Vertical center control not available\n");
253       }
254
255     }
256       break;
257       break;
258     default:
259       if (opt != 10)
260         printf ("error: invalid option %c", opt);
261       break;
262   }
263
264 done:
265
266   return;
267
268 }
269
270 gpointer
271 read_user (gpointer data)
272 {
273
274   char opt;
275
276   while (!exit_read) {
277
278     print_options ();
279
280     do {
281       opt = getchar ();
282       if (exit_read) {
283         break;
284       }
285     } while (opt == '\n');
286
287     run_options (opt);
288
289   }
290
291   return NULL;
292
293 }
294
295 static gboolean
296 my_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
297 {
298
299   switch (GST_MESSAGE_TYPE (message)) {
300     case GST_MESSAGE_ERROR:{
301       GError *err;
302       gchar *debug;
303
304       gst_message_parse_error (message, &err, &debug);
305       g_print ("%s error: %s\n",
306           gst_element_get_name (message->src), err->message);
307       g_print ("Debug: %s\n", debug);
308
309       g_error_free (err);
310       g_free (debug);
311
312       printf ("presse <ENTER> key to exit\n");
313       exit_read = 1;
314       g_main_loop_quit (loop);
315       break;
316     case GST_MESSAGE_EOS:
317       /* end-of-stream */
318       printf ("presse any key to exit\n");
319       exit_read = 1;
320       g_main_loop_quit (loop);
321       break;
322     default:
323       break;
324     }
325   }
326   return TRUE;
327 }
328
329 int
330 main (int argc, char *argv[])
331 {
332
333   GThread *input_thread;
334   gint numbuffers = -1;
335   gchar device[128] = { '\0' };
336   gchar input[128] = { '\0' };
337   gulong frequency = 0;
338   gboolean nofixedfps = TRUE;
339
340
341   /* see for input option */
342
343   int c;
344
345   while (1) {
346     static char long_options_desc[][64] = {
347       {"Number of buffers to output before sending EOS"},
348       {"Device location. Common in /dev/video0"},
349       {"input/output (channel) to switch to"},
350       {"frequency to tune to (in Hz)"},
351       {"set use-fixed-fps to FALSE"},
352       {0, 0, 0, 0}
353     };
354     static struct option long_options[] = {
355       {"numbuffers", 1, 0, 'n'},
356       {"device", 1, 0, 'd'},
357       {"input", 1, 0, 'i'},
358       {"frequency", 1, 0, 'f'},
359       {"nofixedfps", 0, 0, 's'},
360       {0, 0, 0, 0}
361     };
362     /* getopt_long stores the option index here. */
363     int option_index = 0;
364
365     c = getopt_long (argc, argv, "n:d:i:f:sh:", long_options, &option_index);
366
367     /* Detect the end of the options. */
368     if (c == -1) {
369       printf ("tip: use -h to see help message.\n");
370       break;
371     }
372
373     switch (c) {
374       case 0:
375         /* If this option set a flag, do nothing else now. */
376         if (long_options[option_index].flag != 0)
377           break;
378         printf ("option %s", long_options[option_index].name);
379         if (optarg)
380           printf (" with arg %s", optarg);
381         printf ("\n");
382         break;
383
384       case 'n':
385         numbuffers = atoi (optarg);
386         break;
387
388       case 'd':
389         strncpy (device, optarg, sizeof (device) / sizeof (device[0]));
390         break;
391
392       case 'i':
393         strncpy (input, optarg, sizeof (input) / sizeof (input[0]));
394         break;
395
396       case 'f':
397         frequency = atol (optarg);
398         break;
399
400       case 's':
401         nofixedfps = FALSE;
402         break;
403
404       case 'h':
405         printf ("Usage: v4l2src-test [OPTION]...\n");
406         for (c = 0; long_options[c].name; ++c) {
407           printf ("-%c, --%s\r\t\t\t\t%s\n", long_options[c].val,
408               long_options[c].name, long_options_desc[c]);
409         }
410         exit (0);
411         break;
412
413       case '?':
414         /* getopt_long already printed an error message. */
415         printf ("Use -h to see help message.\n");
416         break;
417
418       default:
419         abort ();
420     }
421   }
422
423
424   /* Print any remaining command line arguments (not options). */
425   if (optind < argc) {
426     printf ("Use -h to see help message.\n" "non-option ARGV-elements: ");
427     while (optind < argc)
428       printf ("%s ", argv[optind++]);
429     putchar ('\n');
430   }
431
432
433
434   /* init */
435   gst_init (&argc, &argv);
436
437   /* create elements */
438   if (!(pipeline = gst_pipeline_new ("my_pipeline"))) {
439     fprintf (stderr, "error: gst_pipeline_new return NULL");
440     return -1;
441   }
442
443   if (!(source = gst_element_factory_make ("v4l2src", NULL))) {
444     fprintf (stderr,
445         "error: gst_element_factory_make (\"v4l2src\", NULL) return NULL");
446     return -1;
447   }
448
449   if (!(sink = gst_element_factory_make ("xvimagesink", NULL))) {
450     fprintf (stderr,
451         "error: gst_element_factory_make (\"xvimagesink\", NULL) return NULL");
452     return -1;
453   }
454
455   if (numbuffers > -1) {
456     g_object_set (source, "num-buffers", numbuffers, NULL);
457   }
458   if (device[0]) {
459     g_object_set (source, "device", device, NULL);
460   }
461   if (input[0]) {
462     g_object_set (source, "input", input, NULL);
463   }
464   if (frequency) {
465     g_object_set (source, "frequency", frequency, NULL);
466   }
467   if (!nofixedfps) {
468     g_object_set (source, "use-fixed-fps", nofixedfps, NULL);
469   }
470
471   /* you would normally check that the elements were created properly */
472   gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)),
473       my_bus_callback, NULL);
474
475   /* put together a pipeline */
476   gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
477   gst_element_link_pads (source, "src", sink, "sink");
478
479   /* start the pipeline */
480   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
481   loop = g_main_loop_new (NULL, FALSE);
482
483   if (!(input_thread = g_thread_create (read_user, source, TRUE, NULL))) {
484     fprintf (stderr, "error: g_thread_create return NULL");
485     return -1;
486   }
487
488   g_main_loop_run (loop);
489   g_thread_join (input_thread);
490
491   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_NULL);
492
493   gst_object_unref (pipeline);
494
495   gst_deinit ();
496
497   return 0;
498
499 }