Adding mod_gstreamer
Add gstreamer to environment variables.
This commit is contained in:
parent
1c4a48595c
commit
569de5382e
|
@ -1,6 +1,6 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27130.2010
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.33502.453
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Codecs", "Codecs", "{F881ADA2-2F1A-4046-9FEB-191D9422D781}"
|
||||
EndProject
|
||||
|
@ -554,6 +554,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_core_db", "test
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_switch_ivr_originate", "tests\unit\test_switch_ivr_originate.2017.vcxproj", "{69A7464A-9B0D-4804-A108-835229DACF58}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mod_gstreamer", "src\mod\endpoints\mod_gstreamer\mod_gstreamer.vcxproj", "{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
All|Win32 = All|Win32
|
||||
|
@ -2516,6 +2518,18 @@ Global
|
|||
{69A7464A-9B0D-4804-A108-835229DACF58}.Release|Win32.Build.0 = Release|Win32
|
||||
{69A7464A-9B0D-4804-A108-835229DACF58}.Release|x64.ActiveCfg = Release|x64
|
||||
{69A7464A-9B0D-4804-A108-835229DACF58}.Release|x64.Build.0 = Release|x64
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.All|Win32.ActiveCfg = Debug|Win32
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.All|Win32.Build.0 = Debug|Win32
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.All|x64.ActiveCfg = Debug|x64
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.All|x64.Build.0 = Debug|x64
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Debug|x64.Build.0 = Debug|x64
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Release|Win32.Build.0 = Release|Win32
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Release|x64.ActiveCfg = Release|x64
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -2714,6 +2728,7 @@ Global
|
|||
{0B612F84-7533-4DEC-AEDD-5C9CBCF15EAC} = {31C2761D-20E0-4BF8-98B9-E32F0D8DD6E1}
|
||||
{580675D7-C1C9-4197-AAC5-00F64FAFDE78} = {9388C266-C3FC-468A-92EF-0CBC35941412}
|
||||
{69A7464A-9B0D-4804-A108-835229DACF58} = {9388C266-C3FC-468A-92EF-0CBC35941412}
|
||||
{5AC15CAA-B153-4B45-804A-0CFDF6FA3422} = {9460B5F1-0A95-41C4-BEB7-9C2C96459A7C}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {09840DE7-9208-45AA-9667-1A71EE93BD1E}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
<configuration name="gstreamer.conf" description="Gstreamer module">
|
||||
<settings>
|
||||
<!--file to play when calls are on hold-->
|
||||
<param name="hold-file" value="$${hold_music}"/>
|
||||
<!--Default dialplan and caller-id info -->
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="cid-name" value="$${outbound_caller_name}"/>
|
||||
<param name="cid-num" value="$${outbound_caller_id}"/>
|
||||
<!--audio sample rate and interval -->
|
||||
<param name="sample-rate" value="48000"/>
|
||||
<param name="codec-ms" value="20"/>
|
||||
<param name="channels" value="1"/>
|
||||
<param name="bit-depth" value="S16LE"/>
|
||||
<!-- Tx params for the gstreamer pipeline -->
|
||||
<param name="tx-address" value="239.69.0.119"/>
|
||||
<param name="tx-port" value="5004" />
|
||||
<!-- Rx params for the in gstreamer pipeline -->
|
||||
<param name="rx-address" value="239.69.161.58"/>
|
||||
<param name="rx-port" value="5004" />
|
||||
</settings>
|
||||
<streams>
|
||||
<stream name="udp1">
|
||||
<!-- Tx params for the gstreamer pipeline -->
|
||||
<param name="tx-address" value="239.69.0.119"/>
|
||||
<param name="tx-port" value="5004" />
|
||||
<!-- Rx params for the in gstreamer pipeline -->
|
||||
<param name="rx-address" value="239.69.161.58"/>
|
||||
<param name="rx-port" value="5004" />
|
||||
<param name="sample-rate" value="48000"/>
|
||||
<param name="codec-ms" value="20"/>
|
||||
<param name="channels" value="1" />
|
||||
</stream>
|
||||
</streams>
|
||||
<endpoints>
|
||||
<endpoint name="udp1-tx">
|
||||
<param name="outstream" value="udp1:0" />
|
||||
</endpoint>
|
||||
<endpoint name="udp1-rx">
|
||||
<param name="instream" value="udp1:0" />
|
||||
</endpoint>
|
||||
<endpoint name="udp1-txrx">
|
||||
<param name="outstream" value="udp1:0" />
|
||||
<param name="instream" value="udp1:0" />
|
||||
</endpoint>
|
||||
</endpoints>
|
||||
</configuration>
|
|
@ -0,0 +1,19 @@
|
|||
include $(top_srcdir)/build/modmake.rulesam
|
||||
MODNAME=mod_gstreamer
|
||||
|
||||
if HAVE_GST
|
||||
mod_LTLIBRARIES = mod_gstreamer.la
|
||||
mod_gstreamer_la_SOURCES = mod_gstreamer.c gstreamer_api.c
|
||||
mod_gstreamer_la_CFLAGS = $(AM_CFLAGS)
|
||||
mod_gstreamer_la_CPPFLAGS = -I. $(GST_CFLAGS) $(AM_CPPFLAGS)
|
||||
mod_gstreamer_la_LIBADD = $(GST_LIBS) $(switch_builddir)/libfreeswitch.la
|
||||
mod_gstreamer_la_LDFLAGS = -avoid-version -module -no-undefined -shared
|
||||
if ISMAC
|
||||
#mod_gstreamer_la_LDFLAGS +=
|
||||
endif
|
||||
else
|
||||
install: error
|
||||
all: error
|
||||
error:
|
||||
$(error You must install gstreamer-1.0 and its subprojects to build $(MODNAME))
|
||||
endif
|
|
@ -0,0 +1,46 @@
|
|||
<configuration name="gstreamer.conf" description="Gstreamer module">
|
||||
<settings>
|
||||
<!--file to play when calls are on hold-->
|
||||
<param name="hold-file" value="$${hold_music}"/>
|
||||
<!--Default dialplan and caller-id info -->
|
||||
<param name="dialplan" value="XML"/>
|
||||
<param name="cid-name" value="$${outbound_caller_name}"/>
|
||||
<param name="cid-num" value="$${outbound_caller_id}"/>
|
||||
<!--audio sample rate and interval -->
|
||||
<param name="sample-rate" value="48000"/>
|
||||
<param name="codec-ms" value="20"/>
|
||||
<param name="channels" value="1"/>
|
||||
<param name="bit-depth" value="S16LE"/>
|
||||
<!-- Tx params for the gstreamer pipeline -->
|
||||
<param name="tx-address" value="239.69.0.119"/>
|
||||
<param name="tx-port" value="5004" />
|
||||
<!-- Rx params for the in gstreamer pipeline -->
|
||||
<param name="rx-address" value="239.69.161.58"/>
|
||||
<param name="rx-port" value="5004" />
|
||||
</settings>
|
||||
<streams>
|
||||
<stream name="udp1">
|
||||
<!-- Tx params for the gstreamer pipeline -->
|
||||
<param name="tx-address" value="239.69.0.119"/>
|
||||
<param name="tx-port" value="5004" />
|
||||
<!-- Rx params for the in gstreamer pipeline -->
|
||||
<param name="rx-address" value="239.69.161.58"/>
|
||||
<param name="rx-port" value="5004" />
|
||||
<param name="sample-rate" value="48000"/>
|
||||
<param name="codec-ms" value="20"/>
|
||||
<param name="channels" value="1" />
|
||||
</stream>
|
||||
</streams>
|
||||
<endpoints>
|
||||
<endpoint name="udp1-tx">
|
||||
<param name="outstream" value="udp1:0" />
|
||||
</endpoint>
|
||||
<endpoint name="udp1-rx">
|
||||
<param name="instream" value="udp1:0" />
|
||||
</endpoint>
|
||||
<endpoint name="udp1-txrx">
|
||||
<param name="outstream" value="udp1:0" />
|
||||
<param name="instream" value="udp1:0" />
|
||||
</endpoint>
|
||||
</endpoints>
|
||||
</configuration>
|
|
@ -0,0 +1,650 @@
|
|||
#include <switch.h>
|
||||
|
||||
#include <gst/app/gstappsink.h>
|
||||
#include <gst/audio/audio-channels.h>
|
||||
#include <gst/net/net.h>
|
||||
#include "gstreamer_api.h"
|
||||
|
||||
#define ELEMENT_NAME_SIZE 20
|
||||
#define STR_SIZE 15
|
||||
#define NAME_ELEMENT(name, element, ch_idx) \
|
||||
g_snprintf(name, ELEMENT_NAME_SIZE, "%s-ch%u", element, ch_idx)
|
||||
|
||||
#define RTP_DEPAY "rx-depay"
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SYNTHETIC_CLOCK_INTERVAL_MS 1000
|
||||
#else
|
||||
#define SYNTHETIC_CLOCK_INTERVAL_MS 100
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
bus_callback (GstBus * bus, GstMessage * msg, gpointer data)
|
||||
{
|
||||
|
||||
g_stream_t *stream = (g_stream_t *) data;
|
||||
GstElement *pipeline = (GstElement *) stream->pipeline;
|
||||
switch (GST_MESSAGE_TYPE (msg)) {
|
||||
|
||||
case GST_MESSAGE_EOS:
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"End of stream\n");
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
break;
|
||||
|
||||
case GST_MESSAGE_ERROR:{
|
||||
gchar *debug;
|
||||
GError *error;
|
||||
|
||||
gst_message_parse_error (msg, &error, &debug);
|
||||
g_free (debug);
|
||||
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error: %s\n",
|
||||
error->message);
|
||||
if (stream->error_cb)
|
||||
stream->error_cb (error->message, stream);
|
||||
g_error_free (error);
|
||||
|
||||
gst_element_set_state (pipeline, GST_STATE_NULL);
|
||||
break;
|
||||
}
|
||||
case GST_MESSAGE_STATE_CHANGED:{
|
||||
GstState old, new, pending;
|
||||
GstObject *pipe = (GstObject *) stream->pipeline;
|
||||
gst_message_parse_state_changed (msg, &old, &new, &pending);
|
||||
if (msg->src == (GstObject *) pipe) {
|
||||
gchar *old_state, *new_state, *transition;
|
||||
guint len = 0;
|
||||
old_state = g_strdup (gst_element_state_get_name (old));
|
||||
new_state = g_strdup (gst_element_state_get_name (new));
|
||||
len = strlen (old_state) + strlen (new_state) + strlen ("_to_") + 5;
|
||||
transition = g_malloc0 (len);
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
|
||||
"Pipeline %s changed state from %s to %s\n",
|
||||
GST_OBJECT_NAME (msg->src), old_state, new_state);
|
||||
g_snprintf (transition, len, "%s_to_%s", old_state, new_state);
|
||||
GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (pipe),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, transition);
|
||||
g_free (old_state);
|
||||
g_free (new_state);
|
||||
g_free (transition);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
deinterleave_pad_added (GstElement * deinterleave, GstPad * pad,
|
||||
gpointer userdata)
|
||||
{
|
||||
GstElement *pipeline =
|
||||
GST_ELEMENT (gst_element_get_parent (deinterleave)), *queue;
|
||||
GstPad *queue_sink_pad;
|
||||
gchar name[ELEMENT_NAME_SIZE];
|
||||
gchar *pad_name;
|
||||
guint ch_idx;
|
||||
|
||||
pad_name = gst_pad_get_name (pad);
|
||||
sscanf (pad_name, "src_%u", &ch_idx);
|
||||
|
||||
NAME_ELEMENT (name, "rx-queue", ch_idx);
|
||||
queue = gst_bin_get_by_name (GST_BIN (pipeline), name);
|
||||
g_assert_nonnull (queue);
|
||||
|
||||
queue_sink_pad = gst_element_get_static_pad (queue, "sink");
|
||||
|
||||
if (gst_pad_link (pad, queue_sink_pad) != GST_PAD_LINK_OK) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to link deinterleave %s pad in the rx pipeline", pad_name);
|
||||
}
|
||||
|
||||
gst_object_unref (queue_sink_pad);
|
||||
gst_object_unref(queue);
|
||||
|
||||
GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (pipeline), GST_DEBUG_GRAPH_SHOW_ALL,
|
||||
pad_name);
|
||||
g_free (pad_name);
|
||||
}
|
||||
|
||||
gboolean update_clock (gpointer userdata) {
|
||||
g_stream_t *stream = (g_stream_t *) userdata;
|
||||
GstStructure *stats = NULL;
|
||||
guint32 rtp_timestamp;
|
||||
GstElement *pipeline;
|
||||
GstClockTime internal, external;
|
||||
gdouble r_sq;
|
||||
GstElement *rtpdepay;
|
||||
|
||||
pipeline = (GstElement *) stream->pipeline;
|
||||
rtpdepay = gst_bin_get_by_name (GST_BIN (pipeline), RTP_DEPAY);
|
||||
|
||||
g_object_get (G_OBJECT(rtpdepay), "stats", &stats, NULL);
|
||||
|
||||
if (gst_structure_get_uint(stats, "timestamp", &rtp_timestamp) ) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "rtp timestamp in rtpdepay %u\n", rtp_timestamp);
|
||||
|
||||
internal = gst_clock_get_internal_time(stream->clock);
|
||||
external = gst_util_uint64_scale (rtp_timestamp, GST_SECOND, stream->sample_rate);
|
||||
|
||||
if (gst_clock_add_observation(stream->clock, internal, external, &r_sq) &&
|
||||
!g_atomic_int_get (&stream->clock_sync)) {
|
||||
g_atomic_int_set(&stream->clock_sync, 1);
|
||||
|
||||
gst_pipeline_use_clock (GST_PIPELINE (pipeline), stream->clock);
|
||||
gst_pipeline_set_clock (GST_PIPELINE (pipeline), stream->clock);
|
||||
}
|
||||
}
|
||||
|
||||
gst_structure_free(stats);
|
||||
gst_object_unref (rtpdepay);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
g_stream_t *
|
||||
create_pipeline (pipeline_data_t *data, event_callback_t * error_cb)
|
||||
{
|
||||
GstBus *bus;
|
||||
GstElement *pipeline, *rtp_pay = NULL, *rtpdepay = NULL;
|
||||
g_stream_t *stream = g_new (g_stream_t, 1);
|
||||
char fixed_name[25] = { "pipeline" };
|
||||
char *pipeline_name;
|
||||
if (data->name)
|
||||
pipeline_name = data->name;
|
||||
else
|
||||
pipeline_name = fixed_name;
|
||||
|
||||
pipeline = gst_pipeline_new (pipeline_name);
|
||||
if (!pipeline) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to create the pipeline\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (data->direction & DIRECTION_RX) {
|
||||
GstElement *udp_source, *appsink, *deinterleave, *rx_audioconv,
|
||||
*capsfilter, *queue, *identity;
|
||||
GstCaps *udp_caps = NULL, *rx_caps = NULL;
|
||||
|
||||
udp_source = gst_element_factory_make ("udpsrc", "rx-src");
|
||||
|
||||
if (data->rx_codec == L16) {
|
||||
rtpdepay = gst_element_factory_make ("rtpL16depay", RTP_DEPAY);
|
||||
udp_caps = gst_caps_new_simple ("application/x-rtp",
|
||||
"clock-rate", G_TYPE_INT, data->sample_rate,
|
||||
"channels", G_TYPE_INT, data->channels,
|
||||
"encoding-name", G_TYPE_STRING, "L16",
|
||||
"media", G_TYPE_STRING, "audio", NULL);
|
||||
} else {
|
||||
rtpdepay = gst_element_factory_make ("rtpL24depay", RTP_DEPAY);
|
||||
udp_caps = gst_caps_new_simple ("application/x-rtp",
|
||||
"clock-rate", G_TYPE_INT, data->sample_rate,
|
||||
"channels", G_TYPE_INT, data->channels,
|
||||
"encoding-name", G_TYPE_STRING, "L24",
|
||||
"media", G_TYPE_STRING, "audio", NULL);
|
||||
}
|
||||
|
||||
// rtpjitbuf = gst_element_factory_make("rtpjitterbuffer", "rx-jitbuf");
|
||||
rx_audioconv = gst_element_factory_make ("audioconvert", "rx-aconv");
|
||||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", "rx-caps");
|
||||
|
||||
/*Always feed S16LE to the FS*/
|
||||
rx_caps = gst_caps_new_simple ("audio/x-raw",
|
||||
"channels", G_TYPE_INT, data->channels,
|
||||
"format", G_TYPE_STRING, "S16LE",
|
||||
"layout", G_TYPE_STRING, "interleaved", NULL);
|
||||
|
||||
g_object_set (capsfilter, "caps", rx_caps, NULL);
|
||||
gst_caps_unref (rx_caps);
|
||||
|
||||
deinterleave = gst_element_factory_make ("deinterleave", "rx-deinterleave");
|
||||
|
||||
for (guint ch = 0; ch < data->channels; ch++) {
|
||||
gchar name[ELEMENT_NAME_SIZE];
|
||||
|
||||
NAME_ELEMENT (name, "rx-queue", ch);
|
||||
queue = gst_element_factory_make ("queue", name);
|
||||
NAME_ELEMENT (name, "appsink", ch);
|
||||
appsink = gst_element_factory_make ("appsink", name);
|
||||
NAME_ELEMENT (name, "identity", ch);
|
||||
identity = gst_element_factory_make ("identity", name);
|
||||
|
||||
if (!queue || !appsink || !identity) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to create receive elements");
|
||||
continue;
|
||||
}
|
||||
|
||||
g_object_set (appsink, "emit-signals", FALSE, "sync", FALSE,"drop", TRUE,
|
||||
"max-buffers", 1, NULL);
|
||||
g_object_set (queue, "max-size-time", 100000000 /* 100 ms */ , "leaky",
|
||||
2 /* downstream */ , NULL);
|
||||
g_object_set (identity, "drop-probability", 1.0, NULL);
|
||||
|
||||
gst_bin_add (GST_BIN (pipeline), queue);
|
||||
gst_bin_add (GST_BIN (pipeline), identity);
|
||||
gst_bin_add (GST_BIN (pipeline), appsink);
|
||||
|
||||
gst_element_link_many (queue, identity, appsink, NULL);
|
||||
|
||||
// The deinterleave will be linked to the queue dynamically
|
||||
}
|
||||
|
||||
g_signal_connect (deinterleave, "pad-added",
|
||||
G_CALLBACK (deinterleave_pad_added), NULL);
|
||||
|
||||
g_object_set (udp_source, "address", data->rx_ip_addr, "port", data->rx_port,
|
||||
NULL);
|
||||
g_object_set (udp_source, "caps", udp_caps, NULL);
|
||||
gst_caps_unref (udp_caps);
|
||||
|
||||
if (!udp_source || !rtpdepay || !rx_audioconv || !capsfilter
|
||||
|| !deinterleave) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to create rx elements\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_bin_add_many (GST_BIN (pipeline), udp_source, rtpdepay, rx_audioconv,
|
||||
capsfilter, deinterleave, NULL);
|
||||
|
||||
if (!gst_element_link_many (udp_source, rtpdepay, rx_audioconv, capsfilter,
|
||||
deinterleave, NULL)) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to link elements in the rx pipeline");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->direction & DIRECTION_TX) {
|
||||
GstElement *udpsink, *tx_audioconv, *audiointerleave, *capsfilter;
|
||||
GstElement *appsrc;
|
||||
GstCaps *caps = NULL;
|
||||
|
||||
audiointerleave =
|
||||
gst_element_factory_make ("audiointerleave", "audiointerleave");
|
||||
gst_bin_add (GST_BIN (pipeline), audiointerleave);
|
||||
g_object_set(audiointerleave, "start-time-selection", GST_AGGREGATOR_START_TIME_SELECTION_FIRST, NULL);
|
||||
|
||||
if (data->tx_codec == L16) {
|
||||
rtp_pay = gst_element_factory_make ("rtpL16pay", "rtp-pay");
|
||||
|
||||
} else {
|
||||
rtp_pay = gst_element_factory_make ("rtpL24pay", "rtp-pay");
|
||||
}
|
||||
if (data->ptime_ms != -1.0) {
|
||||
g_object_set(rtp_pay, "max-ptime", (gint64) (data->ptime_ms * 1000000),
|
||||
"min-ptime", (gint64) (data->ptime_ms * 1000000), NULL);
|
||||
}
|
||||
|
||||
for (guint ch = 0; ch < data->channels; ch++) {
|
||||
gchar name[ELEMENT_NAME_SIZE];
|
||||
gchar pad_name[STR_SIZE];
|
||||
|
||||
NAME_ELEMENT (name, "appsrc", ch);
|
||||
g_snprintf (pad_name, STR_SIZE, "sink_%u", ch);
|
||||
|
||||
appsrc = gst_element_factory_make ("appsrc", name);
|
||||
if (!appsrc) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to create %s \n", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*Always accept S16LE from the FS*/
|
||||
caps = gst_caps_new_simple ("audio/x-raw",
|
||||
"rate", G_TYPE_INT, data->sample_rate,
|
||||
"channels", G_TYPE_INT, 1,
|
||||
"format", G_TYPE_STRING, "S16LE",
|
||||
"layout", G_TYPE_STRING, "interleaved",
|
||||
"channel-mask", GST_TYPE_BITMASK, (guint64) (1 << ch), NULL);
|
||||
g_object_set (appsrc, "format", GST_FORMAT_TIME, NULL);
|
||||
g_object_set (appsrc, "do-timestamp", TRUE, NULL);
|
||||
g_object_set (appsrc, "is-live", TRUE, NULL);
|
||||
/* Second * 3 allows a little bit of headroom */
|
||||
g_object_set (appsrc, "max-bytes", data->codec_ms * data->sample_rate * 2 * 3, NULL);
|
||||
|
||||
g_object_set (appsrc, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
gst_bin_add (GST_BIN (pipeline), appsrc);
|
||||
|
||||
if (!gst_element_link_pads (appsrc, "src", audiointerleave, pad_name)) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to link pads of %s with audiointerleave\n", name);
|
||||
goto error;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
capsfilter = gst_element_factory_make ("capsfilter", "tx-capsf");
|
||||
|
||||
tx_audioconv = gst_element_factory_make ("audioconvert", "tx-audioconv");
|
||||
|
||||
udpsink = gst_element_factory_make ("udpsink", "tx-sink");
|
||||
|
||||
caps = gst_caps_new_simple ("audio/x-raw",
|
||||
"rate", G_TYPE_INT, data->sample_rate,
|
||||
"channels", G_TYPE_INT, data->channels,
|
||||
"format", G_TYPE_STRING, "S16LE",
|
||||
"layout", G_TYPE_STRING, "interleaved",
|
||||
"channel-mask", GST_TYPE_BITMASK, (guint64) (1 << data->channels) - 1,
|
||||
NULL);
|
||||
g_object_set (capsfilter, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
g_object_set (udpsink, "host", data->tx_ip_addr, "port", data->tx_port, NULL);
|
||||
g_object_set (udpsink, "sync", TRUE, "async", FALSE, NULL);
|
||||
g_object_set (udpsink, "qos", TRUE, "qos-dscp", 34, NULL);
|
||||
|
||||
if (!audiointerleave || !tx_audioconv || !rtp_pay || !udpsink) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to create tx elements\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
gst_bin_add_many (GST_BIN (pipeline), capsfilter, tx_audioconv, rtp_pay,
|
||||
udpsink, NULL);
|
||||
|
||||
if (!gst_element_link_many (audiointerleave, capsfilter, tx_audioconv,
|
||||
rtp_pay, udpsink, NULL)) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to link elements");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
|
||||
gst_bus_add_watch (bus, bus_callback, stream);
|
||||
gst_object_unref (bus);
|
||||
|
||||
stream->error_cb = error_cb;
|
||||
stream->pipeline = GST_PIPELINE (pipeline);
|
||||
stream->mainloop = g_main_loop_new (NULL, FALSE);
|
||||
stream->thread = g_thread_new (pipeline_name, start_pipeline, stream);
|
||||
stream->sample_rate = data->sample_rate;
|
||||
|
||||
g_atomic_int_set (&stream->clock_sync, 0);
|
||||
|
||||
gst_element_set_start_time(pipeline, GST_CLOCK_TIME_NONE);
|
||||
gst_element_set_base_time(pipeline, 0);
|
||||
|
||||
if (rtp_pay) {
|
||||
g_object_set (rtp_pay, "timestamp-offset",
|
||||
gst_util_uint64_scale_int (data->rtp_ts_offset * GST_MSECOND, data->sample_rate, GST_SECOND)
|
||||
% G_MAXUINT32,
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (rtpdepay && data->synthetic_ptp) {
|
||||
stream->clock = g_object_new (GST_TYPE_SYSTEM_CLOCK, "name", "SyntheticPtpClock", NULL);
|
||||
stream->cb_rx_stats_id =
|
||||
g_timeout_add_full(G_PRIORITY_DEFAULT, SYNTHETIC_CLOCK_INTERVAL_MS, update_clock, stream, NULL);
|
||||
/* We'll set the pipeline clock once it's synced */
|
||||
} else {
|
||||
stream->clock = NULL;
|
||||
gst_pipeline_use_clock (GST_PIPELINE(pipeline), data->clock);
|
||||
g_atomic_int_set (&stream->clock_sync, 1);
|
||||
}
|
||||
|
||||
for (guint ch = 0; ch < MAX_IO_CHANNELS; ch++)
|
||||
stream->leftover_bytes[ch] = 0;
|
||||
|
||||
return stream;
|
||||
|
||||
error:
|
||||
gst_object_unref (pipeline);
|
||||
g_free (stream);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void *
|
||||
start_pipeline (void *data)
|
||||
{
|
||||
|
||||
g_stream_t *stream = (g_stream_t *) data;
|
||||
gst_element_set_state (GST_ELEMENT (stream->pipeline), GST_STATE_PLAYING);
|
||||
|
||||
GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (stream->pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "start-pipeline");
|
||||
start_mainloop (stream->mainloop);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
stop_pipeline (g_stream_t * stream)
|
||||
{
|
||||
GstBus *bus;
|
||||
GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (stream->pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, "pipeline-stop");
|
||||
|
||||
gst_element_set_state (GST_ELEMENT (stream->pipeline), GST_STATE_NULL);
|
||||
|
||||
/* cb_rx_stats_id will be non zero only when
|
||||
Rx is operational and pipeline clock is not ptp*/
|
||||
if (stream->cb_rx_stats_id)
|
||||
g_source_remove(stream->cb_rx_stats_id);
|
||||
|
||||
bus = gst_pipeline_get_bus (GST_PIPELINE (stream->pipeline));
|
||||
gst_bus_remove_watch (bus);
|
||||
gst_object_unref (bus);
|
||||
|
||||
gst_object_unref (stream->pipeline);
|
||||
if (stream->clock)
|
||||
gst_object_unref (stream->clock);
|
||||
teardown_mainloop (stream->mainloop);
|
||||
g_thread_join (stream->thread);
|
||||
g_free (stream);
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Pipeline and mainloop cleaned up\n");
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
teardown_mainloop (GMainLoop * mainloop)
|
||||
{
|
||||
|
||||
g_main_loop_quit (mainloop);
|
||||
g_main_loop_unref (mainloop);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
start_mainloop (GMainLoop * mainloop)
|
||||
{
|
||||
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Running mainloop\n");
|
||||
g_main_loop_run (mainloop);
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
push_buffer (g_stream_t *stream, unsigned char *payload, guint len,
|
||||
guint ch_idx, switch_timer_t * timer)
|
||||
{
|
||||
GstState cur_state = GST_STATE_NULL, pending_state;
|
||||
GstBuffer *buf;
|
||||
GstMapInfo info;
|
||||
GstFlowReturn ret;
|
||||
gchar name[ELEMENT_NAME_SIZE];
|
||||
GstElement *appsrc = NULL;
|
||||
GstPipeline *pipeline = stream->pipeline;
|
||||
gboolean res = FALSE;
|
||||
|
||||
NAME_ELEMENT (name, "appsrc", ch_idx);
|
||||
appsrc = gst_bin_get_by_name (GST_BIN (pipeline), name);
|
||||
|
||||
switch_core_timer_next (timer);
|
||||
|
||||
if (appsrc == NULL) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Failed to find appsrc in the pipeline\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_atomic_int_get(&stream->clock_sync)) {
|
||||
ret = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
gst_element_get_state (GST_ELEMENT (pipeline), &cur_state, &pending_state, 0);
|
||||
if (cur_state != GST_STATE_PAUSED && cur_state != GST_STATE_PLAYING) {
|
||||
ret = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
buf = gst_buffer_new_allocate (NULL, len, NULL);
|
||||
if (buf == NULL) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to allocate buffer\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!gst_buffer_map (buf, &info, GST_MAP_WRITE)) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to get buffer map\n");
|
||||
goto done;
|
||||
}
|
||||
memcpy (info.data, payload, len);
|
||||
gst_buffer_unmap (buf, &info);
|
||||
|
||||
g_signal_emit_by_name (appsrc, "push-buffer", buf, &ret);
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Pushed buffer\n");
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
if (ret == GST_FLOW_ERROR) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to do 'push-buffer' \n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
res = TRUE;
|
||||
|
||||
done:
|
||||
gst_object_unref (GST_OBJECT (appsrc));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
pull_buffers (g_stream_t * stream, unsigned char *payload, guint needed_bytes,
|
||||
guint ch_idx, switch_timer_t * timer)
|
||||
{
|
||||
GstState cur_state = GST_STATE_NULL, pending_state;
|
||||
GstBuffer *buf;
|
||||
GstSample *sample;
|
||||
GstMapInfo info;
|
||||
int total_bytes = 0;
|
||||
gchar name[ELEMENT_NAME_SIZE];
|
||||
GstElement *appsink;
|
||||
|
||||
NAME_ELEMENT (name, "appsink", ch_idx);
|
||||
appsink = gst_bin_get_by_name (GST_BIN (stream->pipeline), name);
|
||||
|
||||
if (appsink == NULL) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to find appsink in the pipeline\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
gst_element_get_state (GST_ELEMENT (stream->pipeline), &cur_state,
|
||||
&pending_state, 0);
|
||||
if (cur_state != GST_STATE_PAUSED && cur_state != GST_STATE_PLAYING)
|
||||
goto out;
|
||||
|
||||
if (gst_app_sink_is_eos (GST_APP_SINK (appsink)))
|
||||
goto out;
|
||||
|
||||
// Note: assumes leftover_bytes will never be more than buflen, which is
|
||||
// likely true (packet is limited to MTU, while buflen is 8192)
|
||||
if (stream->leftover_bytes[ch_idx]) {
|
||||
int copy =
|
||||
stream->leftover_bytes[ch_idx] <=
|
||||
needed_bytes ? stream->leftover_bytes[ch_idx] : needed_bytes;
|
||||
memcpy (payload, stream->leftover[ch_idx], copy);
|
||||
total_bytes += copy;
|
||||
stream->leftover_bytes[ch_idx] -= copy;
|
||||
}
|
||||
|
||||
while (total_bytes < needed_bytes) {
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "pulling buffer\n");
|
||||
sample =
|
||||
gst_app_sink_try_pull_sample (GST_APP_SINK (appsink),
|
||||
10 * GST_MSECOND);
|
||||
if (!sample) {
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Failed to pull sample\n");
|
||||
switch_cond_next ();
|
||||
break;
|
||||
}
|
||||
buf = gst_sample_get_buffer (sample);
|
||||
|
||||
if (!buf)
|
||||
continue;
|
||||
|
||||
if (gst_buffer_map (buf, &info, GST_MAP_READ)) {
|
||||
if (total_bytes + info.size > needed_bytes) {
|
||||
int want = needed_bytes - total_bytes;
|
||||
|
||||
stream->leftover_bytes[ch_idx] = info.size - want;
|
||||
memcpy (stream->leftover[ch_idx], info.data + want,
|
||||
stream->leftover_bytes[ch_idx]);
|
||||
|
||||
info.size = want;
|
||||
}
|
||||
|
||||
memcpy (payload + total_bytes, info.data, info.size);
|
||||
total_bytes += info.size;
|
||||
}
|
||||
gst_buffer_unmap (buf, &info);
|
||||
gst_sample_unref (sample);
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Got %d\n", total_bytes);
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
// Dump data to file
|
||||
char name[100];
|
||||
int fd;
|
||||
|
||||
NAME_ELEMENT (name, "/tmp/raw", ch_idx);
|
||||
fd = open (name, O_WRONLY | O_CREAT | O_APPEND);
|
||||
|
||||
write (fd, payload, total_bytes);
|
||||
close (fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%u Returning needed %d, total_bytes: %d\n", ch_idx, needed_bytes, total_bytes);
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Leftover %lu\n", stream->leftover_bytes[ch_idx]);
|
||||
|
||||
out:
|
||||
gst_object_unref(appsink);
|
||||
return total_bytes;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
drop_input_buffers (gboolean drop, g_stream_t * stream, guint32 ch_idx)
|
||||
{
|
||||
gchar name[ELEMENT_NAME_SIZE];
|
||||
GstElement *identity;
|
||||
NAME_ELEMENT (name, "identity", ch_idx);
|
||||
identity = gst_bin_get_by_name (GST_BIN (stream->pipeline), name);
|
||||
if (identity == NULL) {
|
||||
switch_log_printf (SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR,
|
||||
"Failed to get identity element in the pipeline\n");
|
||||
return;
|
||||
}
|
||||
g_object_set (identity, "drop-probability", drop ? 1.0 : 0.0, NULL);
|
||||
g_snprintf (name, STR_SIZE, "drop-ch%d-%d", ch_idx, drop);
|
||||
GST_DEBUG_BIN_TO_DOT_FILE (GST_BIN (stream->pipeline),
|
||||
GST_DEBUG_GRAPH_SHOW_ALL, name);
|
||||
gst_object_unref(identity);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
#ifndef __GSTREAMER_API__
|
||||
#define __GSTREAMER_API__
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <switch.h>
|
||||
|
||||
#define DIRECTION_TX 1 << 0
|
||||
#define DIRECTION_RX 1 << 1
|
||||
|
||||
#define IP_ADDR_MAX_LEN 20
|
||||
#define AUDIO_FMT_STR_LEN 10
|
||||
|
||||
#define MAX_IO_CHANNELS 256
|
||||
|
||||
typedef enum
|
||||
{ L16, L24 } aes67_codec_t;
|
||||
|
||||
typedef struct g_stream g_stream_t;
|
||||
|
||||
typedef void event_callback_t (gchar * error_msg, g_stream_t * stream);
|
||||
typedef struct
|
||||
{
|
||||
char rx_ip_addr[IP_ADDR_MAX_LEN];
|
||||
int rx_port;
|
||||
char tx_ip_addr[IP_ADDR_MAX_LEN];
|
||||
int tx_port;
|
||||
int direction;
|
||||
int sample_rate;
|
||||
char bit_depth[AUDIO_FMT_STR_LEN];
|
||||
int channels;
|
||||
aes67_codec_t tx_codec;
|
||||
aes67_codec_t rx_codec;
|
||||
int codec_ms;
|
||||
char *name;
|
||||
double ptime_ms;
|
||||
GstClock *clock;
|
||||
gint synthetic_ptp;
|
||||
double rtp_ts_offset;
|
||||
} pipeline_data_t;
|
||||
|
||||
struct g_stream
|
||||
{
|
||||
GstPipeline *pipeline;
|
||||
GMainLoop *mainloop;
|
||||
GThread *thread;
|
||||
unsigned char leftover[MAX_IO_CHANNELS][SWITCH_RECOMMENDED_BUFFER_SIZE];
|
||||
size_t leftover_bytes[MAX_IO_CHANNELS];
|
||||
event_callback_t *error_cb;
|
||||
guint cb_rx_stats_id;
|
||||
volatile gint clock_sync;
|
||||
GstClock *clock;
|
||||
gint sample_rate;
|
||||
};
|
||||
|
||||
g_stream_t *create_pipeline (pipeline_data_t *data, event_callback_t * error_cb);
|
||||
void *start_pipeline (void *data);
|
||||
void stop_pipeline (g_stream_t * pipeline);
|
||||
void teardown_mainloop (GMainLoop * loop);
|
||||
void start_mainloop (GMainLoop * loop);
|
||||
|
||||
gboolean push_buffer (g_stream_t *stream, unsigned char *payload, guint len,
|
||||
guint ch_idx, switch_timer_t * timer);
|
||||
int pull_buffers (g_stream_t * stream, unsigned char *payload, guint buflen,
|
||||
guint ch_idx, switch_timer_t * timer);
|
||||
void drop_input_buffers (gboolean drop, g_stream_t * stream, guint32 ch_idx);
|
||||
|
||||
#endif /*__GSTREAMER_API__*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,207 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>mod_gstreamer</ProjectName>
|
||||
<ProjectGuid>{5AC15CAA-B153-4B45-804A-0CFDF6FA3422}</ProjectGuid>
|
||||
<RootNamespace>mod_Streamer</RootNamespace>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_release.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\glib-2.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-app-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-net-1.0.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_debug.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\glib-2.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-app-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-net-1.0.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_release.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\glib-2.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-app-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-net-1.0.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\..\..\..\w32\module_debug.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\glib-2.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-app-1.0.props" />
|
||||
<Import Project="C:\gstreamer\1.0\msvc_x86_64\share\vs\2010\libs\gstreamer-net-1.0.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<IncludePath>C:\gstreamer\1.0\msvc_x86_64\lib\glib-2.0\include\;C:\gstreamer\1.0\msvc_x86_64\include\glib-2.0\;C:\gstreamer\1.0\msvc_x86_64\include\;C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0;C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0\gst\app;C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0\gst\net;C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0\gst;C:\freeswitch\libs\portaudio\src\os\win;$(IncludePath)</IncludePath>
|
||||
<ReferencePath>C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0\gst;C:\freeswitch\libs\portaudio\src\os\win;C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0\gst\app;C:\gstreamer\1.0\msvc_x86_64\include\gstreamer-1.0\gst\net;$(ReferencePath)</ReferencePath>
|
||||
<SourcePath>C:\freeswitch\libs\portaudio\src\os\win;$(SourcePath)</SourcePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<CodeAnalysisRuleSet>NativeMinimumRules.ruleset</CodeAnalysisRuleSet>
|
||||
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||
<IncludePath>C:\freeswitch\libs\portaudio\src\os\win;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\portaudio\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;ALLOW_SMP_DANGERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<DisableSpecificWarnings>4100;4101;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/NODEFAULTLIB:LIMBCTD %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\..\libs\portaudio\winvc\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\portaudio\include;%(RootDir)%(Directory)..\..\..\..\libs\portaudio\src\os\win;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS;ALLOW_SMP_DANGERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<DisableSpecificWarnings>4100;4101;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalOptions>/NODEFAULTLIB:LIMBCTD %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalDependencies>ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\..\libs\portaudio\winvc\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\portaudio\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ALLOW_SMP_DANGERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<DisableSpecificWarnings>4100;4101;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\..\libs\portaudio\winvc\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Midl>
|
||||
<TargetEnvironment>X64</TargetEnvironment>
|
||||
</Midl>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(RootDir)%(Directory)..\..\..\..\libs\portaudio\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>ALLOW_SMP_DANGERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<DisableSpecificWarnings>4100;4101;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<EnablePREfast>false</EnablePREfast>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ksuser.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(ProjectDir)..\..\..\..\libs\portaudio\winvc\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<RandomizedBaseAddress>false</RandomizedBaseAddress>
|
||||
<DataExecutionPrevention>
|
||||
</DataExecutionPrevention>
|
||||
<TargetMachine>MachineX64</TargetMachine>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="gstreamer_api.c" />
|
||||
<ClCompile Include="mod_gstreamer.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="gstreamer_api.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\..\libs\win32\apr\libapr.2017.vcxproj">
|
||||
<Project>{f6c55d93-b927-4483-bb69-15aef3dd2dff}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\..\w32\Library\FreeSwitchCore.2017.vcxproj">
|
||||
<Project>{202d7a4e-760d-4d0e-afa1-d7459ced30ff}</Project>
|
||||
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue