Made sanity check more flexible.

Added V4L2 player program - it will be put here until I can find a better place to put it.

Will now kill the xvfb process.

BUG=
TEST=

Review URL: https://webrtc-codereview.appspot.com/456004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1932 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
phoglund@webrtc.org
2012-03-23 14:59:56 +00:00
parent 196e491c46
commit 22bde08fb8
4 changed files with 160 additions and 5 deletions

View File

@@ -0,0 +1,2 @@
all:
gcc -Wall v4l2_file_player.c -o v4l2_file_player $(shell pkg-config --cflags --libs gstreamer-0.10)

View File

@@ -0,0 +1,10 @@
This is a simple program which can feed raw video data into a V4L2 sink, such as
the v4l2loopback driver. See the .c file for implementation notes and how to run
the program.
You will require the gstreamer developer package and the "bad" plugin set for
gstreamer. The easiest way to get this is to run
sudo apt-get install gstreamer0.10-plugins-bad libgstreamer0.10-dev
Then just build using make in this directory.

View File

@@ -0,0 +1,127 @@
/**
* WebRTC Internal Tooling - Looping V4L2 player
* Author: Patrik Höglund (phoglund@webrtc.org)
*
* This file implements a basic raw video file player which loops its input
* file indefinitely. It is intended to be used with the v4l2loopback driver in
* order to play the contents of a file as if it were a webcam. Therefore, this
* program will write to a v4l2loopback device, say /dev/video1, and the driver
* will then reflect the data unmodified to any reading processes.
*
* This program basically does the same thing as
* gst-launch-0.10 -v filesrc location=resources/foreman_cif.yuv ! \
* videoparse width=352 height=288 ! v4l2sink device=/dev/video1
*
* , but with looping. Looping is unfortunately impossible to do with a regular
* gstreamer pipeline, hence the existence of this program.
*
* It can be run something like this:
* v4l2_file_player foreman_cif_short.yuv 352 288 /dev/video1 >& /dev/null
*
* The program might print warnings about failed ioctls (for instance for
* VIDIOC_G_FMT), but that doesn't seem to be a problem.
*
* To test, you can run for instance mplayer tv:// -tv device=/dev/video1 and
* verify that you see your video playing repeatedly.
*
* This code is based off the hello world example in the gstreamer manual.
* You can find the original code in chapter 10, "Your First Application":
* http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/
*/
#include <gst/gst.h>
#include <glib.h>
typedef struct {
GMainLoop* main_loop;
GstElement* pipeline;
} main_loop_and_pipeline_t;
static gboolean bus_call(GstBus *bus, GstMessage *msg, gpointer data) {
main_loop_and_pipeline_t *main_loop_and_pipeline =
(main_loop_and_pipeline_t*)data;
GMainLoop *loop = main_loop_and_pipeline->main_loop;
GstElement *pipeline = main_loop_and_pipeline->pipeline;
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:
/* Reached end of input video - restart */
gst_element_set_state(pipeline, GST_STATE_READY);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
break;
case GST_MESSAGE_ERROR: {
gchar *debug;
GError *error;
gst_message_parse_error(msg, &error, &debug);
g_free(debug);
g_printerr("Error: %s\n", error->message);
g_error_free(error);
g_main_loop_quit(loop);
break;
}
default:
break;
}
return TRUE;
}
int main(int argc, char *argv[]) {
gst_init(&argc, &argv);
GMainLoop *main_loop = g_main_loop_new(NULL, FALSE);
/* Check input arguments */
if (argc != 5 || atoi(argv[2]) == 0 || atoi(argv[3]) == 0) {
g_printerr("Usage: %s <filename> <width> <height> <device>\n\n", argv[0]);
g_printerr("Arguments:\n");
g_printerr(" filename: Path to the video file.\n");
g_printerr(" width: Video width.\n");
g_printerr(" height: Video height.\n");
g_printerr(" device: Device to write to (like /dev/video1).\n");
return -1;
}
/* Create gstreamer pipeline elements. */
GstElement *pipeline = gst_pipeline_new("looping-video-player");
GstElement *source = gst_element_factory_make("filesrc", "file-source");
GstElement *parse = gst_element_factory_make("videoparse", "video-parse");
GstElement *v4l2_sink = gst_element_factory_make("v4l2sink", "v4l2-sink");
if (!pipeline || !source || !parse || !v4l2_sink) {
g_printerr("One GST element could not be created. Exiting.\n");
return -1;
}
/* Set up input parameters. */
g_object_set(G_OBJECT (source), "location", argv[1], NULL);
g_object_set(G_OBJECT (parse), "width", atoi(argv[2]), NULL);
g_object_set(G_OBJECT (parse), "height", atoi(argv[3]), NULL);
g_object_set(G_OBJECT (v4l2_sink), "device", argv[4], NULL);
/* Add a callback to we can react to end-of-stream and errors. */
main_loop_and_pipeline_t main_loop_and_pipeline;
main_loop_and_pipeline.main_loop = main_loop;
main_loop_and_pipeline.pipeline = pipeline;
GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE (pipeline));
gst_bus_add_watch(bus, bus_call, &main_loop_and_pipeline);
gst_object_unref(bus);
/* Assemble the pipeline. */
gst_bin_add_many(GST_BIN (pipeline), source, parse, v4l2_sink, NULL);
gst_element_link(source, parse);
gst_element_link(parse, v4l2_sink);
/* Start playing. */
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_main_loop_run(main_loop);
/* Never reached. */
return 0;
}

