diff options
author | Harinarayan Bhatta | 2014-06-04 05:33:09 -0500 |
---|---|---|
committer | Harinarayan Bhatta | 2014-06-04 05:33:09 -0500 |
commit | f37124789d9e76de31fbd309296f3a4abb4440a6 (patch) | |
tree | 417400e4c0a217d1c8193893fb2181c153db1e4d | |
parent | 5100105cc46208025af3dbb7944c70b24c3faf0e (diff) | |
download | example-applications-f37124789d9e76de31fbd309296f3a4abb4440a6.tar.gz example-applications-f37124789d9e76de31fbd309296f3a4abb4440a6.tar.xz example-applications-f37124789d9e76de31fbd309296f3a4abb4440a6.zip |
Adding gstreamer test application to test trick play modes
Signed-off-by: Harinarayan Bhatta <harinarayan@ti.com>
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 25 | ||||
-rw-r--r-- | gst/Makefile.am | 8 | ||||
-rw-r--r-- | gst/gsttestplayer.c | 384 |
4 files changed, 417 insertions, 2 deletions
diff --git a/Makefile.am b/Makefile.am index 126b679..2397706 100644 --- a/Makefile.am +++ b/Makefile.am | |||
@@ -1 +1 @@ | |||
SUBDIRS = vpe drm-tests thermal messageq/messageq_ipc_linux | SUBDIRS = vpe drm-tests thermal messageq/messageq_ipc_linux gst | ||
diff --git a/configure.ac b/configure.ac index 1d8ee0f..e65333e 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -6,6 +6,9 @@ AC_INIT(example-apps, 0.1, https://git.ti.com/glsdk/example-applications) | |||
6 | AC_CONFIG_SRCDIR([Makefile.am]) | 6 | AC_CONFIG_SRCDIR([Makefile.am]) |
7 | AC_CONFIG_HEADERS([config.h]) | 7 | AC_CONFIG_HEADERS([config.h]) |
8 | 8 | ||
9 | dnl required versions of gstreamer and plugins-base | ||
10 | GST_REQUIRED=0.10.30 | ||
11 | |||
9 | #Initialize automake | 12 | #Initialize automake |
10 | AM_INIT_AUTOMAKE([foreign dist-bzip2]) | 13 | AM_INIT_AUTOMAKE([foreign dist-bzip2]) |
11 | AM_MAINTAINER_MODE | 14 | AM_MAINTAINER_MODE |
@@ -37,11 +40,31 @@ AM_CONDITIONAL(ENABLE_CAIRO, [test "x$HAVE_CAIRO" = xyes]) | |||
37 | 40 | ||
38 | PKG_CHECK_MODULES(GTHREAD, gthread-2.0) | 41 | PKG_CHECK_MODULES(GTHREAD, gthread-2.0) |
39 | 42 | ||
43 | dnl Check for the required version of GStreamer core (and gst-plugins-base) | ||
44 | dnl This will export GST_CFLAGS and GST_LIBS variables for use in Makefile.am | ||
45 | PKG_CHECK_MODULES(GST, [ | ||
46 | gstreamer-0.10 >= $GST_REQUIRED | ||
47 | gstreamer-base-0.10 >= $GST_REQUIRED | ||
48 | gstreamer-plugins-base-0.10 >= $GST_REQUIRED | ||
49 | gstreamer-plugins-bad-0.10 | ||
50 | ], [ | ||
51 | AC_SUBST(GST_CFLAGS) | ||
52 | AC_SUBST(GST_LIBS) | ||
53 | ], [ | ||
54 | AC_MSG_ERROR([ | ||
55 | You need to install or upgrade the GStreamer development | ||
56 | packages on your system. On debian-based systems these are | ||
57 | libgstreamer0.10-dev and libgstreamer-plugins-base0.10-dev. | ||
58 | on RPM-based systems gstreamer0.10-devel, libgstreamer0.10-devel | ||
59 | or similar. The minimum version required is $GST_REQUIRED. | ||
60 | ]) | ||
61 | ]) | ||
62 | |||
40 | # Checks for header files. | 63 | # Checks for header files. |
41 | 64 | ||
42 | # Checks for typedefs, structures, and compiler characteristics. | 65 | # Checks for typedefs, structures, and compiler characteristics. |
43 | 66 | ||
44 | # Checks for library functions. | 67 | # Checks for library functions. |
45 | 68 | ||
46 | AC_CONFIG_FILES([Makefile vpe/Makefile drm-tests/Makefile thermal/Makefile messageq/messageq_ipc_linux/Makefile]) | 69 | AC_CONFIG_FILES([Makefile vpe/Makefile drm-tests/Makefile thermal/Makefile messageq/messageq_ipc_linux/Makefile gst/Makefile]) |
47 | AC_OUTPUT | 70 | AC_OUTPUT |
diff --git a/gst/Makefile.am b/gst/Makefile.am new file mode 100644 index 0000000..67144c2 --- /dev/null +++ b/gst/Makefile.am | |||
@@ -0,0 +1,8 @@ | |||
1 | |||
2 | noinst_PROGRAMS = gsttestplayer | ||
3 | |||
4 | gsttestplayer_SOURCES = gsttestplayer.c | ||
5 | gsttestplayer_CFLAGS = $(GST_CFLAGS) | ||
6 | gsttestplayer_LDADD = $(GST_LIBS) | ||
7 | |||
8 | |||
diff --git a/gst/gsttestplayer.c b/gst/gsttestplayer.c new file mode 100644 index 0000000..5de21cc --- /dev/null +++ b/gst/gsttestplayer.c | |||
@@ -0,0 +1,384 @@ | |||
1 | /* | ||
2 | * GStreamer | ||
3 | * Copyright (c) 2014, Texas Instruments Incorporated | ||
4 | * | ||
5 | * This library is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU Lesser General Public | ||
7 | * License as published by the Free Software Foundation | ||
8 | * version 2.1 of the License. | ||
9 | * | ||
10 | * This library is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * Lesser General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU Lesser General Public | ||
16 | * License along with this library; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | #ifdef HAVE_CONFIG_H | ||
21 | #include <config.h> | ||
22 | #endif /* */ | ||
23 | |||
24 | #define _GNU_SOURCE | ||
25 | #include <features.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <errno.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <sys/time.h> | ||
31 | #include <unistd.h> | ||
32 | #include <string.h> | ||
33 | #include <ctype.h> | ||
34 | |||
35 | #include <gst/gst.h> | ||
36 | static int sigtermed = 0; | ||
37 | |||
38 | #define MAX_PIPELINES 16 | ||
39 | static GstElement *p[MAX_PIPELINES]; | ||
40 | static void | ||
41 | my_signal_handler (int signum) | ||
42 | { | ||
43 | if (signum == SIGINT) { | ||
44 | sigtermed = 1; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | static void | ||
49 | pad_added_cb (GstElement * element, GstPad * pad, void *data) | ||
50 | { | ||
51 | GstElement *parse = GST_ELEMENT (data); | ||
52 | GstPad *sinkpad; | ||
53 | gchar *theName = GST_PAD_NAME (pad); | ||
54 | printf ("pad added:%s\n", theName); | ||
55 | if (strstr (theName, "video") != NULL) { | ||
56 | sinkpad = gst_element_get_static_pad (parse, "sink"); | ||
57 | gst_pad_link (pad, sinkpad); | ||
58 | gst_object_unref (sinkpad); | ||
59 | } else | ||
60 | printf ("not linking audio pad\n"); | ||
61 | } | ||
62 | |||
63 | static const char *sinkname = "kmssink"; | ||
64 | static gboolean use_vpe = TRUE; | ||
65 | static gboolean use_scaling = TRUE; | ||
66 | static gint scale_w = 800, scale_h = 480; | ||
67 | static gboolean use_avsync = TRUE; | ||
68 | static GstElement * | ||
69 | create_pipeline (char *arg) | ||
70 | { | ||
71 | GstElement *src1; | ||
72 | GstElement *demux; | ||
73 | GstElement *vdecode, *h264parse, *pipeline, *filter; | ||
74 | GstElement *vqueue; | ||
75 | GstElement *queue, *vsink; | ||
76 | GstCaps *filtercaps; | ||
77 | const char *decoder_name, *parser_name, *demux_name; | ||
78 | if (NULL != strcasestr (arg, ".mkv")) | ||
79 | demux_name = "matroskademux"; | ||
80 | |||
81 | else if (NULL != strcasestr (arg, ".mp4")) | ||
82 | demux_name = "qtdemux"; | ||
83 | |||
84 | else if (NULL != strcasestr (arg, ".asf")) | ||
85 | demux_name = "asfdemux"; | ||
86 | |||
87 | else if (NULL != strcasestr (arg, ".wmv")) | ||
88 | demux_name = "asfdemux"; | ||
89 | |||
90 | else if (NULL != strcasestr (arg, ".ts")) | ||
91 | demux_name = "mpegtsdemux"; | ||
92 | |||
93 | else | ||
94 | demux_name = "identity"; | ||
95 | if (NULL != strcasestr (arg, "264")) { | ||
96 | decoder_name = use_vpe ? "ducatih264decvpe" : "ducatih264dec"; | ||
97 | parser_name = "h264parse"; | ||
98 | } | ||
99 | |||
100 | else if (NULL != strcasestr (arg, "mpeg2")) { | ||
101 | decoder_name = use_vpe ? "ducatimpeg2decvpe" : "ducatimpeg2dec"; | ||
102 | parser_name = "mpegvideoparse"; | ||
103 | } | ||
104 | |||
105 | else if (NULL != strcasestr (arg, "mpeg4")) { | ||
106 | decoder_name = use_vpe ? "ducatimpeg4decvpe" : "ducatimpeg4dec"; | ||
107 | parser_name = "mpeg4videoparse"; | ||
108 | } | ||
109 | |||
110 | else { | ||
111 | decoder_name = use_vpe ? "ducativc1decvpe" : "ducativc1dec"; | ||
112 | parser_name = "identity"; | ||
113 | } | ||
114 | printf ("Creating pipeline with %s->%s->%s\n", demux_name, parser_name, | ||
115 | decoder_name); | ||
116 | pipeline = gst_pipeline_new ("my-pipeline"); | ||
117 | src1 = gst_element_factory_make ("filesrc", "src1"); | ||
118 | if (src1 == NULL) | ||
119 | printf ("Could not create 'src1' element\r\n"); | ||
120 | demux = gst_element_factory_make (demux_name, "demux"); | ||
121 | if (demux == NULL) | ||
122 | printf ("Could not create 'demux' element\r\n"); | ||
123 | vdecode = gst_element_factory_make (decoder_name, "vdecode"); | ||
124 | if (vdecode == NULL) | ||
125 | printf ("Could not create 'omx_h264dec1' element\r\n"); | ||
126 | h264parse = gst_element_factory_make (parser_name, "h264parse"); | ||
127 | if (h264parse == NULL) | ||
128 | printf ("Could not create 'h264parse' element\r\n"); | ||
129 | vsink = gst_element_factory_make (sinkname, "kmssink"); | ||
130 | if (vsink == NULL) | ||
131 | printf ("Could not create '%s' element\r\n", sinkname); | ||
132 | queue = gst_element_factory_make ("queue", "queue"); | ||
133 | if (queue == NULL) | ||
134 | printf ("Could not create 'queue' element\r\n"); | ||
135 | vqueue = gst_element_factory_make ("queue", "vqueue"); | ||
136 | if (vqueue == NULL) | ||
137 | printf ("Could not create 'queue' element\r\n"); | ||
138 | filter = | ||
139 | gst_element_factory_make (use_scaling ? "capsfilter" : "identity", | ||
140 | "filter"); | ||
141 | if (filter == NULL) | ||
142 | printf ("Could not create 'capsfilter' element\r\n"); | ||
143 | filtercaps = | ||
144 | gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, | ||
145 | GST_MAKE_FOURCC ('N', 'V', '1', '2'), "width", G_TYPE_INT, scale_w, | ||
146 | "height", G_TYPE_INT, scale_h, NULL); | ||
147 | g_object_set (G_OBJECT (filter), "caps", filtercaps, NULL); | ||
148 | gst_caps_unref (filtercaps); | ||
149 | printf ("set locaticn to : %s\n", arg); | ||
150 | |||
151 | // ================= Add capabilities and properties | ||
152 | // g_object_set(G_OBJECT (scaler), "num-input-buffers", 24, NULL); | ||
153 | // g_object_set(G_OBJECT (scaler), "num-output-buffers", 12, NULL); | ||
154 | // g_object_set(G_OBJECT (vdecode), "max-reorder-frames", 4, NULL); | ||
155 | g_object_set (G_OBJECT (src1), "location", arg, NULL); | ||
156 | g_object_set (G_OBJECT (vsink), "sync", use_avsync, NULL); | ||
157 | |||
158 | // ================= Put pipeline together | ||
159 | gst_bin_add_many (GST_BIN (pipeline), src1, demux, h264parse, vdecode, | ||
160 | vsink, filter, vqueue, queue, NULL); | ||
161 | gst_element_link_many (src1, demux, NULL); | ||
162 | gst_element_link_many (h264parse, queue, vdecode, vqueue, filter, | ||
163 | vsink, NULL); | ||
164 | if (!g_signal_connect (demux, "pad-added", G_CALLBACK (pad_added_cb), | ||
165 | (void *) h264parse)) | ||
166 | printf ("Cannot connect pad-added cb\r\n"); | ||
167 | |||
168 | // ================= Run | ||
169 | printf ("Set Play Mode ...\r\n"); | ||
170 | gst_element_set_state (pipeline, GST_STATE_PLAYING); | ||
171 | |||
172 | #if 0 | ||
173 | { | ||
174 | GstClock *clk = gst_pipeline_get_clock (GST_PIPELINE (pipeline)); | ||
175 | if (clk) { | ||
176 | printf ("Pipeline clock is %s\n", GST_OBJECT_NAME (clk)); | ||
177 | gst_object_unref (clk); | ||
178 | } | ||
179 | } | ||
180 | |||
181 | #endif /* */ | ||
182 | return pipeline; | ||
183 | } | ||
184 | |||
185 | gint | ||
186 | main (gint argc, gchar * argv[]) | ||
187 | { | ||
188 | FILE *in = stdin; | ||
189 | fd_set f; | ||
190 | char *line = NULL; | ||
191 | char linebuf[1024]; | ||
192 | char *args[10]; | ||
193 | int n, i, time, j, rate; | ||
194 | GstEvent *seek_event; | ||
195 | if (SIG_ERR == signal (SIGINT, my_signal_handler)) | ||
196 | exit (1); | ||
197 | |||
198 | if (argc > 1 && (0 == strcmp ("-h", argv[1]) | ||
199 | || 0 == strcmp ("--help", argv[1]))) { | ||
200 | printf ("Usage: %s <options>\n", argv[0]); | ||
201 | printf (" -s <sinkname> Specify the video sink name to be used, default: kmssink\n"); | ||
202 | printf (" -n Do not use VPE, implies no scaling\n"); | ||
203 | printf (" -r <width>x<height> Resize the output to widthxheight, no scaling if left blank\n"); | ||
204 | printf (" -a Play with no A/V Sync\n"); | ||
205 | printf (" -c <cmds file> Non-interactive mode, reading commands from <cmds file>\n"); | ||
206 | } | ||
207 | |||
208 | /* Init GStreamer */ | ||
209 | gst_init (&argc, &argv); | ||
210 | |||
211 | for (i = 1; i < argc; i++) { | ||
212 | if (0 == strcmp ("-s", argv[i])) { | ||
213 | sinkname = argv[i + 1]; | ||
214 | i++; | ||
215 | } | ||
216 | if (0 == strcmp ("-n", argv[i])) { | ||
217 | use_vpe = FALSE; | ||
218 | use_scaling = FALSE; | ||
219 | printf ("Not using VPE...\n"); | ||
220 | } | ||
221 | if (0 == strcmp ("-r", argv[i])) { | ||
222 | if ((i + 1) < argc | ||
223 | && 2 == sscanf (argv[i + 1], "%dx%d", &scale_w, &scale_h)) { | ||
224 | printf ("Scaling output to %dx%d\n", scale_w, scale_h); | ||
225 | } else { | ||
226 | use_scaling = FALSE; | ||
227 | printf ("Not using Scaling...\n"); | ||
228 | } | ||
229 | } | ||
230 | if (0 == strcmp ("-a", argv[i])) { | ||
231 | use_avsync = FALSE; | ||
232 | printf ("No A/V Sync, playing as fast as possible...\n"); | ||
233 | } | ||
234 | if (0 == strcmp ("-c", argv[i]) && (i + 1) < argc) { | ||
235 | in = fopen (argv[i + 1], "r"); | ||
236 | if (!in) { | ||
237 | printf | ||
238 | ("cannot open %s to read in commands, reverting to interactive mode\n", | ||
239 | argv[i + 1]); | ||
240 | in = stdin; | ||
241 | } | ||
242 | i++; | ||
243 | } | ||
244 | } | ||
245 | printf ("Using videosink=%s\n", sinkname); | ||
246 | |||
247 | // To detect memory leaks | ||
248 | if (!gst_alloc_trace_available ()) { | ||
249 | printf ("Trace not available (recompile with trace enabled).\n"); | ||
250 | } else { | ||
251 | gst_alloc_trace_set_flags_all (GST_ALLOC_TRACE_LIVE | | ||
252 | GST_ALLOC_TRACE_MEM_LIVE); | ||
253 | gst_alloc_trace_print_live (); | ||
254 | } | ||
255 | while (!sigtermed) { | ||
256 | if (in == stdin) { | ||
257 | fflush (stdout); | ||
258 | FD_ZERO (&f); | ||
259 | FD_SET (0, &f); | ||
260 | } | ||
261 | printf ("<Enter ip> "); | ||
262 | line = fgets (linebuf, 1023, in); | ||
263 | if (!line) | ||
264 | continue; | ||
265 | line[1023] = '\0'; | ||
266 | n = 0; | ||
267 | while (*line) { | ||
268 | args[n++] = line; | ||
269 | while (!isspace (*line)) | ||
270 | line++; | ||
271 | if (!(*line)) | ||
272 | break; | ||
273 | *line = '\0'; | ||
274 | line++; | ||
275 | while (isspace (*line)) | ||
276 | line++; | ||
277 | } | ||
278 | if (3 == n && 0 == strcmp ("start", args[0])) { | ||
279 | i = atoi (args[1]); | ||
280 | printf ("Starting pipeline %d\n", i); | ||
281 | p[i] = create_pipeline (args[2]); | ||
282 | } | ||
283 | |||
284 | else if (2 == n && 0 == strcmp ("stop", args[0])) { | ||
285 | i = atoi (args[1]); | ||
286 | if (p[i]) { | ||
287 | gst_element_set_state (p[i], GST_STATE_NULL); | ||
288 | gst_object_unref (p[i]); | ||
289 | p[i] = NULL; | ||
290 | } | ||
291 | } | ||
292 | |||
293 | else if (2 == n && 0 == strcmp ("pause", args[0])) { | ||
294 | i = atoi (args[1]); | ||
295 | if (p[i]) | ||
296 | gst_element_set_state (p[i], GST_STATE_PAUSED); | ||
297 | } | ||
298 | |||
299 | else if (2 == n && 0 == strcmp ("resume", args[0])) { | ||
300 | i = atoi (args[1]); | ||
301 | if (p[i]) | ||
302 | gst_element_set_state (p[i], GST_STATE_PLAYING); | ||
303 | } | ||
304 | |||
305 | else if (3 <= n && 0 == strcmp ("seek", args[0])) { | ||
306 | i = atoi (args[1]); | ||
307 | time = atoi (args[2]); | ||
308 | rate = (n == 3) ? 1 : atoi (args[3]); | ||
309 | if (p[i]) { | ||
310 | if (rate == 1) { | ||
311 | gst_element_seek_simple (p[i], GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH, | ||
312 | time * GST_SECOND); | ||
313 | } else { | ||
314 | if (rate > 1) { | ||
315 | seek_event = | ||
316 | gst_event_new_seek (rate, GST_FORMAT_TIME, | ||
317 | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, | ||
318 | time * GST_SECOND, GST_SEEK_TYPE_NONE, 0); | ||
319 | } else { | ||
320 | seek_event = | ||
321 | gst_event_new_seek (rate, GST_FORMAT_TIME, | ||
322 | GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, | ||
323 | 0, GST_SEEK_TYPE_SET, time * GST_SECOND); | ||
324 | } | ||
325 | gst_element_send_event (p[i], seek_event); | ||
326 | } | ||
327 | } | ||
328 | } | ||
329 | |||
330 | else if (2 == n && 0 == strcmp ("step", args[0])) { | ||
331 | i = atoi (args[1]); | ||
332 | rate = atoi (args[2]); | ||
333 | if (p[i]) { | ||
334 | gst_element_send_event (p[i], | ||
335 | gst_event_new_step (GST_FORMAT_BUFFERS, 1, rate, TRUE, FALSE)); | ||
336 | } | ||
337 | } | ||
338 | |||
339 | else if (2 == n && 0 == strcmp ("sleep", args[0])) { | ||
340 | sleep (atoi (args[1])); | ||
341 | } | ||
342 | |||
343 | else if (2 == n && 0 == strcmp ("rewind", args[0])) { | ||
344 | if (in != stdin) { | ||
345 | rewind (in); | ||
346 | j = atoi (args[1]); | ||
347 | while (--j) | ||
348 | fgets (linebuf, 1023, in); | ||
349 | } | ||
350 | } | ||
351 | |||
352 | else if (1 == n && 0 == strcmp ("exit", args[0])) { | ||
353 | break; | ||
354 | } | ||
355 | |||
356 | else if (1 == n && 0 == strcmp ("help", args[0])) { | ||
357 | printf ("Commands available:\n"); | ||
358 | printf (" start <instance num> <filename>\n"); | ||
359 | printf (" stop <instance num>\n"); | ||
360 | printf (" pause <instance num>\n"); | ||
361 | printf (" resume <instance num>\n"); | ||
362 | printf | ||
363 | (" seek <instance num> <seek to time in seconds> <optional: playback speed>\n"); | ||
364 | printf (" sleep <sleep time in seconds>\n"); | ||
365 | printf | ||
366 | (" rewind <line number> <rewind command file go to line number>\n"); | ||
367 | printf (" exit\n"); | ||
368 | } | ||
369 | } | ||
370 | for (i = 0; i < MAX_PIPELINES; i++) { | ||
371 | if (p[i]) { | ||
372 | gst_element_set_state (p[i], GST_STATE_NULL); | ||
373 | gst_object_unref (p[i]); | ||
374 | p[i] = NULL; | ||
375 | } | ||
376 | } | ||
377 | sleep (1); | ||
378 | gst_alloc_trace_print_live (); | ||
379 | { | ||
380 | char command[256]; | ||
381 | sprintf (command, "ls -l //proc//%d//fd//", getpid ()); | ||
382 | system (command); | ||
383 | } return 0; | ||
384 | } | ||