197785dc7792182ba5a2abd93d9561b1a01389ba
[platform/upstream/gstreamer.git] / validate / gst / qa / gst-qa-file-check.c
1 /* GStreamer
2  * Copyright (C) 2013 Thiago Santos <thiago.sousa.santos@collabora.com>
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #  include "config.h"
7 #endif
8
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include <gst/gst.h>
13 #include <gst/qa/qa.h>
14 #include <gst/pbutils/encoding-profile.h>
15
16 static GstEncodingProfile *encoding_profile = NULL;
17
18 /* move this into some utils file */
19 static gboolean
20 _parse_encoding_profile (const gchar * option_name, const gchar * value,
21     gpointer udata, GError ** error)
22 {
23   GstCaps *caps;
24   char *preset_name = NULL;
25   gchar **restriction_format, **preset_v;
26
27   guint i, presence = 0;
28   GstCaps *restrictioncaps = NULL;
29   gchar **strpresence_v, **strcaps_v = g_strsplit (value, ":", 0);
30
31   if (strcaps_v[0] && *strcaps_v[0]) {
32     caps = gst_caps_from_string (strcaps_v[0]);
33     if (caps == NULL) {
34       g_printerr ("Could not parse caps %s", strcaps_v[0]);
35       return FALSE;
36     }
37     encoding_profile =
38         GST_ENCODING_PROFILE (gst_encoding_container_profile_new
39         ("User profile", "User profile", caps, NULL));
40     gst_caps_unref (caps);
41   } else {
42     encoding_profile = NULL;
43   }
44
45   for (i = 1; strcaps_v[i]; i++) {
46     GstEncodingProfile *profile = NULL;
47     gchar *strcaps, *strpresence;
48
49     restriction_format = g_strsplit (strcaps_v[i], "->", 0);
50     if (restriction_format[1]) {
51       restrictioncaps = gst_caps_from_string (restriction_format[0]);
52       strcaps = g_strdup (restriction_format[1]);
53     } else {
54       restrictioncaps = NULL;
55       strcaps = g_strdup (restriction_format[0]);
56     }
57     g_strfreev (restriction_format);
58
59     preset_v = g_strsplit (strcaps, "+", 0);
60     if (preset_v[1]) {
61       strpresence = preset_v[1];
62       g_free (strcaps);
63       strcaps = g_strdup (preset_v[0]);
64     } else {
65       strpresence = preset_v[0];
66     }
67
68     strpresence_v = g_strsplit (strpresence, "|", 0);
69     if (strpresence_v[1]) {     /* We have a presence */
70       gchar *endptr;
71
72       if (preset_v[1]) {        /* We have preset and presence */
73         preset_name = g_strdup (strpresence_v[0]);
74       } else {                  /* We have a presence but no preset */
75         g_free (strcaps);
76         strcaps = g_strdup (strpresence_v[0]);
77       }
78
79       presence = strtoll (strpresence_v[1], &endptr, 10);
80       if (endptr == strpresence_v[1]) {
81         g_printerr ("Wrong presence %s\n", strpresence_v[1]);
82
83         return FALSE;
84       }
85     } else {                    /* We have no presence */
86       if (preset_v[1]) {        /* Not presence but preset */
87         preset_name = g_strdup (preset_v[1]);
88         g_free (strcaps);
89         strcaps = g_strdup (preset_v[0]);
90       }                         /* Else we have no presence nor preset */
91     }
92     g_strfreev (strpresence_v);
93     g_strfreev (preset_v);
94
95     GST_DEBUG ("Creating preset with restrictions: %" GST_PTR_FORMAT
96         ", caps: %s, preset %s, presence %d", restrictioncaps, strcaps,
97         preset_name ? preset_name : "none", presence);
98
99     caps = gst_caps_from_string (strcaps);
100     g_free (strcaps);
101     if (caps == NULL) {
102       g_warning ("Could not create caps for %s", strcaps_v[i]);
103
104       return FALSE;
105     }
106
107     if (g_str_has_prefix (strcaps_v[i], "audio/")) {
108       profile = GST_ENCODING_PROFILE (gst_encoding_audio_profile_new (caps,
109               preset_name, restrictioncaps, presence));
110     } else if (g_str_has_prefix (strcaps_v[i], "video/") ||
111         g_str_has_prefix (strcaps_v[i], "image/")) {
112       profile = GST_ENCODING_PROFILE (gst_encoding_video_profile_new (caps,
113               preset_name, restrictioncaps, presence));
114     }
115
116     g_free (preset_name);
117     gst_caps_unref (caps);
118     if (restrictioncaps)
119       gst_caps_unref (restrictioncaps);
120
121     if (profile == NULL) {
122       g_warning ("No way to create a preset for caps: %s", strcaps_v[i]);
123
124       return FALSE;
125     }
126
127     if (encoding_profile) {
128       if (gst_encoding_container_profile_add_profile
129           (GST_ENCODING_CONTAINER_PROFILE (encoding_profile),
130               profile) == FALSE) {
131         g_warning ("Can not create a preset for caps: %s", strcaps_v[i]);
132
133         return FALSE;
134       }
135     } else {
136       encoding_profile = profile;
137     }
138   }
139   g_strfreev (strcaps_v);
140
141   return TRUE;
142 }
143
144 int
145 main (int argc, gchar ** argv)
146 {
147   GstQaRunner *runner;
148   GOptionContext *ctx;
149   GstQaFileChecker *fc;
150
151   GError *err = NULL;
152   guint count = -1;
153
154   gboolean playback = FALSE, seekable = FALSE, reverse_playback = FALSE;
155   gint64 filesize = 0, filesize_tolerance = 0, duration_arg =
156       0, duration_tolerance = 0;
157   GstClockTime duration = GST_CLOCK_TIME_NONE;
158
159   GOptionEntry options[] = {
160     {"expected-profile", 'o', 0, G_OPTION_ARG_CALLBACK,
161           &_parse_encoding_profile,
162           "Set the properties to use for the encoding profile "
163           "to be used as expected for the file. For example:\n"
164           "video/mpegts:video/x-raw-yuv,width=1920,height=1080->video/x-h264:audio/x-ac3\n"
165           "A preset name can be used by adding +presetname, eg:\n"
166           "video/webm:video/x-vp8+mypreset:audio/x-vorbis\n"
167           "The presence property of the profile can be specified with |<presence>, eg:\n"
168           "video/webm:video/x-vp8|<presence>:audio/x-vorbis\n",
169         "properties-values"},
170     {"seekable", 's', 0, G_OPTION_ARG_NONE,
171           &seekable, "If the file should be seekable",
172         NULL},
173     {"playback", 'p', 0, G_OPTION_ARG_NONE,
174           &playback, "If the file should be tested for playback",
175         NULL},
176     {"reverse-playback", '\0', 0, G_OPTION_ARG_NONE,
177           &reverse_playback,
178           "If the file should be tested for reverse playback",
179         NULL},
180     {"file-size", '\0', 0, G_OPTION_ARG_INT64, &filesize,
181         "The expected file size in bytes", NULL},
182     {"file-size-tolerance", '\0', 0, G_OPTION_ARG_INT64, &filesize_tolerance,
183         "The file size margin tolerance, in bytes", NULL},
184     {"duration", 'd', 0, G_OPTION_ARG_INT64, &duration_arg,
185         "The expected file duration in nanoseconds", NULL},
186     {"duration-tolerance", '\0', 0, G_OPTION_ARG_INT64, &duration_tolerance,
187         "The file duration tolerance margin, in nanoseconds", NULL},
188     {NULL}
189   };
190
191   ctx = g_option_context_new ("- runs QA transcoding test.");
192   g_option_context_add_main_entries (ctx, options, NULL);
193
194   if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
195     g_printerr ("Error initializing: %s\n", err->message);
196     g_option_context_free (ctx);
197     exit (1);
198   }
199
200   g_option_context_free (ctx);
201
202   gst_init (&argc, &argv);
203
204   if (argc != 2) {
205     g_printerr ("%i arguments recived, 1 expected.\n"
206         "You should run the test using:\n"
207         "    ./gst-qa-file-check-0.10 <uri> [options]\n", argc - 1);
208     return 1;
209   }
210
211   if (duration_arg > 0)
212     duration = (GstClockTime) duration_arg;
213
214   /* Create the pipeline */
215   runner = gst_qa_runner_new ();
216   fc = g_object_new (GST_TYPE_QA_FILE_CHECKER, "uri",
217       argv[1], "profile", encoding_profile, "qa-runner", runner,
218       "is-seekable", seekable, "test-playback", playback,
219       "test-reverse-playback", reverse_playback,
220       "file-size", (guint64) filesize, "file-size-tolerance", (guint64)
221       filesize_tolerance, "duration", (guint64) duration,
222       "duration-tolerance", (guint64) duration_tolerance, NULL);
223
224   g_print ("Starting tests\n");
225   if (!gst_qa_file_checker_run (fc)) {
226     g_print ("Failed file checking\n");
227   }
228   count = gst_qa_runner_get_reports_count (runner);
229   g_print ("Tests finished, total issues found: %u\n", count);
230   g_object_unref (fc);
231
232   g_object_unref (runner);
233
234   if (count)
235     return -1;
236   return 0;
237 }