View File

@@ -7,8 +7,10 @@
# capture screenshots from inside the virtual environment. If you don't what
# that is, never mind and run this script without arguments.
#
# Pass the argument --chrome-binary <binary> to provide a custom chrome binary.
#
# Method:
# - Start peerconnection server.
# - Start peerconnection_server.
# - Start serving webrtc_test.html off a local web server.
# - Start 2 browser tabs.
# - Tab 1 connects to the server.
@@ -26,10 +28,22 @@ fi
# Tweakable parameters:
URLBASE=localhost:3000
CHROME_BINARY=google-chrome
CALLEE="$URLBASE/webrtc_test.html?name=test1&autoconnect=yes"
CALLER="$URLBASE/webrtc_test.html?name=test2&autocall=test1"
FLAGS="--enable-media-stream"
CHROME_BINARY=google-chrome
# Parse parameters:
while (( "$#" )); do
if [ "$1" == "--xvfb-and-screenshots" ]; then
RUN_WITH_XVFB_AND_SCREENSHOTS=1
fi
if [ "$1" == "--chrome-binary" ]; then
shift
CHROME_BINARY=$1
fi
shift
done
run_chrome_for_user() {
# Run the binary straight up and proceed with cleanup when the user closes
@@ -41,6 +55,7 @@ run_chrome_in_xvfb_with_screenshots() {
# Run chrome in a virtual window environment and capture screenshots.
# It will run for 30 seconds and then exit.
Xvfb :17 -screen 0 1024x768x24 &
XVFB=$!
DISPLAY=:17 ${CHROME_BINARY} $CALLEE $CALLER $FLAGS --user-data-dir=temp/user1 &
CHROME=$!
@@ -52,6 +67,7 @@ run_chrome_in_xvfb_with_screenshots() {
sleep 5
done
kill $CHROME || echo "No Chrome process."
kill $XVFB || echo "No XVFB process."
}
PROJECT_ROOT=../..
@@ -79,10 +95,10 @@ SERVER=$!
echo "Started server as $SERVER"
# Launch a browser with two tabs:
if [ "$1" == "--xvfb-and-screenshots" ]; then
run_chrome_in_xvfb_with_screenshots
else
if [ -z "$RUN_WITH_XVFB_AND_SCREENSHOTS" ]; then
run_chrome_for_user
else
run_chrome_in_xvfb_with_screenshots
fi
echo "Test finished, cleaning up"