summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Dufresne <nicolas.dufresne@collabora.com>2013-12-23 20:01:46 (GMT)
committerNicolas Dufresne <nicolas.dufresne@collabora.com>2013-12-23 20:01:46 (GMT)
commit5e801fbf38e027bcb86548dd6c753f8a3b5d4ef2 (patch)
treecc8900ed103d07600b9d42eb4e817c00d0679983
downloadcc-compliance-5e801fbf38e027bcb86548dd6c753f8a3b5d4ef2.tar.gz
cc-compliance-5e801fbf38e027bcb86548dd6c753f8a3b5d4ef2.tar.xz
Implement simple test to cover the CTS
-rw-r--r--.gitignore4
-rwxr-xr-xMakefile29
-rw-r--r--cts-list.inc52
-rwxr-xr-xplayer.c316
4 files changed, 401 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1723faa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.swp
+*.o
+/player
+/Videos
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..bc6a973
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+include cts-list.inc
+
+CC = gcc
+
+LDFLAGS += `pkg-config --libs glib-2.0 gstreamer-1.0`
+CFLAGS += -g -Wall `pkg-config --cflags glib-2.0 gstreamer-1.0`
+
+SOURCES = $(wildcard *.c)
+OBJECTS = $(patsubst %.c,%.o,$(SOURCES))
+
+all: player
+
+player: $(OBJECTS)
+ $(CC) -o $@ $(OBJECTS) $(LDFLAGS)
+
+%.o: %.c
+ $(CC) -c $< $(CFLAGS) -o $@
+
+clean:
+ rm -f $(wildcard *.o) player
+
+.NOTPARALLEL: $(CTS_STREAMS)
+
+check: $(CTS_STREAMS)
+ @echo Success
+
+$(CTS_STREAMS): player
+ @./player "file://$(shell pwd)/Videos/$(@)"
+
diff --git a/cts-list.inc b/cts-list.inc
new file mode 100644
index 0000000..8d32be4
--- /dev/null
+++ b/cts-list.inc
@@ -0,0 +1,52 @@
+CTS_STREAMS = \
+ "bbb_full/1280x720/mp4_libx264_libfaac/bbb_full.ffmpeg.1280x720.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_full/1280x720/mp4_libx264_libfaac/bbb_full.ffmpeg.1280x720.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_full/1920x1080/mp4_libx264_libfaac/bbb_full.ffmpeg.1920x1080.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_full/720x480/mp4_libx264_libfaac/bbb_full.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.ts" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1350kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_5000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/1280x720/mp4_libx264_libfaac/bbb_short.ffmpeg.1280x720.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/1920x1080/mp4_libx264_libfaac/bbb_short.ffmpeg.1920x1080.mp4.libx264_10000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_short/1920x1080/mp4_libx264_libfaac/bbb_short.ffmpeg.1920x1080.mp4.libx264_1750kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_short/1920x1080/mp4_libx264_libfaac/bbb_short.ffmpeg.1920x1080.mp4.libx264_5000kbps_30fps.libfaac_stereo_192kbps_48000Hz.mp4" \
+ "bbb_short/1920x1080/mp4_libx264_libfaac/bbb_short.ffmpeg.1920x1080.mp4.libx264_5000kbps_30fps.libfaac_stereo_192kbps_48000Hz.ts" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.ts" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_1350kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/480x360/mp4_libx264_libfaac/bbb_short.ffmpeg.480x360.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1000kbps_30fps.libfaac_stereo_192kbps_44100Hz.ts" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_1350kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_25fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_30fps.libfaac_stereo_128kbps_44100Hz.mp4" \
+ "bbb_short/720x480/mp4_libx264_libfaac/bbb_short.ffmpeg.720x480.mp4.libx264_500kbps_30fps.libfaac_stereo_192kbps_44100Hz.mp4" \
+ $(null)
diff --git a/player.c b/player.c
new file mode 100755
index 0000000..e87c608
--- /dev/null
+++ b/player.c
@@ -0,0 +1,316 @@
+/*
+ * A Hands-On Course in GStreamer Development
+ * Copyright 2008 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* player-9:
+ *
+ * Modify player-8 to query and print playback position, and exit on command
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <gst/gst.h>
+
+#define PC 1
+
+#if PC == 0
+#define VIDEO_SINK "v4l2sink device=/dev/video12"
+#define PLAY_FLAGS \
+ GST_PLAY_FLAG_VIDEO | \
+ GST_PLAY_FLAG_NATIVE_VIDEO | \
+ GST_PLAY_FLAG_AUDIO
+#else
+#define VIDEO_SINK "xvimagesink"
+#define PLAY_FLAGS \
+ GST_PLAY_FLAG_VIDEO | \
+ GST_PLAY_FLAG_NATIVE_VIDEO | \
+ GST_PLAY_FLAG_AUDIO
+#endif
+
+enum TestState {
+ STATE_INITIAL,
+ STATE_PREROLL_1,
+ STATE_2_SECOND,
+ STATE_4_SECOND,
+ STATE_6_SECOND,
+ STATE_3_SECOND,
+ STATE_PAUSED,
+ STATE_NEAR_END,
+ STATE_EOS,
+ STATE_FAILURE
+};
+
+static GMainLoop *loop = NULL;
+static enum TestState state = STATE_INITIAL;
+static guint64 position = 0;
+static gboolean reached_eos = FALSE;
+
+static void run_test (GstElement * bin);
+
+static gboolean
+check_position (GstElement * bin)
+{
+ gint64 p;
+
+ if (!gst_element_query_position (bin, GST_FORMAT_TIME, &p)) {
+ g_print ("Could not get position");
+ state = STATE_FAILURE;
+ } else if (p < position) {
+ g_print ("Expected to be at %" GST_TIME_FORMAT " but is at %"
+ GST_TIME_FORMAT "\n", GST_TIME_ARGS (position), GST_TIME_ARGS (p));
+ state = STATE_FAILURE;
+ }
+
+ return state != STATE_FAILURE;
+}
+
+static gboolean
+check_position_timeout (gpointer user_data)
+{
+ GstElement *bin = user_data;
+ check_position (bin);
+ run_test (bin);
+ return FALSE;
+}
+
+static void
+do_seek (GstElement * bin, GstClockTime second)
+{
+ if (second == -1) {
+ gint64 duration;
+ if (!gst_element_query_duration (bin, GST_FORMAT_TIME, &duration)) {
+ g_print ("Could not get duration");
+ state = STATE_FAILURE;
+ return;
+ }
+ position = duration - GST_SECOND;
+ } else {
+ position = second * GST_SECOND;
+ }
+
+ if (!gst_element_seek_simple (bin, GST_FORMAT_TIME,
+ GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, position)) {
+ g_print ("Failed to seek at %" GST_TIME_FORMAT "\n",
+ GST_TIME_ARGS (position));
+ state = STATE_FAILURE;
+ }
+}
+
+static void
+run_test (GstElement *bin)
+{
+ switch (state) {
+ case STATE_INITIAL:
+ g_print ("Starting play_back\n");
+ gst_element_set_state (bin, GST_STATE_PLAYING);
+ state++;
+ break;
+ case STATE_PREROLL_1:
+ g_print ("Playback ready, running for 2s\n");
+ position = 2 * GST_SECOND;
+ g_timeout_add (2300, check_position_timeout, bin);
+ state++;
+ break;
+ case STATE_2_SECOND:
+ g_print ("Seeking from 2 seconds to 4 seconds\n");
+ state++;
+ do_seek (bin, 4);
+ break;
+ case STATE_4_SECOND:
+ if (check_position (bin)) {
+ g_print ("Seeking from 4 second to 6 seconds\n");
+ state++;
+ do_seek (bin, 6);
+ }
+ break;
+ case STATE_6_SECOND:
+ if (check_position (bin)) {
+ g_print ("Seeking from 6 second to 3 seconds\n");
+ state++;
+ do_seek (bin, 3);
+ }
+ break;
+ case STATE_3_SECOND:
+ if (check_position (bin)) {
+ g_print ("Pausing at 3 second\n");
+ state++;
+ if (gst_element_set_state (bin, GST_STATE_PAUSED)
+ != GST_STATE_CHANGE_ASYNC) {
+ g_print ("Failed to pause pipeline\n");
+ state = STATE_FAILURE;
+ }
+ }
+ break;
+ case STATE_PAUSED:
+ if (check_position (bin)) {
+ g_print ("Seeking near end\n");
+ state++;
+ do_seek (bin, -1);
+ }
+ break;
+ case STATE_NEAR_END:
+ if (check_position (bin)) {
+ g_print ("Playing till EOS\n");
+ state++;
+ if (gst_element_set_state (bin, GST_STATE_PLAYING)
+ != GST_STATE_CHANGE_SUCCESS) {
+ g_print ("Failed to put pipeline into playing again\n");
+ state = STATE_FAILURE;
+ } else {
+ /* It's not uncommon that EOS occures slightly sooner */
+ position += 1 * GST_SECOND - 300 * GST_MSECOND;
+ g_timeout_add (1300, check_position_timeout, bin);
+ }
+ }
+ break;
+ case STATE_EOS: {
+ if (!reached_eos) {
+ g_print ("Did not receive EOS message");
+ state = STATE_FAILURE;
+ } else {
+ GstMessage *m = gst_message_new_application (GST_OBJECT (bin), NULL);
+ gst_element_post_message (bin, m);
+ g_print ("Success\n");
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (state == STATE_FAILURE)
+ exit (-1);
+}
+
+static gboolean
+handle_message (GstBus *bus, GstMessage * message, gpointer user_data)
+{
+ GstElement * bin = user_data;
+
+ switch (message->type) {
+ case GST_MESSAGE_EOS: {
+ reached_eos = TRUE;
+ break;
+ }
+ case GST_MESSAGE_ERROR: {
+ GError *gerror;
+ gchar *debug;
+
+ gst_message_parse_error (message, &gerror, &debug);
+ gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+ g_error_free (gerror);
+ g_free (debug);
+ exit (-1);
+ break;
+ }
+ case GST_MESSAGE_WARNING: {
+ GError *gerror;
+ gchar *debug;
+
+ gst_message_parse_warning (message, &gerror, &debug);
+ gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
+ g_error_free (gerror);
+ g_free (debug);
+ break;
+ }
+ case GST_MESSAGE_APPLICATION: {
+ g_main_loop_quit (loop);
+ break;
+ }
+ case GST_MESSAGE_LATENCY: {
+ gst_bin_recalculate_latency (GST_BIN (bin));
+ break;
+ }
+ case GST_MESSAGE_ASYNC_DONE: {
+ if (message->src == (GstObject *) bin)
+ run_test (bin);
+ break;
+ }
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+typedef enum {
+ GST_PLAY_FLAG_VIDEO = (1 << 0),
+ GST_PLAY_FLAG_AUDIO = (1 << 1),
+ GST_PLAY_FLAG_TEXT = (1 << 2),
+ GST_PLAY_FLAG_VIS = (1 << 3),
+ GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
+ GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
+ GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6),
+ GST_PLAY_FLAG_DOWNLOAD = (1 << 7),
+ GST_PLAY_FLAG_BUFFERING = (1 << 8),
+ GST_PLAY_FLAG_DEINTERLACE = (1 << 9),
+ GST_PLAY_FLAG_SOFT_COLORBALANCE = (1 << 10)
+} GstPlayFlags;
+
+int
+main (int argc, char *argv[])
+{
+ GstElement *bin, *sink;
+ GstBus *bus;
+ GError *error = NULL;
+
+ gst_init (&argc, &argv);
+
+ if (argc != 2) {
+ g_print ("usage: %s <uri to play>\n", argv[0]);
+ exit (-1);
+ }
+
+ g_print ("Constructing pipeline\n");
+
+ sink = gst_parse_bin_from_description (VIDEO_SINK, TRUE, &error);
+ if (!sink) {
+ g_print ("Could not create video sink: %s\n", error->message);
+ g_error_free (error);
+ exit (-1);
+ }
+
+ bin = gst_element_factory_make ("playbin", NULL);
+ g_assert (bin);
+ g_object_set (G_OBJECT (bin), "uri", argv[1],
+ "video-sink", sink,
+ "flags", PLAY_FLAGS,
+ NULL);
+
+ bus = gst_element_get_bus (bin);
+ gst_bus_add_watch (bus, handle_message, bin);
+ g_object_unref (bus);
+
+ run_test (bin);
+
+ loop = g_main_loop_new (NULL, FALSE);
+ g_main_loop_run (loop);
+
+ /* stop the bin */
+ gst_element_set_state (bin, GST_STATE_NULL);
+
+ /* Unreffing the bin will clean up all its children too */
+ gst_object_unref (bin);
+ g_main_loop_unref (loop);
+
+ return 0;
+}