Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • gstreamer/gst-plugins-bad
  • thiblahute/gst-plugins-bad
  • slomo/gst-plugins-bad
  • sree/gst-plugins-bad
  • seungha.yang/gst-plugins-bad
  • xclaesse/gst-plugins-bad
  • haihao/gst-plugins-bad
  • Russel/gst-plugins-bad
  • heftig/gst-plugins-bad
  • joshuadoe/gst-plugins-bad
  • bilboed/gst-plugins-bad
  • ndufresne/gst-plugins-bad
  • ystreet/gst-plugins-bad
  • hgr/gst-plugins-bad
  • nielsdg/gst-plugins-bad
  • Brad/gst-plugins-bad
  • alatiera/gst-plugins-bad
  • SiewHoon/gst-plugins-bad
  • joykim/gst-plugins-bad
  • edholland/gst-plugins-bad
  • jh-hsd/gst-plugins-bad
  • lpendresen/gst-plugins-bad
  • daniels/gst-plugins-bad
  • nirbheek/gst-plugins-bad
  • tchakabam/gst-plugins-bad
  • wangfei/gst-plugins-bad
  • mangix/gst-plugins-bad
  • gdesmott/gst-plugins-bad
  • jonakn/gst-plugins-bad
  • Yeongjin-Jeong/gst-plugins-bad
  • harshadkhedkar/gst-plugins-bad
  • vjaquez/gst-plugins-bad
  • tpm/gst-plugins-bad
  • drakkan/gst-plugins-bad
  • milloni-ct/gst-plugins-bad
  • wonchul/gst-plugins-bad
  • philn/gst-plugins-bad
  • patricia/gst-plugins-bad
  • alexashley/gst-plugins-bad
  • gkiagia/gst-plugins-bad
  • dong9/gst-plugins-bad
  • michaelgruner/gst-plugins-bad
  • ikreymer/gst-plugins-bad
  • donghyeok/gst-plugins-bad
  • ullysses.a.eoff/gst-plugins-bad
  • CarlFK/gst-plugins-bad
  • ding/gst-plugins-bad
  • meh/gst-plugins-bad
  • victortoso/gst-plugins-bad
  • valbok/gst-plugins-bad
  • joel-holdsworth/gst-plugins-bad
  • jdm/gst-plugins-bad
  • thaytan/gst-plugins-bad
  • yangcha/gst-plugins-bad
  • ThomasSchlien/gst-plugins-bad
  • boxerab/gst-plugins-bad
  • den_erpel/gst-plugins-bad
  • alyyousuf7/gst-plugins-bad
  • andrey-konovalov/gst-plugins-bad
  • mvlad/gst-plugins-bad
  • JimmyOhn/gst-plugins-bad
  • chturne/gst-plugins-bad
  • yskkmi/gst-plugins-bad
  • vivia/gst-plugins-bad
  • billylindeman/gst-plugins-bad
  • nacho.garglez/gst-plugins-bad
  • MaZderMind/gst-plugins-bad
  • david.lee/gst-plugins-bad
  • JaredHu/gst-plugins-bad
  • ulfo/gst-plugins-bad
  • fuweitax/gst-plugins-bad
  • calvaris/gst-plugins-bad
  • codinho/gst-plugins-bad
  • lord.jacold/gst-plugins-bad
  • adn770/gst-plugins-bad
  • ayaka/gst-plugins-bad
  • kevinbing.song/gst-plugins-bad
  • billconan/gst-plugins-bad
  • psreport/gst-plugins-bad
  • welaq/gst-plugins-bad
  • dank/gst-plugins-bad
  • raytiley/gst-plugins-bad
  • myungjoo/gst-plugins-bad
  • fabio-d/gst-plugins-bad
  • marcosk/gst-plugins-bad
  • nh2/gst-plugins-bad
  • creiter/gst-plugins-bad
  • mnauw/gst-plugins-bad
  • dv1/gst-plugins-bad
  • santoscadenas/gst-plugins-bad
  • dabrain34/gst-plugins-bad
  • taylor.patton/gst-plugins-bad
  • edersondisouza/gst-plugins-bad
  • GNUDimarik/gst-plugins-bad
  • Aduskett/gst-plugins-bad
  • aleksandrm8/gst-plugins-bad
  • OleksandrKvl/gst-plugins-bad
  • autintim/gst-plugins-bad
  • charles/gst-plugins-bad
  • floobleflam/gst-plugins-bad
  • lantw/gst-plugins-bad
  • bellet/gst-plugins-bad
  • marxin.liska/gst-plugins-bad
  • therimar/gst-plugins-bad
  • xhaakon/gst-plugins-bad
  • zeidbekli48/gst-plugins-bad
  • okajun/gst-plugins-bad
  • szve/gst-plugins-bad
  • dougnazar/gst-plugins-bad
  • nacho.resa/gst-plugins-bad
  • pfy/gst-plugins-bad
  • coldtom/gst-plugins-bad
  • ankurdeepjaiswal/gst-plugins-bad
  • fdavulcu/gst-plugins-bad
  • lemenkov/gst-plugins-bad
  • Pyrrhvs/gst-plugins-bad
  • wangyan42164/gst-plugins-bad
  • tezcatli/gst-plugins-bad
  • ssaito/gst-plugins-bad
  • slabajo/gst-plugins-bad
  • hq/gst-plugins-bad
  • peat-psuwit/gst-plugins-bad
  • mol/gst-plugins-bad
  • luisbg/gst-plugins-bad
  • zubzub/gst-plugins-bad
  • fabiangreffrath/gst-plugins-bad
  • davidph/gst-plugins-bad
  • pH5/gst-plugins-bad
  • jmaibaum/gst-plugins-bad
  • aleb/gst-plugins-bad
  • jcelaya/gst-plugins-bad
  • StefanBruens/gst-plugins-bad
  • abranson/gst-plugins-bad
  • cap/gst-plugins-bad
  • ihalip/gst-plugins-bad
  • vedangpatel1/gst-plugins-bad
  • ali1234/gst-plugins-bad
  • jgilje/gst-plugins-bad
  • He_Junyan/gst-plugins-bad
  • aguedes/gst-plugins-bad
  • francisv/gst-plugins-bad
  • t/gst-plugins-bad
  • hwilkes/gst-plugins-bad
  • thiagossantos/gst-plugins-bad
  • linussn/gst-plugins-bad
  • Hosang/gst-plugins-bad
  • rob_gries/gst-plugins-bad
  • o0Ignition0o/gst-plugins-bad
  • ntrrgc/gst-plugins-bad
  • neithanmo/gst-plugins-bad
  • andrew.voznytsa/gst-plugins-bad
  • sf2020/gst-plugins-bad
  • danisla/gst-plugins-bad
  • juzza_uk/gst-plugins-bad
  • fraxinas/gst-plugins-bad
  • Arhno/gst-plugins-bad
  • leio/gst-plugins-bad
  • guillerodriguez/gst-plugins-bad
  • krivoguzovVlad/gst-plugins-bad
  • ludvigr/gst-plugins-bad
  • nazar-pc/gst-plugins-bad
  • Buora/gst-plugins-bad
  • heinrich.kruger/gst-plugins-bad
  • motownread/gst-plugins-bad
  • jwestman/gst-plugins-bad
  • paulyc/gst-plugins-bad
  • balte/gst-plugins-bad
  • jurijs.satcs/gst-plugins-bad
  • rgonzalez/gst-plugins-bad
  • antonovitch/gst-plugins-bad
  • jan.vermaete/gst-plugins-bad
  • XuGuangxin/gst-plugins-bad
  • 123vivekr/gst-plugins-bad
  • decembersoul/gst-plugins-bad
  • mparisdiaz/gst-plugins-bad
  • worldofpeace/gst-plugins-bad
  • achris/gst-plugins-bad
  • nanonyme/gst-plugins-bad
  • arun/gst-plugins-bad
  • DuBistKomisch/gst-plugins-bad
  • lblasc/gst-plugins-bad
  • ahoenig/gst-plugins-bad
  • Mats/gst-plugins-bad
  • Andruxin52rus/gst-plugins-bad
  • cketti/gst-plugins-bad
  • MM_Star/gst-plugins-bad
  • Chikushu/gst-plugins-bad
  • daniel.qtec/gst-plugins-bad
  • 4kevinking/gst-plugins-bad
  • fritzprix/gst-plugins-bad
  • dhobsong/gst-plugins-bad
  • rambden/gst-plugins-bad
  • razvanphp/gst-plugins-bad
  • foreverneilyoung/gst-plugins-bad
  • wtaymans/gst-plugins-bad
  • ezequielgarcia/gst-plugins-bad
  • trollkarlen/gst-plugins-bad
  • jedevc/gst-plugins-bad
  • jusizela/gst-plugins-bad
  • karim.davoodi/gst-plugins-bad
  • quaresma.jose/gst-plugins-bad
  • felixonmars/gst-plugins-bad
  • louisharris/gst-plugins-bad
  • lmurillo/gst-plugins-bad
  • trilene/gst-plugins-bad
  • jlaheurte/gst-plugins-bad
  • jmatthew/gst-plugins-bad
  • wilkinsw/gst-plugins-bad
  • yychao/gst-plugins-bad
  • eckhart.koppen/gst-plugins-bad
  • AdamW/gst-plugins-bad
  • SanchayanMaity/gst-plugins-bad
  • twischer/gst-plugins-bad
  • marian/gst-plugins-bad
  • linkmauve/gst-plugins-bad
  • gvanmeter/gst-plugins-bad
  • julian/gst-plugins-bad
  • raghu447/gst-plugins-bad
  • TobiasR/gst-plugins-bad
  • MoizAhmedd/gst-plugins-bad
  • gstreamer-release-bot/gst-plugins-bad
  • artectrex/gst-plugins-bad
  • Rafostar/gst-plugins-bad
  • mindriot88/gst-plugins-bad
  • mexxik/gst-plugins-bad
  • robin.carlisle/gst-plugins-bad
  • MarijnS95/gst-plugins-bad
  • igor.v.kovalenko/gst-plugins-bad
  • chriswiggins/gst-plugins-bad
  • johast/gst-plugins-bad
  • fauxsoup1/gst-plugins-bad
  • ekwange/gst-plugins-bad
  • raju.babannavar/gst-plugins-bad
  • eater/gst-plugins-bad
  • ds/gst-plugins-bad
  • avantgardnerio/gst-plugins-bad
  • marsupial/gst-plugins-bad
  • ignacy.ruksza/gst-plugins-bad
  • t-8ch/gst-plugins-bad
  • trey.hutcheson/gst-plugins-bad
  • ssanders1449/gst-plugins-bad
  • stazio/gst-plugins-bad
  • obbardc/gst-plugins-bad
  • dwlsalmeida/gst-plugins-bad
  • benjamin.gaignard1/gst-plugins-bad
  • AntoninRousset/gst-plugins-bad
  • AdhBash816/gst-plugins-bad
  • jjanku/gst-plugins-bad
  • liuyinhangx/gst-plugins-bad
  • AdvanceSoftware/gst-plugins-bad
  • jn/gst-plugins-bad
  • wantlamy/gst-plugins-bad
  • hjanuschka/gst-plugins-bad
  • Nei/gst-plugins-bad
  • arojas/gst-plugins-bad
  • zhao-gang/gst-plugins-bad
  • sid.sethupathi/gst-plugins-bad
  • mkba/gst-plugins-bad
  • YakoYakoYokuYoku/gst-plugins-bad
  • CartoonFan/gst-plugins-bad
  • rsiv/gst-plugins-bad
  • martinetd/gst-plugins-bad
  • reynaldo/gst-plugins-bad
  • kay0u1/gst-plugins-bad
  • thongthai/gst-plugins-bad
  • spartazhc/gst-plugins-bad
  • leeys888/gst-plugins-bad
  • ferruck/gst-plugins-bad
  • benjamin545/gst-plugins-bad
  • budziq/gst-plugins-bad
  • madsbuvi/gst-plugins-bad
  • agx/gst-plugins-bad
  • amotzte/gst-plugins-bad
  • devarsht/gst-plugins-bad
  • kimtinh/gst-plugins-bad
  • lshuying/gst-plugins-bad
  • rsnk96/gst-plugins-bad
  • mortimergoro/gst-plugins-bad
  • cfoch/gst-plugins-bad
  • jfelder/gst-plugins-bad
  • kathirvel621/gst-plugins-bad
  • bradh/gst-plugins-bad
  • middelschultele/gst-plugins-bad
  • pocock/gst-plugins-bad
  • marex/gst-plugins-bad
  • vivienne/gst-plugins-bad
  • pldin601/gst-plugins-bad
  • heirecka/gst-plugins-bad
  • Casey-Bateman/gst-plugins-bad
  • adrianf0/gst-plugins-bad
  • ovchinnikov.dmitrii/gst-plugins-bad
  • DimStar77/gst-plugins-bad
  • intelfx/gst-plugins-bad
  • derschueddi/gst-plugins-bad
  • driss.el.bouhali/gst-plugins-bad
  • jinsl00000/gst-plugins-bad
  • Wenlin/gst-plugins-bad
  • carra8674/gst-plugins-bad
  • ssdeng6812/gst-plugins-bad
  • glepag1/gst-plugins-bad
  • cnhzcy14/gst-plugins-bad
  • HuQian/gst-plugins-bad
  • Zhipeng/gst-plugins-bad
  • Harikrishnan/gst-plugins-bad
  • benjaminGraef/gst-plugins-bad
  • vnguyentrong/gst-plugins-bad
306 results
Show changes
Commits on Source (76)
Showing
with 619 additions and 235 deletions
......@@ -221942,6 +221942,33 @@
"videoparsersbad": {
"description": "videoparsers",
"elements": {
"av1parse": {
"author": "He Junyan <junyan.he@intel.com>",
"description": "Parses AV1 streams",
"hierarchy": [
"GstAV1Parse",
"GstBaseParse",
"GstElement",
"GstObject",
"GInitiallyUnowned",
"GObject"
],
"klass": "Codec/Parser/Converter/Video",
"long-name": "AV1 parser",
"pad-templates": {
"sink": {
"caps": "video/x-av1:\n",
"direction": "sink",
"presence": "always"
},
"src": {
"caps": "video/x-av1:\n parsed: true\n stream-format: { (string)obu-stream, (string)annexb }\n alignment: { (string)obu, (string)tu, (string)frame }\n",
"direction": "src",
"presence": "always"
}
},
"rank": "secondary"
},
"diracparse": {
"author": "David Schleef <ds@schleef.org>",
"description": "Parses Dirac streams",
......@@ -584,6 +584,7 @@ gst_dash_sink_generate_mpd_content (GstDashSink * sink,
gst_mpd_client_set_root_node (sink->mpd_client,
"type", GST_MPD_FILE_TYPE_DYNAMIC,
"availability-start-time", now, "publish-time", now, NULL);
gst_date_time_unref (now);
}
if (sink->minimum_update_period)
gst_mpd_client_set_root_node (sink->mpd_client,
......
......@@ -103,7 +103,6 @@ gst_mpd_helper_get_audio_codec_from_mime (GstCaps * caps)
}
done:
gst_caps_unref (caps);
return codec_name;
}
......@@ -123,12 +122,13 @@ gst_mpd_helper_get_video_codec_from_mime (GstCaps * caps)
name = gst_structure_get_name (s);
if (!g_strcmp0 (name, "video/x-h264")) {
return "avc1";
} else if (!g_strcmp0 (name, "video/x-h265")) {
return "hvc1";
} else {
GST_DEBUG ("No codecs for this caps name %s", name);
}
done:
gst_caps_unref (caps);
return codec_name;
}
......
......@@ -83,17 +83,17 @@ gst_mpd_root_node_set_property (GObject * object, guint prop_id,
case PROP_MPD_ROOT_AVAILABILTY_START_TIME:
if (self->availabilityStartTime)
gst_date_time_unref (self->availabilityStartTime);
self->availabilityStartTime = g_value_get_boxed (value);
self->availabilityStartTime = g_value_dup_boxed (value);
break;
case PROP_MPD_ROOT_AVAILABILTY_END_TIME:
if (self->availabilityEndTime)
gst_date_time_unref (self->availabilityEndTime);
self->availabilityEndTime = g_value_get_boxed (value);
self->availabilityEndTime = g_value_dup_boxed (value);
break;
case PROP_MPD_ROOT_PUBLISH_TIME:
if (self->publishTime)
gst_date_time_unref (self->publishTime);
self->publishTime = g_value_get_boxed (value);
self->publishTime = g_value_dup_boxed (value);
break;
case PROP_MPD_ROOT_MEDIA_PRESENTATION_DURATION:
self->mediaPresentationDuration = g_value_get_uint64 (value);
......
......@@ -51,21 +51,22 @@ GST_DEBUG_CATEGORY_STATIC (ldac_enc_debug);
#define parent_class gst_ldac_enc_parent_class
G_DEFINE_TYPE (GstLdacEnc, gst_ldac_enc, GST_TYPE_AUDIO_ENCODER);
#define SAMPLE_RATES "44100, 48000, 88200, 96000"
static GstStaticPadTemplate ldac_enc_sink_factory =
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
GST_STATIC_CAPS
("audio/x-raw, format=(string) { S16LE, S24LE, S32LE, F32LE }, "
"rate = (int) { 44100, 48000, 88200, 96000 }, "
"channels = (int) [ 1, 2 ] "));
"rate = (int) { " SAMPLE_RATES " }, channels = (int) [ 1, 2 ] "));
static GstStaticPadTemplate ldac_enc_src_factory =
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
GST_STATIC_CAPS ("audio/x-ldac, "
"rate = (int) { 44100, 48000, 88200, 96000 }, "
"rate = (int) { " SAMPLE_RATES " }, "
"channels = (int) 1, channel-mode = (string)mono; "
"audio/x-ldac, "
"rate = (int) { 44100, 48000, 882000, 96000 }, "
"channels = (int) 2, " "channel-mode = (string) { dual, stereo }"));
"rate = (int) { " SAMPLE_RATES " }, "
"channels = (int) 2, channel-mode = (string) { dual, stereo }"));
enum
{
......
......@@ -4,8 +4,9 @@ ldac_sources = [
]
ldac_dep = cc.find_library('ldacBT_enc', required : get_option('ldac'))
ldac_hdr = cc.has_header('ldac/ldacBT.h', required: get_option('ldac'))
if ldac_dep.found()
if ldac_dep.found() and ldac_hdr
gstldac = library('gstldac',
ldac_sources,
c_args : gst_plugins_bad_args,
......
......@@ -37,6 +37,25 @@
GST_DEBUG_CATEGORY_EXTERN (gst_debug_srtobject);
#define GST_CAT_DEFAULT gst_debug_srtobject
#if SRT_VERSION_VALUE > 0x10402
#define SRTSOCK_ERROR_DEBUG ("libsrt reported: %s", srt_rejectreason_str (reason))
#else
/* srt_rejectreason_str() is unavailable in libsrt 1.4.2 and prior due to
* unexported symbol. See https://github.com/Haivision/srt/pull/1728. */
#define SRTSOCK_ERROR_DEBUG ("libsrt reported reject reason code %d", reason)
#endif
/* Define options added in later revisions */
#if SRT_VERSION_VALUE < 0x10402
#define SRTO_DRIFTTRACER 37
/* We can't define SRTO_BINDTODEVICE since it depends on configuration flags *sigh* */
#define SRTO_RETRANSMITALGO 61
#endif
#define ELEMENT_WARNING_SRTSOCK_ERROR(code, reason) \
GST_ELEMENT_WARNING (srtobject->element, RESOURCE, code, \
("Error on SRT socket. Trying to reconnect."), SRTSOCK_ERROR_DEBUG)
enum
{
PROP_URI = 1,
......@@ -51,6 +70,7 @@ enum
PROP_STATS,
PROP_WAIT_FOR_CONNECTION,
PROP_STREAMID,
PROP_AUTHENTICATION,
PROP_LAST
};
......@@ -132,6 +152,54 @@ static const struct srt_constant_params srt_params[] = {
};
/* *INDENT-ON* */
typedef struct
{
const gchar *name;
SRT_SOCKOPT opt;
GType gtype;
} SrtOption;
SrtOption srt_options[] = {
{"mss", SRTO_MSS, G_TYPE_INT},
{"fc", SRTO_FC, G_TYPE_INT},
{"sndbuf", SRTO_SNDBUF, G_TYPE_INT},
{"rcvbuf", SRTO_RCVBUF, G_TYPE_INT},
{"maxbw", SRTO_MAXBW, G_TYPE_INT64},
{"tsbpdmode", SRTO_TSBPDMODE, G_TYPE_BOOLEAN},
{"latency", SRTO_LATENCY, G_TYPE_INT},
{"inputbw", SRTO_INPUTBW, G_TYPE_INT64},
{"oheadbw", SRTO_OHEADBW, G_TYPE_INT},
{"passphrase", SRTO_PASSPHRASE, G_TYPE_STRING},
{"pbkeylen", SRTO_PBKEYLEN, G_TYPE_INT},
{"ipttl", SRTO_IPTTL, G_TYPE_INT},
{"iptos", SRTO_IPTOS, G_TYPE_INT},
{"tlpktdrop", SRTO_TLPKTDROP, G_TYPE_BOOLEAN},
{"snddropdelay", SRTO_SNDDROPDELAY, G_TYPE_INT},
{"nakreport", SRTO_NAKREPORT, G_TYPE_BOOLEAN},
{"conntimeo", SRTO_CONNTIMEO, G_TYPE_INT},
{"drifttracer", SRTO_DRIFTTRACER, G_TYPE_BOOLEAN},
{"lossmaxttl", SRTO_LOSSMAXTTL, G_TYPE_INT},
{"rcvlatency", SRTO_RCVLATENCY, G_TYPE_INT},
{"peerlatency", SRTO_PEERLATENCY, G_TYPE_INT},
{"minversion", SRTO_MINVERSION, G_TYPE_INT},
{"streamid", SRTO_STREAMID, G_TYPE_STRING},
{"congestion", SRTO_CONGESTION, G_TYPE_STRING},
{"messageapi", SRTO_MESSAGEAPI, G_TYPE_BOOLEAN},
{"payloadsize", SRTO_PAYLOADSIZE, G_TYPE_INT},
{"transtype", SRTO_TRANSTYPE, G_TYPE_INT},
{"kmrefreshrate", SRTO_KMREFRESHRATE, G_TYPE_INT},
{"kmpreannounce", SRTO_KMPREANNOUNCE, G_TYPE_INT},
{"enforcedencryption", SRTO_ENFORCEDENCRYPTION, G_TYPE_BOOLEAN},
{"ipv6only", SRTO_IPV6ONLY, G_TYPE_INT},
{"peeridletimeo", SRTO_PEERIDLETIMEO, G_TYPE_INT},
#if SRT_VERSION_VALUE >= 0x10402
{"bindtodevice", SRTO_BINDTODEVICE, G_TYPE_STRING},
#endif
{"packetfilter", SRTO_PACKETFILTER, G_TYPE_STRING},
{"retransmitalgo", SRTO_RETRANSMITALGO, G_TYPE_INT},
{NULL}
};
static gint srt_init_refcount = 0;
static GSocketAddress *
......@@ -184,12 +252,69 @@ name_resolve:
}
}
static gboolean
gst_srt_object_apply_socket_option (SRTSOCKET sock, SrtOption * option,
const GValue * value, GError ** error)
{
union
{
int32_t i;
int64_t i64;
gboolean b;
const gchar *c;
} u;
const void *optval = &u;
gint optlen;
if (!G_VALUE_HOLDS (value, option->gtype)) {
goto bad_type;
}
switch (option->gtype) {
case G_TYPE_INT:
u.i = g_value_get_int (value);
optlen = sizeof u.i;
break;
case G_TYPE_INT64:
u.i64 = g_value_get_int64 (value);
optlen = sizeof u.i64;
break;
case G_TYPE_BOOLEAN:
u.b = g_value_get_boolean (value);
optlen = sizeof u.b;
break;
case G_TYPE_STRING:
u.c = g_value_get_string (value);
optval = u.c;
optlen = u.c ? strlen (u.c) : 0;
if (optlen == 0) {
return TRUE;
}
break;
default:
goto bad_type;
}
if (srt_setsockopt (sock, 0, option->opt, optval, optlen)) {
g_set_error (error, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
"failed to set %s (reason: %s)", option->name, srt_getlasterror_str ());
return FALSE;
}
return TRUE;
bad_type:
g_set_error (error, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
"option %s has unsupported type", option->name);
return FALSE;
}
static gboolean
gst_srt_object_set_common_params (SRTSOCKET sock, GstSRTObject * srtobject,
GError ** error)
{
const struct srt_constant_params *params = srt_params;
const gchar *passphrase;
SrtOption *option = srt_options;
GST_OBJECT_LOCK (srtobject->element);
......@@ -202,53 +327,15 @@ gst_srt_object_set_common_params (SRTSOCKET sock, GstSRTObject * srtobject,
}
}
passphrase = gst_structure_get_string (srtobject->parameters, "passphrase");
if (passphrase != NULL && passphrase[0] != '\0') {
int32_t pbkeylen;
if (srt_setsockopt (sock, 0, SRTO_PASSPHRASE, passphrase,
strlen (passphrase))) {
g_set_error (error, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
"failed to set passphrase (reason: %s)", srt_getlasterror_str ());
goto err;
}
if (!gst_structure_get_int (srtobject->parameters, "pbkeylen", &pbkeylen)) {
pbkeylen = GST_SRT_DEFAULT_PBKEYLEN;
}
if (srt_setsockopt (sock, 0, SRTO_PBKEYLEN, &pbkeylen, sizeof pbkeylen)) {
g_set_error (error, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
"failed to set pbkeylen (reason: %s)", srt_getlasterror_str ());
goto err;
}
}
{
int32_t latency;
for (; option->name; ++option) {
const GValue *val;
if (!gst_structure_get_int (srtobject->parameters, "latency", &latency))
latency = GST_SRT_DEFAULT_LATENCY;
if (srt_setsockopt (sock, 0, SRTO_LATENCY, &latency, sizeof latency)) {
g_set_error (error, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
"failed to set latency (reason: %s)", srt_getlasterror_str ());
val = gst_structure_get_value (srtobject->parameters, option->name);
if (val && !gst_srt_object_apply_socket_option (sock, option, val, error)) {
goto err;
}
}
if (gst_structure_has_field (srtobject->parameters, "streamid")) {
const gchar *streamid;
streamid = gst_structure_get_string (srtobject->parameters, "streamid");
if (streamid != NULL && streamid[0] != '\0') {
if (srt_setsockopt (sock, 0, SRTO_STREAMID, streamid, strlen (streamid))) {
g_set_error (error, GST_LIBRARY_ERROR, GST_LIBRARY_ERROR_SETTINGS,
"failed to set stream ID (reason: %s)", srt_getlasterror_str ());
}
}
}
GST_OBJECT_UNLOCK (srtobject->element);
return TRUE;
......@@ -338,7 +425,8 @@ gst_srt_object_set_property_helper (GstSRTObject * srtobject,
gst_structure_set_value (srtobject->parameters, "passphrase", value);
break;
case PROP_PBKEYLEN:
gst_structure_set_value (srtobject->parameters, "pbkeylen", value);
gst_structure_set (srtobject->parameters, "pbkeylen", G_TYPE_INT,
g_value_get_enum (value), NULL);
break;
case PROP_WAIT_FOR_CONNECTION:
srtobject->wait_for_connection = g_value_get_boolean (value);
......@@ -346,6 +434,9 @@ gst_srt_object_set_property_helper (GstSRTObject * srtobject,
case PROP_STREAMID:
gst_structure_set_value (srtobject->parameters, "streamid", value);
break;
case PROP_AUTHENTICATION:
srtobject->authentication = g_value_get_boolean (value);
break;
default:
goto err;
}
......@@ -403,8 +494,8 @@ gst_srt_object_get_property_helper (GstSRTObject * srtobject,
GstSRTKeyLength v;
GST_OBJECT_LOCK (srtobject->element);
if (!gst_structure_get_enum (srtobject->parameters, "pbkeylen",
GST_TYPE_SRT_KEY_LENGTH, (gint *) & v)) {
if (!gst_structure_get_int (srtobject->parameters, "pbkeylen",
(gint *) & v)) {
GST_WARNING_OBJECT (srtobject->element, "Failed to get 'pbkeylen'");
v = GST_SRT_KEY_LENGTH_NO_KEY;
}
......@@ -450,6 +541,9 @@ gst_srt_object_get_property_helper (GstSRTObject * srtobject,
gst_structure_get_string (srtobject->parameters, "streamid"));
GST_OBJECT_UNLOCK (srtobject->element);
break;
case PROP_AUTHENTICATION:
g_value_set_boolean (value, srtobject->authentication);
break;
default:
return FALSE;
}
......@@ -594,6 +688,22 @@ gst_srt_object_install_properties_helper (GObjectClass * gobject_class)
"Stream ID for the SRT access control", "",
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
G_PARAM_STATIC_STRINGS));
/**
* GstSRTSink:authentication:
*
* Boolean to authenticate a connection. If TRUE,
* the incoming connection is authenticated. Else,
* all the connections are accepted.
*
* Since: 1.20
*
*/
g_object_class_install_property (gobject_class, PROP_AUTHENTICATION,
g_param_spec_boolean ("authentication",
"Authentication",
"Authenticate a connection",
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
......@@ -636,6 +746,65 @@ gst_srt_object_set_int_value (GstStructure * s, const gchar * key,
(gint) g_ascii_strtoll (value, NULL, 10), NULL);
}
static void
gst_srt_object_set_int64_value (GstStructure * s, const gchar * key,
const gchar * value)
{
gst_structure_set (s, key, G_TYPE_INT64,
g_ascii_strtoll (value, NULL, 10), NULL);
}
static void
gst_srt_object_set_boolean_value (GstStructure * s, const gchar * key,
const gchar * value)
{
gboolean bool_val;
static const gchar *true_names[] = {
"1", "yes", "on", "true", NULL
};
static const gchar *false_names[] = {
"0", "no", "off", "false", NULL
};
if (g_strv_contains (true_names, value)) {
bool_val = TRUE;
} else if (g_strv_contains (false_names, value)) {
bool_val = FALSE;
} else {
return;
}
gst_structure_set (s, key, G_TYPE_BOOLEAN, bool_val, NULL);
}
static void
gst_srt_object_set_socket_option (GstStructure * s, const gchar * key,
const gchar * value)
{
SrtOption *option = srt_options;
for (; option; ++option) {
if (g_str_equal (key, option->name)) {
switch (option->gtype) {
case G_TYPE_INT:
gst_srt_object_set_int_value (s, key, value);
break;
case G_TYPE_INT64:
gst_srt_object_set_int64_value (s, key, value);
break;
case G_TYPE_STRING:
gst_srt_object_set_string_value (s, key, value);
break;
case G_TYPE_BOOLEAN:
gst_srt_object_set_boolean_value (s, key, value);
break;
}
break;
}
}
}
static void
gst_srt_object_validate_parameters (GstStructure * s, GstUri * uri)
{
......@@ -724,17 +893,10 @@ gst_srt_object_set_uri (GstSRTObject * srtobject, const gchar * uri,
gst_srt_object_set_string_value (srtobject->parameters, key, value);
} else if (!g_strcmp0 ("localport", key)) {
gst_srt_object_set_uint_value (srtobject->parameters, key, value);
} else if (!g_strcmp0 ("passphrase", key)) {
gst_srt_object_set_string_value (srtobject->parameters, key, value);
} else if (!g_strcmp0 ("pbkeylen", key)) {
gst_srt_object_set_enum_value (srtobject->parameters,
GST_TYPE_SRT_KEY_LENGTH, key, value);
} else if (!g_strcmp0 ("streamid", key)) {
gst_srt_object_set_string_value (srtobject->parameters, key, value);
} else if (!g_strcmp0 ("latency", key)) {
gst_srt_object_set_int_value (srtobject->parameters, key, value);
} else if (!g_strcmp0 ("poll-timeout", key)) {
gst_srt_object_set_int_value (srtobject->parameters, key, value);
} else {
gst_srt_object_set_socket_option (srtobject->parameters, key, value);
}
}
......@@ -838,6 +1000,62 @@ thread_func (gpointer data)
}
}
static GSocketAddress *
peeraddr_to_g_socket_address (const struct sockaddr *peeraddr)
{
gsize peeraddr_len;
switch (peeraddr->sa_family) {
case AF_INET:
peeraddr_len = sizeof (struct sockaddr_in);
break;
case AF_INET6:
peeraddr_len = sizeof (struct sockaddr_in6);
break;
default:
g_warning ("Unsupported address family %d", peeraddr->sa_family);
return NULL;
}
return g_socket_address_new_from_native ((gpointer) peeraddr, peeraddr_len);
}
static gint
srt_listen_callback_func (GstSRTObject * self, SRTSOCKET sock, int hs_version,
const struct sockaddr *peeraddr, const char *stream_id)
{
GSocketAddress *addr = peeraddr_to_g_socket_address (peeraddr);
if (!addr) {
GST_WARNING_OBJECT (self->element,
"Invalid peer address. Rejecting sink %d streamid: %s", sock,
stream_id);
return -1;
}
if (self->authentication) {
gboolean authenticated = FALSE;
/* notifying caller-connecting */
g_signal_emit_by_name (self->element, "caller-connecting", addr,
stream_id, &authenticated);
if (!authenticated)
goto reject;
}
GST_DEBUG_OBJECT (self->element,
"Accepting sink %d streamid: %s", sock, stream_id);
g_object_unref (addr);
return 0;
reject:
/* notifying caller-rejected */
GST_WARNING_OBJECT (self->element,
"Rejecting sink %d streamid: %s", sock, stream_id);
g_signal_emit_by_name (self->element, "caller-rejected", addr, stream_id);
g_object_unref (addr);
return -1;
}
static gboolean
gst_srt_object_wait_connect (GstSRTObject * srtobject,
GCancellable * cancellable, gpointer sa, size_t sa_len, GError ** error)
......@@ -916,10 +1134,16 @@ gst_srt_object_wait_connect (GstSRTObject * srtobject,
srtobject->listener_sock = sock;
/* Register the SRT listen callback */
if (srt_listen_callback (srtobject->listener_sock,
(srt_listen_callback_fn *) srt_listen_callback_func, srtobject)) {
goto failed;
}
srtobject->thread =
g_thread_try_new ("GstSRTObjectListener", thread_func, srtobject, error);
if (*error != NULL) {
if (srtobject->thread == NULL) {
GST_ERROR_OBJECT (srtobject->element, "Failed to start thread");
goto failed;
}
......@@ -1307,11 +1531,11 @@ gst_srt_object_read (GstSRTObject * srtobject,
SRTSOCKET rsock;
gint rsocklen = 1;
int pollret;
SRTSOCKET wsock;
gint wsocklen = 1;
pollret = srt_epoll_wait (poll_id, &rsock,
&rsocklen, 0, 0, poll_timeout, NULL, 0, NULL, 0);
if (pollret < 0) {
if (srt_epoll_wait (poll_id, &rsock, &rsocklen, &wsock, &wsocklen,
poll_timeout, NULL, 0, NULL, 0) < 0) {
gint srt_errno = srt_getlasterror (NULL);
if (srt_errno != SRT_ETIMEOUT) {
......@@ -1320,34 +1544,30 @@ gst_srt_object_read (GstSRTObject * srtobject,
continue;
}
if (rsocklen < 0) {
GST_WARNING_OBJECT (srtobject->element,
"abnormal SRT socket is detected");
srt_close (rsock);
}
if (wsocklen == 1 && rsocklen == 1) {
/* Socket reported in wsock AND rsock signifies an error. */
gint reason = srt_getrejectreason (wsock);
gboolean is_auth_error = (reason == SRT_REJ_BADSECRET
|| reason == SRT_REJ_UNSECURE);
if (is_auth_error) {
ELEMENT_WARNING_SRTSOCK_ERROR (NOT_AUTHORIZED, reason);
}
switch (srt_getsockstate (rsock)) {
case SRTS_BROKEN:
case SRTS_NONEXIST:
case SRTS_CLOSED:
if (connection_mode == GST_SRT_CONNECTION_MODE_LISTENER) {
/* Caller has been disappeared. */
return 0;
} else {
GST_WARNING_OBJECT (srtobject->element,
"Invalid SRT socket. Trying to reconnect");
gst_srt_object_close (srtobject);
if (!gst_srt_object_open_internal (srtobject, cancellable, error)) {
return -1;
}
continue;
if (connection_mode == GST_SRT_CONNECTION_MODE_LISTENER) {
/* Caller has disappeared. */
return 0;
} else {
if (!is_auth_error) {
ELEMENT_WARNING_SRTSOCK_ERROR (READ, reason);
}
case SRTS_CONNECTED:
/* good to go */
break;
default:
/* not-ready */
continue;
gst_srt_object_close (srtobject);
if (!gst_srt_object_open_internal (srtobject, cancellable, error)) {
return -1;
}
}
continue;
}
......@@ -1517,8 +1737,10 @@ gst_srt_object_write_one (GstSRTObject * srtobject,
gint poll_timeout;
const guint8 *msg = mapinfo->data;
gint payload_size, optlen = 1;
gboolean wait_for_connection;
GST_OBJECT_LOCK (srtobject->element);
wait_for_connection = srtobject->wait_for_connection;
if (!gst_structure_get_int (srtobject->parameters, "poll-timeout",
&poll_timeout)) {
poll_timeout = GST_SRT_DEFAULT_POLL_TIMEOUT;
......@@ -1534,6 +1756,8 @@ gst_srt_object_write_one (GstSRTObject * srtobject,
}
while (len < mapinfo->size) {
SRTSOCKET rsock;
gint rsocklen = 1;
SRTSOCKET wsock;
gint wsocklen = 1;
......@@ -1544,30 +1768,33 @@ gst_srt_object_write_one (GstSRTObject * srtobject,
break;
}
if (srt_epoll_wait (srtobject->poll_id, 0, 0, &wsock,
if (!wait_for_connection &&
srt_getsockstate (srtobject->sock) == SRTS_CONNECTING) {
GST_LOG_OBJECT (srtobject->element,
"Not connected yet. Dropping the buffer.");
break;
}
if (srt_epoll_wait (srtobject->poll_id, &rsock, &rsocklen, &wsock,
&wsocklen, poll_timeout, NULL, 0, NULL, 0) < 0) {
continue;
}
switch (srt_getsockstate (wsock)) {
case SRTS_BROKEN:
case SRTS_NONEXIST:
case SRTS_CLOSED:
GST_WARNING_OBJECT (srtobject->element,
"Invalid SRT socket. Trying to reconnect");
gst_srt_object_close (srtobject);
if (!gst_srt_object_open_internal (srtobject, cancellable, error)) {
return -1;
}
continue;
case SRTS_CONNECTED:
/* good to go */
GST_LOG_OBJECT (srtobject->element, "good to go");
break;
default:
GST_WARNING_OBJECT (srtobject->element, "not ready");
/* not-ready */
continue;
if (wsocklen == 1 && rsocklen == 1) {
/* Socket reported in wsock AND rsock signifies an error. */
gint reason = srt_getrejectreason (wsock);
if (reason == SRT_REJ_BADSECRET || reason == SRT_REJ_UNSECURE) {
ELEMENT_WARNING_SRTSOCK_ERROR (NOT_AUTHORIZED, reason);
} else {
ELEMENT_WARNING_SRTSOCK_ERROR (WRITE, reason);
}
gst_srt_object_close (srtobject);
if (!gst_srt_object_open_internal (srtobject, cancellable, error)) {
return -1;
}
continue;
}
if (srt_getsockflag (wsock, SRTO_PAYLOADSIZE, &payload_size, &optlen)) {
......
......@@ -70,6 +70,8 @@ struct _GstSRTObject
gboolean wait_for_connection;
gboolean authentication;
guint64 previous_bytes;
};
......
......@@ -56,7 +56,8 @@ enum
{
SIG_CALLER_ADDED,
SIG_CALLER_REMOVED,
SIG_CALLER_REJECTED,
SIG_CALLER_CONNECTING,
LAST_SIGNAL
};
......@@ -67,6 +68,10 @@ static void gst_srt_sink_uri_handler_init (gpointer g_iface,
static gchar *gst_srt_sink_uri_get_uri (GstURIHandler * handler);
static gboolean gst_srt_sink_uri_set_uri (GstURIHandler * handler,
const gchar * uri, GError ** error);
static gboolean default_caller_connecting (GstSRTSink * self,
GSocketAddress * addr, const gchar * username, gpointer data);
static gboolean authentication_accumulator (GSignalInvocationHint * ihint,
GValue * return_accu, const GValue * handler_return, gpointer data);
#define gst_srt_sink_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstSRTSink, gst_srt_sink,
......@@ -74,6 +79,25 @@ G_DEFINE_TYPE_WITH_CODE (GstSRTSink, gst_srt_sink,
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_srt_sink_uri_handler_init)
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "srtsink", 0, "SRT Sink"));
static gboolean
default_caller_connecting (GstSRTSink * self,
GSocketAddress * addr, const gchar * stream_id, gpointer data)
{
/* Accept all connections. */
return TRUE;
}
static gboolean
authentication_accumulator (GSignalInvocationHint * ihint,
GValue * return_accu, const GValue * handler_return, gpointer data)
{
gboolean ret = g_value_get_boolean (handler_return);
/* Handlers return TRUE on authentication success and we want to stop on
* the first failure. */
g_value_set_boolean (return_accu, ret);
return ret;
}
static void
gst_srt_sink_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
......@@ -122,14 +146,10 @@ static gboolean
gst_srt_sink_start (GstBaseSink * bsink)
{
GstSRTSink *self = GST_SRT_SINK (bsink);
GstSRTConnectionMode connection_mode = GST_SRT_CONNECTION_MODE_NONE;
GError *error = NULL;
gboolean ret = FALSE;
gst_structure_get_enum (self->srtobject->parameters, "mode",
GST_TYPE_SRT_CONNECTION_MODE, (gint *) & connection_mode);
ret = gst_srt_object_open (self->srtobject, self->cancellable, &error);
if (!ret) {
......@@ -280,6 +300,7 @@ gst_srt_sink_class_init (GstSRTSinkClass * klass)
gobject_class->set_property = gst_srt_sink_set_property;
gobject_class->get_property = gst_srt_sink_get_property;
gobject_class->finalize = gst_srt_sink_finalize;
klass->caller_connecting = default_caller_connecting;
/**
* GstSRTSink::caller-added:
......@@ -308,6 +329,41 @@ gst_srt_sink_class_init (GstSRTSinkClass * klass)
caller_added), NULL, NULL, NULL, G_TYPE_NONE,
2, G_TYPE_INT, G_TYPE_SOCKET_ADDRESS);
/**
* GstSRTSink::caller-rejected:
* @gstsrtsink: the srtsink element that emitted this signal
* @addr: the #GSocketAddress that describes the client socket
* @stream_id: the stream Id to which the caller wants to connect
*
* A caller's connection to srtsink in listener mode has been rejected.
*
* Since: 1.20
*
*/
signals[SIG_CALLER_REJECTED] =
g_signal_new ("caller-rejected", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE,
2, G_TYPE_SOCKET_ADDRESS, G_TYPE_STRING);
/**
* GstSRTSink::caller-connecting:
* @gstsrtsink: the srtsink element that emitted this signal
* @addr: the #GSocketAddress that describes the client socket
* @stream_id: the stream Id to which the caller wants to connect
*
* Whether to accept or reject a caller's connection to srtsink in listener mode.
* The Caller's connection is rejected if the callback returns FALSE, else
* the connection is accepeted.
*
* Since: 1.20
*
*/
signals[SIG_CALLER_CONNECTING] =
g_signal_new ("caller-connecting", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSRTSinkClass, caller_connecting),
authentication_accumulator, NULL, NULL, G_TYPE_BOOLEAN,
2, G_TYPE_SOCKET_ADDRESS, G_TYPE_STRING);
gst_srt_object_install_properties_helper (gobject_class);
gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
......
......@@ -56,6 +56,10 @@ struct _GstSRTSinkClass {
void (*caller_added) (GstSRTSink *self, int sock, GSocketAddress * addr);
void (*caller_removed) (GstSRTSink *self, int sock, GSocketAddress * addr);
void (*caller_rejected) (GstSRTSink *self, GSocketAddress * peer_address,
const gchar * stream_id, gpointer data);
gboolean (*caller_connecting) (GstSRTSink *self, GSocketAddress * peer_address,
const gchar * stream_id, gpointer data);
};
GType gst_srt_sink_get_type (void);
......
......@@ -59,7 +59,8 @@ enum
{
SIG_CALLER_ADDED,
SIG_CALLER_REMOVED,
SIG_CALLER_REJECTED,
SIG_CALLER_CONNECTING,
LAST_SIGNAL
};
......@@ -70,6 +71,10 @@ static void gst_srt_src_uri_handler_init (gpointer g_iface,
static gchar *gst_srt_src_uri_get_uri (GstURIHandler * handler);
static gboolean gst_srt_src_uri_set_uri (GstURIHandler * handler,
const gchar * uri, GError ** error);
static gboolean src_default_caller_connecting (GstSRTSrc * self,
GSocketAddress * addr, const gchar * username, gpointer data);
static gboolean src_authentication_accumulator (GSignalInvocationHint * ihint,
GValue * return_accu, const GValue * handler_return, gpointer data);
#define gst_srt_src_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstSRTSrc, gst_srt_src,
......@@ -77,6 +82,25 @@ G_DEFINE_TYPE_WITH_CODE (GstSRTSrc, gst_srt_src,
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, gst_srt_src_uri_handler_init)
GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "srtsrc", 0, "SRT Source"));
static gboolean
src_default_caller_connecting (GstSRTSrc * self,
GSocketAddress * addr, const gchar * stream_id, gpointer data)
{
/* Accept all connections. */
return TRUE;
}
static gboolean
src_authentication_accumulator (GSignalInvocationHint * ihint,
GValue * return_accu, const GValue * handler_return, gpointer data)
{
gboolean ret = g_value_get_boolean (handler_return);
/* Handlers return TRUE on authentication success and we want to stop on
* the first failure. */
g_value_set_boolean (return_accu, ret);
return ret;
}
static gboolean
gst_srt_src_start (GstBaseSrc * bsrc)
{
......@@ -333,11 +357,12 @@ gst_srt_src_class_init (GstSRTSrcClass * klass)
gobject_class->set_property = gst_srt_src_set_property;
gobject_class->get_property = gst_srt_src_get_property;
gobject_class->finalize = gst_srt_src_finalize;
klass->caller_connecting = src_default_caller_connecting;
/**
* GstSRTSrc::caller-added:
* @gstsrtsink: the srtsink element that emitted this signal
* @sock: the client socket descriptor that was added to srtsink
* @gstsrtsrc: the srtsrc element that emitted this signal
* @sock: the client socket descriptor that was added to srtsrc
* @addr: the #GSocketAddress that describes the @sock
*
* The given socket descriptor was added to srtsink.
......@@ -349,11 +374,11 @@ gst_srt_src_class_init (GstSRTSrcClass * klass)
/**
* GstSRTSrc::caller-removed:
* @gstsrtsink: the srtsink element that emitted this signal
* @sock: the client socket descriptor that was added to srtsink
* @gstsrtsrc: the srtsrc element that emitted this signal
* @sock: the client socket descriptor that was added to srtsrc
* @addr: the #GSocketAddress that describes the @sock
*
* The given socket descriptor was removed from srtsink.
* The given socket descriptor was removed from srtsrc.
*/
signals[SIG_CALLER_REMOVED] =
g_signal_new ("caller-removed", G_TYPE_FROM_CLASS (klass),
......@@ -361,6 +386,41 @@ gst_srt_src_class_init (GstSRTSrcClass * klass)
caller_added), NULL, NULL, NULL, G_TYPE_NONE,
2, G_TYPE_INT, G_TYPE_SOCKET_ADDRESS);
/**
* GstSRTSrc::caller-rejected:
* @gstsrtsrc: the srtsrc element that emitted this signal
* @addr: the #GSocketAddress that describes the client socket
* @stream_id: the stream Id to which the caller wants to connect
*
* A caller's connection to srtsrc in listener mode has been rejected.
*
* Since: 1.20
*
*/
signals[SIG_CALLER_REJECTED] =
g_signal_new ("caller-rejected", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSRTSrcClass, caller_rejected),
NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_SOCKET_ADDRESS, G_TYPE_STRING);
/**
* GstSRTSrc::caller-connecting:
* @gstsrtsrc: the srtsrc element that emitted this signal
* @addr: the #GSocketAddress that describes the client socket
* @stream_id: the stream Id to which the caller wants to connect
*
* Whether to accept or reject a caller's connection to srtsrc in listener mode.
* The Caller's connection is rejected if the callback returns FALSE, else
* the connection is accepeted.
*
* Since: 1.20
*
*/
signals[SIG_CALLER_CONNECTING] =
g_signal_new ("caller-connecting", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstSRTSrcClass, caller_connecting),
src_authentication_accumulator, NULL, NULL, G_TYPE_BOOLEAN,
2, G_TYPE_SOCKET_ADDRESS, G_TYPE_STRING);
gst_srt_object_install_properties_helper (gobject_class);
gst_element_class_add_static_pad_template (gstelement_class, &src_template);
......
......@@ -58,6 +58,10 @@ struct _GstSRTSrcClass {
void (*caller_added) (GstSRTSrc *self, int sock, GSocketAddress * addr);
void (*caller_removed) (GstSRTSrc *self, int sock, GSocketAddress * addr);
void (*caller_rejected) (GstSRTSrc *self, GSocketAddress * peer_address,
const gchar * stream_id, gpointer data);
gboolean (*caller_connecting) (GstSRTSrc *self, GSocketAddress * peer_address,
const gchar * stream_id, gpointer data);
};
GType gst_srt_src_get_type (void);
......
......@@ -949,7 +949,6 @@ _collate_ice_gathering_states (GstWebRTCBin * webrtc)
GstWebRTCDTLSTransport *dtls_transport;
GstWebRTCICETransport *transport;
GstWebRTCICEGatheringState ice_state;
gboolean rtcp_mux = FALSE;
if (rtp_trans->stopped || stream == NULL) {
GST_TRACE_OBJECT (webrtc, "transceiver %p stopped or unassociated",
......@@ -963,8 +962,6 @@ _collate_ice_gathering_states (GstWebRTCBin * webrtc)
GST_TRACE_OBJECT (webrtc, "transceiver %p has no mid", rtp_trans);
}
g_object_get (stream, "rtcp-mux", &rtcp_mux, NULL);
dtls_transport = webrtc_transceiver_get_dtls_transport (rtp_trans);
if (dtls_transport == NULL) {
GST_WARNING ("Transceiver %p has no DTLS transport", rtp_trans);
......@@ -1023,12 +1020,9 @@ _collate_peer_connection_states (GstWebRTCBin * webrtc)
for (i = 0; i < webrtc->priv->transceivers->len; i++) {
GstWebRTCRTPTransceiver *rtp_trans =
g_ptr_array_index (webrtc->priv->transceivers, i);
WebRTCTransceiver *trans = WEBRTC_TRANSCEIVER (rtp_trans);
TransportStream *stream = trans->stream;
GstWebRTCDTLSTransport *transport;
GstWebRTCICEConnectionState ice_state;
GstWebRTCDTLSTransportState dtls_state;
gboolean rtcp_mux = FALSE;
if (rtp_trans->stopped) {
GST_TRACE_OBJECT (webrtc, "transceiver %p stopped", rtp_trans);
......@@ -1039,7 +1033,6 @@ _collate_peer_connection_states (GstWebRTCBin * webrtc)
continue;
}
g_object_get (stream, "rtcp-mux", &rtcp_mux, NULL);
transport = webrtc_transceiver_get_dtls_transport (rtp_trans);
/* get transport state */
......@@ -2137,8 +2130,6 @@ _get_or_create_data_channel_transports (GstWebRTCBin * webrtc, guint session_id)
webrtc->priv->data_channel_transport = stream;
g_object_set (stream, "rtcp-mux", TRUE, NULL);
if (!(sctp_transport = webrtc->priv->sctp_transport)) {
sctp_transport = gst_webrtc_sctp_transport_new ();
sctp_transport->transport =
......@@ -2456,7 +2447,7 @@ static gboolean
sdp_media_from_transceiver (GstWebRTCBin * webrtc, GstSDPMedia * media,
GstWebRTCRTPTransceiver * trans, GstWebRTCSDPType type, guint media_idx,
GString * bundled_mids, guint bundle_idx, gchar * bundle_ufrag,
gchar * bundle_pwd, GArray * reserved_pts)
gchar * bundle_pwd, GArray * reserved_pts, GHashTable * all_mids)
{
/* TODO:
* rtp header extensions
......@@ -2598,10 +2589,18 @@ sdp_media_from_transceiver (GstWebRTCBin * webrtc, GstSDPMedia * media,
if (trans->mid) {
gst_sdp_media_add_attribute (media, "mid", trans->mid);
} else {
sdp_mid = g_strdup_printf ("%s%u", gst_sdp_media_get_media (media),
webrtc->priv->media_counter++);
gst_sdp_media_add_attribute (media, "mid", sdp_mid);
g_free (sdp_mid);
/* Make sure to avoid mid collisions */
while (TRUE) {
sdp_mid = g_strdup_printf ("%s%u", gst_sdp_media_get_media (media),
webrtc->priv->media_counter++);
if (g_hash_table_contains (all_mids, (gpointer) sdp_mid)) {
g_free (sdp_mid);
} else {
gst_sdp_media_add_attribute (media, "mid", sdp_mid);
g_hash_table_insert (all_mids, sdp_mid, NULL);
break;
}
}
}
/* TODO:
......@@ -2665,7 +2664,7 @@ gather_reserved_pts (GstWebRTCBin * webrtc)
static gboolean
_add_data_channel_offer (GstWebRTCBin * webrtc, GstSDPMessage * msg,
GstSDPMedia * media, GString * bundled_mids, guint bundle_idx,
gchar * bundle_ufrag, gchar * bundle_pwd)
gchar * bundle_ufrag, gchar * bundle_pwd, GHashTable * all_mids)
{
GstSDPMessage *last_offer = _get_latest_self_generated_sdp (webrtc);
gchar *ufrag, *pwd, *sdp_mid;
......@@ -2726,10 +2725,18 @@ _add_data_channel_offer (GstWebRTCBin * webrtc, GstSDPMessage * msg,
gst_sdp_media_add_attribute (media, "mid", mid);
} else {
sdp_mid = g_strdup_printf ("%s%u", gst_sdp_media_get_media (media),
webrtc->priv->media_counter++);
gst_sdp_media_add_attribute (media, "mid", sdp_mid);
g_free (sdp_mid);
/* Make sure to avoid mid collisions */
while (TRUE) {
sdp_mid = g_strdup_printf ("%s%u", gst_sdp_media_get_media (media),
webrtc->priv->media_counter++);
if (g_hash_table_contains (all_mids, (gpointer) sdp_mid)) {
g_free (sdp_mid);
} else {
gst_sdp_media_add_attribute (media, "mid", sdp_mid);
g_hash_table_insert (all_mids, sdp_mid, NULL);
break;
}
}
}
if (bundled_mids) {
......@@ -2754,11 +2761,14 @@ static GstSDPMessage *
_create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
GError ** error)
{
GstSDPMessage *ret;
GstSDPMessage *ret = NULL;
GString *bundled_mids = NULL;
gchar *bundle_ufrag = NULL;
gchar *bundle_pwd = NULL;
GArray *reserved_pts = NULL;
GHashTable *all_mids =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
GstSDPMessage *last_offer = _get_latest_self_generated_sdp (webrtc);
GList *seen_transceivers = NULL;
guint media_idx = 0;
......@@ -2830,6 +2840,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
if (trans->mid && g_strcmp0 (trans->mid, last_mid) == 0) {
GstSDPMedia *media;
const gchar *mid;
g_assert (!g_list_find (seen_transceivers, trans));
......@@ -2841,13 +2852,22 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
gst_sdp_media_copy (last_media, &media);
_media_replace_direction (media, trans->direction);
if (bundled_mids) {
const gchar *mid = gst_sdp_media_get_attribute_val (media, "mid");
mid = gst_sdp_media_get_attribute_val (media, "mid");
g_assert (mid);
g_assert (mid);
g_string_append_printf (bundled_mids, " %s", mid);
if (g_hash_table_contains (all_mids, mid)) {
gst_sdp_media_free (media);
g_set_error (error, GST_WEBRTC_BIN_ERROR,
GST_WEBRTC_BIN_ERROR_FAILED,
"Duplicate mid %s when creating offer", mid);
goto duplicate_mid;
}
g_hash_table_insert (all_mids, g_strdup (mid), NULL);
if (bundled_mids)
g_string_append_printf (bundled_mids, " %s", mid);
gst_sdp_message_add_media (ret, media);
media_idx++;
......@@ -2861,7 +2881,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
GstSDPMedia media = { 0, };
gst_sdp_media_init (&media);
if (_add_data_channel_offer (webrtc, ret, &media, bundled_mids, 0,
bundle_ufrag, bundle_pwd)) {
bundle_ufrag, bundle_pwd, all_mids)) {
gst_sdp_message_add_media (ret, &media);
media_idx++;
} else {
......@@ -2871,6 +2891,26 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
}
}
/* First, go over all transceivers and gather existing mids */
for (i = 0; i < webrtc->priv->transceivers->len; i++) {
GstWebRTCRTPTransceiver *trans;
trans = g_ptr_array_index (webrtc->priv->transceivers, i);
if (g_list_find (seen_transceivers, trans))
continue;
if (trans->mid) {
if (g_hash_table_contains (all_mids, trans->mid)) {
g_set_error (error, GST_WEBRTC_BIN_ERROR, GST_WEBRTC_BIN_ERROR_FAILED,
"Duplicate mid %s when creating offer", trans->mid);
goto duplicate_mid;
}
g_hash_table_insert (all_mids, g_strdup (trans->mid), NULL);
}
}
/* add any extra streams */
for (i = 0; i < webrtc->priv->transceivers->len; i++) {
GstWebRTCRTPTransceiver *trans;
......@@ -2897,7 +2937,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
if (sdp_media_from_transceiver (webrtc, &media, trans,
GST_WEBRTC_SDP_TYPE_OFFER, media_idx, bundled_mids, 0, bundle_ufrag,
bundle_pwd, reserved_pts)) {
bundle_pwd, reserved_pts, all_mids)) {
gst_sdp_message_add_media (ret, &media);
media_idx++;
} else {
......@@ -2906,12 +2946,14 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
if (webrtc->bundle_policy == GST_WEBRTC_BUNDLE_POLICY_NONE) {
g_array_free (reserved_pts, TRUE);
reserved_pts = NULL;
}
seen_transceivers = g_list_prepend (seen_transceivers, trans);
}
if (webrtc->bundle_policy != GST_WEBRTC_BUNDLE_POLICY_NONE) {
g_array_free (reserved_pts, TRUE);
reserved_pts = NULL;
}
/* add a data channel if exists and not renegotiated */
......@@ -2919,7 +2961,7 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
GstSDPMedia media = { 0, };
gst_sdp_media_init (&media);
if (_add_data_channel_offer (webrtc, ret, &media, bundled_mids, 0,
bundle_ufrag, bundle_pwd)) {
bundle_ufrag, bundle_pwd, all_mids)) {
gst_sdp_message_add_media (ret, &media);
media_idx++;
} else {
......@@ -2934,18 +2976,11 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
gst_sdp_message_add_attribute (ret, "group", mids);
g_free (mids);
bundled_mids = NULL;
}
if (bundle_ufrag)
g_free (bundle_ufrag);
if (bundle_pwd)
g_free (bundle_pwd);
/* FIXME: pre-emptively setup receiving elements when needed */
g_list_free (seen_transceivers);
if (webrtc->priv->last_generated_answer)
gst_webrtc_session_description_free (webrtc->priv->last_generated_answer);
webrtc->priv->last_generated_answer = NULL;
......@@ -2958,7 +2993,29 @@ _create_offer_task (GstWebRTCBin * webrtc, const GstStructure * options,
gst_webrtc_session_description_new (GST_WEBRTC_SDP_TYPE_OFFER, copy);
}
out:
if (reserved_pts)
g_array_free (reserved_pts, TRUE);
g_hash_table_unref (all_mids);
g_list_free (seen_transceivers);
if (bundle_ufrag)
g_free (bundle_ufrag);
if (bundle_pwd)
g_free (bundle_pwd);
if (bundled_mids)
g_string_free (bundled_mids, TRUE);
return ret;
duplicate_mid:
gst_sdp_message_uninit (ret);
ret = NULL;
goto out;
}
static void
......@@ -4028,7 +4085,7 @@ _update_transceiver_from_sdp_media (GstWebRTCBin * webrtc,
GstWebRTCRTPTransceiverDirection new_dir;
const GstSDPMedia *media = gst_sdp_message_get_media (sdp, media_idx);
GstWebRTCDTLSSetup new_setup;
gboolean new_rtcp_mux, new_rtcp_rsize;
gboolean new_rtcp_rsize;
ReceiveState receive_state = RECEIVE_STATE_UNSET;
int i;
......@@ -4098,8 +4155,6 @@ _update_transceiver_from_sdp_media (GstWebRTCBin * webrtc,
}
if (!bundled || bundle_idx == media_idx) {
new_rtcp_mux = _media_has_attribute_key (local_media, "rtcp-mux")
&& _media_has_attribute_key (remote_media, "rtcp-mux");
new_rtcp_rsize = _media_has_attribute_key (local_media, "rtcp-rsize")
&& _media_has_attribute_key (remote_media, "rtcp-rsize");
......@@ -4112,8 +4167,6 @@ _update_transceiver_from_sdp_media (GstWebRTCBin * webrtc,
g_object_unref (session);
}
}
g_object_set (stream, "rtcp-mux", new_rtcp_mux, NULL);
}
}
......@@ -4319,7 +4372,7 @@ _update_data_channel_from_sdp_media (GstWebRTCBin * webrtc,
/* data channel is always rtcp-muxed to avoid generating ICE candidates
* for RTCP */
g_object_set (stream, "rtcp-mux", TRUE, "dtls-client",
g_object_set (stream, "dtls-client",
new_setup == GST_WEBRTC_DTLS_SETUP_ACTIVE, NULL);
local_port = _get_sctp_port_from_media (local_media);
......
......@@ -138,35 +138,6 @@ _stop_thread (GstWebRTCICE * ice)
g_thread_unref (ice->priv->thread);
}
#if 0
static NiceComponentType
_webrtc_component_to_nice (GstWebRTCICEComponent comp)
{
switch (comp) {
case GST_WEBRTC_ICE_COMPONENT_RTP:
return NICE_COMPONENT_TYPE_RTP;
case GST_WEBRTC_ICE_COMPONENT_RTCP:
return NICE_COMPONENT_TYPE_RTCP;
default:
g_assert_not_reached ();
return 0;
}
}
static GstWebRTCICEComponent
_nice_component_to_webrtc (NiceComponentType comp)
{
switch (comp) {
case NICE_COMPONENT_TYPE_RTP:
return GST_WEBRTC_ICE_COMPONENT_RTP;
case NICE_COMPONENT_TYPE_RTCP:
return GST_WEBRTC_ICE_COMPONENT_RTCP;
default:
g_assert_not_reached ();
return 0;
}
}
#endif
struct NiceStreamItem
{
guint session_id;
......@@ -380,16 +351,6 @@ _add_turn_server (GstWebRTCICE * ice, struct NiceStreamItem *item,
g_free (uri);
break;
}
ret = nice_agent_set_relay_info (ice->priv->nice_agent,
item->nice_stream_id, NICE_COMPONENT_TYPE_RTCP,
gst_uri_get_host (turn_server), gst_uri_get_port (turn_server),
user, pass, relays[i]);
if (!ret) {
gchar *uri = gst_uri_to_string (turn_server);
GST_ERROR_OBJECT (ice, "Failed to set TURN server '%s'", uri);
g_free (uri);
break;
}
}
g_free (user);
g_free (pass);
......
......@@ -239,11 +239,11 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
/* RTCOutboundRTPStreamStats */
if (gst_structure_get_uint (source_stats, "sent-fir-count", &fir))
if (gst_structure_get_uint (source_stats, "recv-fir-count", &fir))
gst_structure_set (out, "fir-count", G_TYPE_UINT, fir, NULL);
if (gst_structure_get_uint (source_stats, "sent-pli-count", &pli))
if (gst_structure_get_uint (source_stats, "recv-pli-count", &pli))
gst_structure_set (out, "pli-count", G_TYPE_UINT, pli, NULL);
if (gst_structure_get_uint (source_stats, "sent-nack-count", &nack))
if (gst_structure_get_uint (source_stats, "recv-nack-count", &nack))
gst_structure_set (out, "nack-count", G_TYPE_UINT, nack, NULL);
/* XXX: mediaType, trackId, sliCount, qpSum */
......@@ -391,11 +391,11 @@ _get_stats_from_rtp_source_stats (GstWebRTCBin * webrtc,
if (gst_structure_get_uint64 (source_stats, "octets-received", &bytes))
gst_structure_set (in, "bytes-received", G_TYPE_UINT64, bytes, NULL);
if (gst_structure_get_uint (source_stats, "recv-fir-count", &fir))
if (gst_structure_get_uint (source_stats, "sent-fir-count", &fir))
gst_structure_set (in, "fir-count", G_TYPE_UINT, fir, NULL);
if (gst_structure_get_uint (source_stats, "recv-pli-count", &pli))
if (gst_structure_get_uint (source_stats, "sent-pli-count", &pli))
gst_structure_set (in, "pli-count", G_TYPE_UINT, pli, NULL);
if (gst_structure_get_uint (source_stats, "recv-nack-count", &nack))
if (gst_structure_get_uint (source_stats, "sent-nack-count", &nack))
gst_structure_set (in, "nack-count", G_TYPE_UINT, nack, NULL);
if (jb_stats)
gst_structure_set (in, "packets-duplicated", G_TYPE_UINT64, duplicates,
......
......@@ -69,7 +69,6 @@ enum
{
PROP_0,
PROP_STREAM,
PROP_RTCP_MUX,
};
#define TSB_GET_LOCK(tsb) (&tsb->lock)
......
......@@ -59,7 +59,6 @@ struct _TransportSendBin
/*
struct pad_block *rtp_block;
struct pad_block *rtcp_mux_block;
struct pad_block *rtp_nice_block;
struct pad_block *rtcp_block;
......
......@@ -36,7 +36,6 @@ enum
PROP_0,
PROP_WEBRTC,
PROP_SESSION_ID,
PROP_RTCP_MUX,
PROP_DTLS_CLIENT,
};
......@@ -124,9 +123,6 @@ transport_stream_set_property (GObject * object, guint prop_id,
case PROP_SESSION_ID:
stream->session_id = g_value_get_uint (value);
break;
case PROP_RTCP_MUX:
stream->rtcp_mux = g_value_get_boolean (value);
break;
case PROP_DTLS_CLIENT:
stream->dtls_client = g_value_get_boolean (value);
break;
......@@ -148,9 +144,6 @@ transport_stream_get_property (GObject * object, guint prop_id,
case PROP_SESSION_ID:
g_value_set_uint (value, stream->session_id);
break;
case PROP_RTCP_MUX:
g_value_set_boolean (value, stream->rtcp_mux);
break;
case PROP_DTLS_CLIENT:
g_value_set_boolean (value, stream->dtls_client);
break;
......@@ -270,12 +263,6 @@ transport_stream_class_init (TransportStreamClass * klass)
0, G_MAXUINT, 0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_RTCP_MUX,
g_param_spec_boolean ("rtcp-mux", "RTCP Mux",
"Whether RTCP packets are muxed with RTP packets",
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class,
PROP_DTLS_CLIENT,
g_param_spec_boolean ("dtls-client", "DTLS client",
......
......@@ -52,9 +52,6 @@ struct _TransportStream
GstObject parent;
guint session_id; /* session_id */
gboolean rtcp;
gboolean rtcp_mux;
gboolean rtcp_rsize;
gboolean dtls_client;
gboolean active; /* TRUE if any mline in the bundle/transport is active */
TransportSendBin *send_bin; /* bin containing all the sending transport elements */
......
......@@ -59,12 +59,17 @@ webrtc_transceiver_set_transport (WebRTCTransceiver * trans,
gst_object_replace ((GstObject **) & trans->stream, (GstObject *) stream);
if (rtp_trans->sender)
if (rtp_trans->sender) {
gst_object_replace ((GstObject **) & rtp_trans->sender->transport,
(GstObject *) stream->transport);
if (rtp_trans->receiver)
g_object_notify (G_OBJECT (rtp_trans->sender), "transport");
}
if (rtp_trans->receiver) {
gst_object_replace ((GstObject **) & rtp_trans->receiver->transport,
(GstObject *) stream->transport);
g_object_notify (G_OBJECT (rtp_trans->receiver), "transport");
}
}
GstWebRTCDTLSTransport *
......