Commit c2b0fd9c authored by Brendan Long's avatar Brendan Long

Merge pull request #1 from cablelabs/delete_playspeeds

Moved the logic from playspeeds-test.c into general-test.c hence deletin...
parents 88ba6b28 556b7c1b
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = general playspeeds
bin_PROGRAMS = general
general_SOURCES = src/general-test.c
general_CFLAGS = $(GST_CFLAGS)
general_LDADD = $(GST_LIBS) -lm
general_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
general_LIBTOOLFLAGS = --tag=disable-static
playspeeds_SOURCES = src/playspeeds-test.c
playspeeds_CFLAGS = $(GST_CFLAGS)
playspeeds_LDADD = $(GST_LIBS)
playspeeds_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
playspeeds_LIBTOOLFLAGS = --tag=disable-static
......@@ -55,6 +55,8 @@ static gboolean g_zero_position = FALSE;
static gboolean g_positions = FALSE;
static gboolean g_states = FALSE;
static gboolean g_test_uri_switch = FALSE;
static gboolean g_playspeeds = FALSE;
static int g_eos_max_cnt = 1;
static int g_eos_cnt = 0;
//static const guint64 NANOS_PER_SECOND = 1000000000L;
......@@ -86,6 +88,7 @@ typedef struct _CustomData {
gint64 duration; /* How long does this media last, in nanoseconds */
gdouble rate; /* current playspeed */
GstElement *pipeline_2; /* Optional second pipeline element */
GMainLoop *loop; /* Main loop for testing with keyboard input */
} CustomData;
// Local method declarations
......@@ -112,19 +115,24 @@ static gboolean perform_test_position(CustomData* data);
static gboolean perform_test_query(CustomData* data, gint64* position, GstFormat format);
static gboolean perform_test_seek(CustomData* data, gint64 position, GstFormat format, gfloat rate);
static gboolean perform_test_states(CustomData* data);
static gboolean perform_test_playspeeds(CustomData* data);
static gboolean set_pipeline_state(GstElement* pipeline, GstState desired_state, gint timeoutSecs);
static gboolean set_new_uri(CustomData* data);
static void handle_message (CustomData *data, GstMessage *msg);
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data);
static gboolean send_seek_event (CustomData *data);
static void log_bin_elements(GstBin* bin);
static GstElement* log_element_links(GstElement* elem);
/**
* Test program for playspeed testing
* Test program for testing gstreamer playback
*/
int main(int argc, char *argv[])
{
CustomData data;
data.playing = FALSE;
data.terminate = FALSE;
......@@ -477,6 +485,11 @@ static gboolean process_cmd_line_args(int argc, char *argv[])
g_states = TRUE;
g_print("Set to test state changes\n");
}
else if (strstr(argv[i], "playspeeds") != NULL)
{
g_playspeeds = TRUE;
g_print("Set to change playspeeds from keyboard\n");
}
else
{
g_printerr("Invalid option: %s\n", argv[i]);
......@@ -492,6 +505,7 @@ static gboolean process_cmd_line_args(int argc, char *argv[])
g_printerr("\t manual_uri_bin \t\t build manual pipeline using uri decode bin\n");
g_printerr("\t manual_decode_bin \t\t build manual pipeline using decode bin\n");
g_printerr("\t manual_elements \t\t build manual pipeline using decode elements\n");
g_printerr("\t playspeeds \t\t allow changing of playspeeds from keyboard\n");
g_printerr("\t position \t\t test positioning of seeks\n");
g_printerr("\t query \t\t perform seek using current position + 10\n");
g_printerr("\t rate=y \t\t where y is desired rate\n");
......@@ -1348,6 +1362,10 @@ static void perform_test(CustomData* data)
{
perform_test_states(data);
}
else if (g_playspeeds)
{
perform_test_playspeeds(data);
}
// Wait until error or EOS
bus = gst_element_get_bus (data->pipeline);
......@@ -1630,6 +1648,136 @@ static gboolean perform_test_seek(CustomData* data, gint64 start_position, GstFo
return TRUE;
}
static gboolean perform_test_playspeeds(CustomData* data)
{
GIOChannel *io_stdin;
g_print("%s - Performing position changes at 2, 1, 3, and 1 mins\n", __FUNCTION__);
/* Print usage map */
g_print (
"USAGE: Choose one of the following options, then press enter:\n"
" 'P' to toggle between PAUSE and PLAY\n"
" 'S' to increase playback speed, 's' to decrease playback speed\n"
" 'D' to toggle playback direction\n"
" 'N' to move to next frame (in the current direction, better in PAUSE)\n"
" 'Q' to quit\n");
/* Add a keyboard watch so we get notified of keystrokes */
g_print ("Setting up keyboard watch\n");
#ifdef _WIN32
io_stdin = g_io_channel_win32_new_fd (fileno (stdin));
#else
io_stdin = g_io_channel_unix_new (fileno (stdin));
#endif
g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, data);
g_print ("Setting rate to 1.0\n");
data->rate = 1.0;
// Create a GLib Main Loop and set it to run
g_print ("Entering main loop\n");
data->loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (data->loop);
/* Free resources */
g_print ("Exiting\n");
g_main_loop_unref (data->loop);
g_io_channel_unref (io_stdin);
return TRUE;
}
/* Process keyboard input */
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {
gchar *str = NULL;
g_print ("Called to handle keyboard input\n");
if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) {
return TRUE;
}
switch (g_ascii_tolower (str[0])) {
case 'p':
data->playing = !data->playing;
g_print ("Setting state to %s\n", data->playing ? "PLAYING" : "PAUSE");
gst_element_set_state (data->pipeline, data->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED);
break;
case 's':
g_print ("Current rate: %2.0f\n", data->rate);
if (g_ascii_isupper (str[0])) {
data->rate *= 2.0;
} else {
data->rate /= 2.0;
}
g_print ("Adjusting rate to: %2.0f\n", data->rate);
if (send_seek_event (data)) {
g_print ("Rate changed to: %2.0f\n", data->rate);
} else {
g_print ("Problems changing rate to: %2.0f\n", data->rate);
return FALSE;
}
break;
case 'd':
data->rate *= -1.0;
g_print ("Adjusting rate to: %2.0f\n", data->rate);
send_seek_event (data);
break;
case 'n':
gst_element_send_event (data->pipeline,
gst_event_new_step (GST_FORMAT_BUFFERS, 1, data->rate, TRUE, FALSE));
g_print ("Stepping one frame\n");
break;
case 'q':
g_print ("Quitting\n");
g_main_loop_quit (data->loop);
break;
default:
break;
}
g_free (str);
return TRUE;
}
static gboolean send_seek_event (CustomData *data) {
gint64 position;
GstFormat format = GST_FORMAT_TIME;
g_print ("Sending Seek Event\n");
if (!gst_element_query_position(data->pipeline, format, &position))
{
g_printerr("%s - Unable to retrieve current position.\n",
__FUNCTION__);
return FALSE;
}
/* Create the seek event */
if (!gst_element_seek (data->pipeline, data->rate,
format, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, position,
GST_SEEK_TYPE_SET, -1))
//GST_SEEK_TYPE_NONE, 0))
{
g_printerr("%s - Problems seeking.\n", __FUNCTION__);
return FALSE;
}
else
{
printf("%s - seek was successful\n", __FUNCTION__);
}
return TRUE;
}
static gboolean set_pipeline_state(GstElement* pipeline, GstState desired_state, gint timeoutSecs)
{
GstStateChangeReturn ret = gst_element_set_state(pipeline, desired_state);
......
/* Copyright (C) 2013 Cable Television Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include <gst/gst.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib/gprintf.h>
typedef struct _CustomData {
GstElement *pipeline;
GstElement *video_sink;
GMainLoop *loop;
gboolean playing; /* Playing or Paused */
gdouble rate; /* Current playback rate (can be negative) */
int rrid; /* Recording id if using OCAP RI Server */
char host[256]; /* HTTP Server Address */
char uri[256]; /* URI to requested content */
gboolean use_file; /* local file rather than http request */
char file_name[256];
char* file_path;
} CustomData;
static gchar* TEST_FILE_URL_PREFIX_ENV = "TEST_FILE_URL_PREFIX";
static gboolean process_cmd_line_args(CustomData *data, int argc, char *argv[]);
static gboolean launch_playbin_pipeline(CustomData* data);
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data);
static gboolean send_seek_event (CustomData *data);
int main(int argc, char *argv[]) {
CustomData data;
GstStateChangeReturn ret;
GIOChannel *io_stdin;
/* Initialize GStreamer */
gst_init (&argc, &argv);
/* Initialize our data structure */
memset (&data, 0, sizeof (data));
if (!process_cmd_line_args(&data, argc, argv)) {
g_printerr("Exit due to problems with cmd line args\n");
return -1;
}
/* Print usage map */
g_print (
"USAGE: Choose one of the following options, then press enter:\n"
" 'P' to toggle between PAUSE and PLAY\n"
" 'S' to increase playback speed, 's' to decrease playback speed\n"
" 'D' to toggle playback direction\n"
" 'N' to move to next frame (in the current direction, better in PAUSE)\n"
" 'Q' to quit\n");
/* Build the pipeline */
g_print ("Launching pipeline\n");
if (!launch_playbin_pipeline(&data)) {
g_printerr("Exit due to problems creating pipeline\n");
return -1;
}
/* Add a keyboard watch so we get notified of keystrokes */
g_print ("Setting up keyboard watch\n");
#ifdef _WIN32
io_stdin = g_io_channel_win32_new_fd (fileno (stdin));
#else
io_stdin = g_io_channel_unix_new (fileno (stdin));
#endif
g_io_add_watch (io_stdin, G_IO_IN, (GIOFunc)handle_keyboard, &data);
/* Start playing */
g_print ("Starting pipeline\n");
ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
if (ret == GST_STATE_CHANGE_FAILURE) {
g_printerr ("Unable to set the pipeline to the playing state.\n");
gst_object_unref (data.pipeline);
return -1;
}
data.playing = TRUE;
data.rate = 1.0;
/* Create a GLib Main Loop and set it to run */
g_print ("Entering main loop\n");
data.loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (data.loop);
/* Free resources */
g_print ("Exiting\n");
g_main_loop_unref (data.loop);
g_io_channel_unref (io_stdin);
gst_element_set_state (data.pipeline, GST_STATE_NULL);
if (data.video_sink != NULL)
gst_object_unref (data.video_sink);
gst_object_unref (data.pipeline);
return 0;
}
/**
* Handle command line args
*/
static gboolean process_cmd_line_args(CustomData* data, int argc, char *argv[]) {
int i = 0;
// Setup default values
strcpy(data->host, "192.168.2.2");
data->uri[0] = '\0';
data->file_name[0] = '\0';
data->file_path = NULL;
for (i = 1; i < argc; i++) {
if (strstr(argv[i], "uri=") != NULL) {
if (sscanf(argv[i], "uri=%s\n", &data->uri[0]) != 1) {
g_printerr("Invalid uri arg specified: %s\n", argv[i]);
return FALSE;
} else {
g_print("Set requested URI to %s\n", data->uri);
}
} else if (strstr(argv[i], "rrid=") != NULL) {
if (sscanf(argv[i], "rrid=%d", &data->rrid) != 1) {
g_printerr("Invalid rrid specified: %s\n", argv[i]);
return FALSE;
} else {
g_print("Set requested rrid to %d\n", data->rrid);
}
} else if (strstr(argv[i], "host=") != NULL) {
if (sscanf(argv[i], "host=%s\n", &data->host[0]) != 1) {
g_printerr("Invalid host arg specified: %s\n", argv[i]);
return FALSE;
} else {
g_print("Set requested host ip to %s\n", data->host);
}
} else if (strstr(argv[i], "file=") != NULL) {
if (sscanf(argv[i], "file=%s\n", &data->file_name[0]) != 1) {
g_printerr("Invalid file name specified: %s\n", argv[i]);
return FALSE;
} else {
data->use_file = TRUE;
g_print("Test using local file %s rather than URI\n", data->file_name);
}
} else {
g_printerr("Invalid option: %s\n", argv[i]);
g_printerr("Usage:\n");
g_printerr("\t file=name \t\twhere name indicates file name using path from env var\n");
g_printerr("\t host=ip \t\t addr of server\n");
g_printerr("\t rrid=i \t\t where i is cds recording id\n");
g_printerr("\t uri=l \t\t where l is uri of desired content\n");
return FALSE;
}
}
return TRUE;
}
/**
* Create playbin pipeline
*/
static gboolean launch_playbin_pipeline(CustomData* data)
{
char launchLine[256];
char* line1 = "playbin flags=0x3 uri=";
if (!data->use_file) {
g_print("Initializing URI\n");
// Build default URI if one was not specified
if (data->uri[0] == '\0') {
char* line2 = "http://";
char* line3 = ":8008/ocaphn/recording?rrid=";
char* line4 = "&profile=MPEG_TS_SD_NA_ISO&mime=video/mpeg";
sprintf(data->uri, "%s%s%s%d%s", line2, data->host, line3, data->rrid, line4);
}
sprintf(launchLine, "%s%s", line1, data->uri);
} else {
g_print("Initializing File path\n");
data->file_path = getenv(TEST_FILE_URL_PREFIX_ENV);
if (data->file_path == NULL) {
g_printerr ("Could not get env var %s value\n", TEST_FILE_URL_PREFIX_ENV);
return FALSE;
} else {
sprintf(launchLine, "%s%s%s", line1, data->file_path, data->file_name);
}
}
g_print("Starting up playbin using line: %s\n", launchLine);
data->pipeline = gst_parse_launch(launchLine, NULL);
return TRUE;
}
/* Send seek event to change rate */
static gboolean send_seek_event (CustomData *data) {
gint64 position;
GstFormat format = GST_FORMAT_TIME;
g_print ("Sending Seek Event\n");
if (!gst_element_query_position(data->pipeline, format, &position))
{
g_printerr("%s - Unable to retrieve current position.\n",
__FUNCTION__);
return FALSE;
}
/* Create the seek event */
if (!gst_element_seek (data->pipeline, data->rate,
format, GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_SET, position,
GST_SEEK_TYPE_SET, -1))
//GST_SEEK_TYPE_NONE, 0))
{
g_printerr("%s - Problems seeking.\n", __FUNCTION__);
return FALSE;
}
else
{
g_printf("%s - seek was successful\n", __FUNCTION__);
}
return TRUE;
}
/* Process keyboard input */
static gboolean handle_keyboard (GIOChannel *source, GIOCondition cond, CustomData *data) {
gchar *str = NULL;
if (g_io_channel_read_line (source, &str, NULL, NULL, NULL) != G_IO_STATUS_NORMAL) {
return TRUE;
}
switch (g_ascii_tolower (str[0])) {
case 'p':
data->playing = !data->playing;
g_print ("Setting state to %s\n", data->playing ? "PLAYING" : "PAUSE");
gst_element_set_state (data->pipeline, data->playing ? GST_STATE_PLAYING : GST_STATE_PAUSED);
break;
case 's':
g_print ("Current rate: %2.0f\n", data->rate);
if (g_ascii_isupper (str[0])) {
data->rate *= 2.0;
} else {
data->rate /= 2.0;
}
g_print ("Adjusting rate to: %2.0f\n", data->rate);
if (send_seek_event (data)) {
g_print ("Rate changed to: %2.0f\n", data->rate);
} else {
g_print ("Problems changing rate to: %2.0f\n", data->rate);
return FALSE;
}
break;
case 'd':
data->rate *= -1.0;
g_print ("Adjusting rate to: %2.0f\n", data->rate);
send_seek_event (data);
break;
case 'n':
if (data->video_sink == NULL) {
/* If we have not done so, obtain the sink through which we will send the step events */
g_object_get (data->pipeline, "video-sink", &data->video_sink, NULL);
}
gst_element_send_event (data->video_sink,
gst_event_new_step (GST_FORMAT_BUFFERS, 1, data->rate, TRUE, FALSE));
g_print ("Stepping one frame\n");
break;
case 'q':
g_print ("Quitting\n");
g_main_loop_quit (data->loop);
break;
default:
break;
}
g_free (str);
return TRUE;
}
#!/bin/sh
#rm ./tmp/*.dot
#
TEST_FILE_URL_PREFIX=file:///home/landerson/gst/git/gst-plugins-cl/test/videos/
TEST_FILE_URL_PREFIX=file:///home/landerson/gst/git/gst-plugins-cablelabs-ruih/test/videos/
export TEST_FILE_URL_PREFIX
#
#RUIH_GST_DTCP_DISABLE=true
#export RUIH_GST_DTCP_DISABLE
#
RUIH_GST_DTCP_KEY_STORAGE=/media/RUIH_RI_2/test_keys
RUIH_GST_DTCP_DLL=/media/RUIH_RI_2/dtcp_greg/dtcpip_test_nodebug.so
#RUIH_GST_DTCP_DLL=/media/RUIH_RI_2/dtcp_greg/dtcpip_test_debug.so
#
#RUIH_GST_DTCP_KEY_STORAGE=/media/RUIH-RI-3/test_keys
#RUIH_GST_DTCP_DLL=/media/RUIH-RI-3/dtcpip_v1.1_Linux_test.so
#
#RUIH_GST_DTCP_KEY_STORAGE=/home/landerson/RUIHRI/dtcp/test_keys
#RUIH_GST_DTCP_DLL=/home/landerson/RUIHRI/dtcp/dtcpip_v1.1_Linux_test.so
#
RUIH_GST_DTCP_KEY_STORAGE=/home/landerson/RUIHRI/dtcp/test_keys
RUIH_GST_DTCP_DLL=/home/landerson/RUIHRI/dtcp/dtcpip_mock.so
#
export RUIH_GST_DTCP_KEY_STORAGE
export RUIH_GST_DTCP_DLL
#
GST_DEBUG=*:1,dlnasrc:4,souphttpsrc:4,mpeg2dec:3,tsdemux:4,mpegtsbase:4,mpegtspacketizer:4,dtcpip:5,basesrc:4,GST_STATES:1
GST_DEBUG=*:1,dlnasrc:4,souphttpsrc:4,tsdemux:3,basesrc:3,dtcpip:3
#uridecodebin:3,filesrc:5,dtcpip:4,playbin:3,passthru:1,\
#basesrc:3,pushsrc:5,baseparse:1,task:1,queue2:2,multiqueue:2,bin:1,\
#mpegtsdemux:4,xvimagesink:3,fakesink:5,structure:1,\
......@@ -35,13 +34,15 @@ export GST_DEBUG_NO_COLOR
# This doesn't seem to work here - need to export in terminal window using ./tmp as value
#export GST_DEBUG_DUMP_DOT_DIR=tmp
#
#gst-git ../general host=192.168.0.106 rrid=35 wait=1 rate=2 dot
#gst-git ../general file=clock.mpg two
gst-git ../general uri=http://192.168.2.16:818/tests/test.m2t auto_audio wait=5 states
#gst-git ../general host=192.168.2.17 rrid=5 dtcp wait=15 position
gst-git ../general host=192.168.2.17 rrid=4 playspeeds
#gst-git ../general uri=http://192.168.2.17:55927/mal/I/AL10/60/O-MP2TS_SN_I-1.mpeg
#gst-git ../general uri=http://192.168.2.17:819/tests/test.m2t wait=10 position
#gst-git ../general file=clock.mpg dot
#gst-git ../general uri=http://192.168.2.16:818/tests/test.m2t auto_audio wait=5 states
#gst-git ../general uri=http://10.36.32.195/fxi/Ultimate-Stream-1280x720-5Mb-mpeg2v-ac3_0100_CC_Trim.ts
#gst-git ../general uri=http://192.168.2.16:8895/resource/1/MEDIA_ITEM/MPEG_TS_SD_KO_ISO-0/ORIGINAL
#gst-git ../general uri=http://dveo.com/downloads/TS-sample-files/San_Diego_Clip.ts
#gst-git ../general uri=http://192.168.0.106:60656/mal/I/AM2/1.mpeg
#gst-git ../general uri="http://192.168.2.16:8008/ocaphn/service?ocaploc=0x45a&profile=MPEG_TS_SD_NA_ISO&mime=video/mpeg"
#
# Bunch of possible cmd line args to include
......
#!/bin/sh
#
TEST_FILE_URL_PREFIX=file:///home/landerson/gst/git/gst-plugins-cl/test/videos/
export TEST_FILE_URL_PREFIX
#
GST_DEBUG=*:1,dlnasrc:5,souphttpsrc:4,basesrc:4,playbin:4,GST_EVENT:2,tsdemux:4,mpegtsbase:4,playsink:3
#GST_EVENT:3,playbin:3,basesrc:3,tsdemux:4,mpegtsbase:4,mpegtspacketizer:4,GST_PADS:1
#uridecodebin:3,filesrc:5,dtcpip:4,playbin:3,passthru:1,\
#basesrc:3,pushsrc:5,baseparse:1,task:1,queue2:2,multiqueue:2,bin:1,\
#mpegtsdemux:4,xvimagesink:3,fakesink:5,structure:1,\
#GST_REGISTRY:1,GST_EVENT:3,GST_SEGMENT:5,GST_ELEMENT_FACTORY:1,GST_ELEMENT_PAD:1,\
#GST_PADS:2,GST_STATES:1,GST_BUFFER:1,GST_BUS:1,GST_REFCOUNTING:1,GST_TYPEFIND:1,\
#GST_PLUGIN_LOADING:1,GST_MEMORY:1
export GST_DEBUG
#
GST_DEBUG_NO_COLOR=1
export GST_DEBUG_NO_COLOR
#
gst-git ../playspeeds file=clock.mpg
#gst-git ../playspeeds host=192.168.2.16 rrid=35
#gst-git ../playspeeds uri=http://192.168.0.106:60753/mal/I/AL10/51.mpeg
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment