You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hello,
I'm trying to build a simple sender and receiver using c language and your openwebrtc libraries.
The sender and the receiver exchanges candidates correctly and my video session goes into "ready" state, but my stream won't start. Or at least, i see nothing on the screen where the receiver is running. It seems that no fatal errors occurs judging from libnice-debug output and from bus messages sent by transport_agent and media_session. Can someone help me?
Here is the sender.c code:
`
int write_code(int sock, guint code){
char *conv = (char *)&code;
int len = sizeof(guint);
return write(sock, conv, len);
}
void exchange_candidates(OwrSession *session){
int sock, ret;
gint code;
struct sockaddr_in receiver;
gchar *address, *baseAddress, *foundation, *password, *ufrag, *msg;
guint basePort, port, priority, compType, transportType, type;
GList *candidates, *elem;
// Create client socket for signaling
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0){
printf("Error in creating socket: [%d]:[%s]", errno, strerror(errno));
return;
}
receiver.sin_family = AF_INET;
receiver.sin_port = htons(RCV_SOCK_PORT);
receiver.sin_addr.s_addr = inet_addr(remote_addr);
if (connect(sock, (struct sockaddr *) &receiver, sizeof(struct sockaddr_in)) < 0 ){
g_warning("Error while trying to connect to receiver: [%d]:[%s]", errno, strerror(errno));
return;
}
msg = malloc(sizeof(char) * MSG_MAX_LEN);
// Wait until receiver has accepted our connection
if (read(sock, &code, sizeof(guint)) < 0){
g_warning("Error while reading from socket: [%d]:[%s]", errno, strerror(errno));
return;
}
if (code != ACCEPTED){
printf("Socket: Wrong message sequence!\n");
return;
}
printf("Connection accepted\n");
ret = 1;
candidates = g_object_steal_data(G_OBJECT(session), "local-candidates");
for (elem = candidates; elem; elem = elem->next){
int len;
OwrCandidate *cand = elem->data;
print_candidate_info(cand, "CAND:\n");
g_object_get(G_OBJECT(cand), "address", &address, "base-address", &baseAddress,
"base-port", &basePort, "component-type", &compType, "foundation", &foundation,
"password", &password, "port", &port, "priority", &priority, "transport-type", &transportType,
"type", &type, "ufrag", &ufrag, NULL);
// using write/gets functions, so need to be careful about buffers size
/** every candidate information message begin with a number indicating in wich field we want to store
* the value that follows. when reading, we proceed to the next candidate when we encounter the
* "END" value integer. if a field is a string, we first send the buffer size, then the string.
*
* here we duplicate some code for the purpose of a more readable one.
* if at least one of the reads returns -1 (error), ret will be 0.
* Send Component type and CandidateType because they are needed to initialize the candidate
**/
ret = ret * 1+write_code(sock, COMPONENT_TYPE);
ret = ret * 1+write_code(sock, compType);
ret = ret * 1+write_code(sock, TYPE);
ret = ret * 1+write_code(sock, type);
ret = ret * 1+write_code(sock, ADDRESS);
len = strlen(address) * sizeof(char) + 1;
ret = ret * 1+write_code(sock, len);
ret = ret * 1+write(sock, address, len);
ret = ret * 1+write_code(sock, BASE_ADDRESS);
len = strlen(baseAddress) * sizeof(char) + 1;
ret = ret * 1+write_code(sock, len);
ret = ret * 1+write(sock, baseAddress, len);
ret = ret * 1+write_code(sock, BASE_PORT);
ret = ret * 1+write(sock, &basePort, sizeof(guint));
ret = ret * 1+write_code(sock, FOUNDATION);
len = strlen(foundation) * sizeof(char) + 1;
ret = ret * 1+write_code(sock, len);
ret = ret * 1+write(sock, foundation, len);
ret = ret * 1+write_code(sock, PASSWORD);
len = strlen(password) * sizeof(char) + 1;
ret = ret * 1+write_code(sock, len);
ret = ret * 1+write(sock, password, len);
ret = ret * 1+write_code(sock, PORT);
ret = ret * 1+write_code(sock, port);
ret = ret * 1+write_code(sock, PRIORITY);
ret = ret * 1+write_code(sock, priority);
ret = ret * 1+write_code(sock, TRANSPORT_TYPE);
ret = ret * 1+write_code(sock, transportType);
ret = ret * 1+write_code(sock, UFRAG);
len = strlen(ufrag) * sizeof(char) + 1;
ret = ret * 1+write_code(sock, len);
ret = ret * 1+write(sock, ufrag, len);
ret = ret * 1+write_code(sock, END);
}
ret = ret * 1+write_code(sock, END_OF_CANDIDATES);
printf("End of candidates\n");
if (ret <= 0){
printf("Error while writing on socket: [%d]:[%s]", errno, strerror(errno));
return;
}
ret = 1;
// Read receiver's candidates
ret = ret * 1+read(sock, &code, sizeof(guint));
while(code != END_OF_CANDIDATES){
// initialize candidate with default values. eventually those values will be replaced
OwrCandidate *cand = NULL;
guint len;
gboolean hasCT = FALSE, hasT = FALSE;
OwrCandidateType t;
OwrComponentType ct;
OwrTransportType tt;
// wait until we have component_type and candidate_type for initializing candidate.
while (!cand){
if (code == COMPONENT_TYPE){
ret = ret * 1+read(sock, &compType, sizeof(guint));
ct = compType;
hasCT = TRUE;
}
if (code == TYPE){
ret = ret * 1+read(sock, &type, sizeof(guint));
t = type;
hasT = TRUE;
}
if (hasCT & hasT)
cand = owr_candidate_new(t, ct);
// read next code
ret = ret * 1+read(sock, &code, sizeof(guint));
}
while (code != END){
switch (code){
case ADDRESS:
ret = ret * 1+read(sock, &len, sizeof(guint));
ret = ret * 1+read(sock, address, len);
g_object_set(cand, "address", address, NULL);
break;
case BASE_ADDRESS:
ret = ret * 1+read(sock, &len, sizeof(guint));
ret = ret * 1+read(sock, baseAddress, len);
g_object_set(cand, "base-address", baseAddress, NULL);
break;
case BASE_PORT:
ret = ret * 1+read(sock, &basePort, sizeof(guint));
g_object_set(cand, "base-port", basePort, NULL);
break;
case FOUNDATION:
ret = ret * 1+read(sock, &len, sizeof(guint));
ret = ret * 1+read(sock, foundation, len);
g_object_set(cand, "foundation", foundation, NULL);
break;
case PASSWORD:
ret = ret * 1+read(sock, &len, sizeof(guint));
ret = ret * 1+read(sock, password, len);
g_object_set(cand, "password", password, NULL);
break;
case PORT:
ret = ret * 1+read(sock, &port, sizeof(guint));
g_object_set(cand, "port", port, NULL);
break;
case PRIORITY:
ret = ret * 1+read(sock, &priority, sizeof(guint));
g_object_set(cand, "priority", priority, NULL);
break;
case TRANSPORT_TYPE:
ret = ret * 1+read(sock, &transportType, sizeof(guint));
tt = transportType;
g_object_set(cand, "transport-type", tt, NULL);
break;
case UFRAG:
ret = ret * 1+read(sock, &len, sizeof(guint));
ret = ret * 1+read(sock, ufrag, len);
g_object_set(cand, "ufrag", ufrag, NULL);
break;
}
// read next code
ret = ret * 1+read(sock, &code, sizeof(guint));
}// End when code == END
owr_session_add_remote_candidate(session, cand);
print_candidate_info(cand, "RECEIVED CANDIDATE:\n");
// read code of the next candidate (or end of stream)
ret = ret * 1+read(sock, &code, sizeof(guint));
}// End when code == END_OF_CANDIDATES
if (ret <= 0){
printf("Error while writing on socket: [%d]:[%s]", errno, strerror(errno));
return;
}
printf("All candidates received successfully\n");
// TODO: rendere un po' piu' "guardabile" il modo in cui si gestiscono gli errori tramite la variabile ret
close(sock);
free(msg);
return;
}
static void got_candidate(OwrMediaSession *sessionA, OwrCandidate *candidate, gpointer data){
GList *localCandidates;
//print_candidate_info(candidate, "Got candidate");
//force_candidate_port(candidate);
localCandidates = g_object_get_data(G_OBJECT(sessionA), "local-candidates");
localCandidates = g_list_append(localCandidates, candidate);
g_object_set_data(G_OBJECT(sessionA), "local-candidates", localCandidates);
}
static void gathering_done(OwrSession *session, gpointer data){
g_object_set_data(G_OBJECT(session), "gathering-done", GUINT_TO_POINTER(1));
exchange_candidates(session);
}
void print_source_info(OwrMediaSource *src){
OwrMediaType mediaType;
gchar *name = NULL;
OwrSourceType sourceType;
g_object_get(src, "name", &name, "type", &sourceType, "media-type", &mediaType, NULL);
g_print("[%s/%s] %s\n", mediaType == OWR_MEDIA_TYPE_AUDIO ? "audio" : "video",
sourceType == OWR_SOURCE_TYPE_CAPTURE ? "capture" : sourceType == OWR_SOURCE_TYPE_TEST ? "test" : "unknown",
name);
}
/**
void force_candidates(OwrSession *mediaSession){
GList *candidates;
OwrCandidate *remote_rtp, *remote_rtcp;
// Setting up RTP and RTCP candidates
remote_rtp = owr_candidate_new(OWR_CANDIDATE_TYPE_HOST, OWR_COMPONENT_TYPE_RTP);
g_object_set(remote_rtp, "address", remote_addr, "password", stun_pass,
"port", RCV_PORT_RTP, "ufrag", remote_addr, NULL);
remote_rtcp = owr_candidate_new(OWR_CANDIDATE_TYPE_HOST, OWR_COMPONENT_TYPE_RTCP);
g_object_set(remote_rtcp, "address", remote_addr, "password", stun_pass,
"port", RCV_PORT_RTCP, "ufrag", remote_addr, NULL);
owr_session_add_remote_candidate(mediaSession, remote_rtp);
owr_session_add_remote_candidate(mediaSession, remote_rtcp);
// Forcing candidates pairs
for (candidates = g_object_get_data(G_OBJECT(mediaSession), "local-candidates"); candidates;
candidates = g_list_next(candidates)){
OwrCandidate *localCnd = candidates->data, *remoteCnd;
OwrComponentType ctype;
guint port = 0, rport = 0;
gchar *r_addr;
g_object_get(localCnd, "port", &port, "component-type", &ctype, NULL);
// +++++ printing pairing info
if (ctype == OWR_COMPONENT_TYPE_RTP) type = "RTP";
else if (ctype == OWR_COMPONENT_TYPE_RTCP) type = "RTCP";
else type = "Unknown";
g_object_get(G_OBJECT(localCnd), "address", &l_addr, NULL);
g_object_get(G_OBJECT(remote_rtp), "address", &r_addr, "port", &rport, NULL);
g_object_get(G_OBJECT(remote_rtcp), "address", &r_addrc, "port", &rcport, NULL);
printf("trying to pair:\nlocal %s = %s:%d\nremoteRTP= %s:%d\nremoteRTCP= %s:%d\n\n",
type, l_addr, port, r_addr, rport, r_addrc, rcport);
// ----- finished printing pairing info
if (port == SEND_PORT_RTP && ctype == OWR_COMPONENT_TYPE_RTP)
remoteCnd = remote_rtp;
else if (port == SEND_PORT_RTCP && ctype == OWR_COMPONENT_TYPE_RTCP)
remoteCnd = remote_rtcp;
else continue; //TODO: trovare il modo di fare a meno di questo continue
g_object_get(G_OBJECT(remoteCnd), "address", &r_addr, "port", &rport, NULL);
owr_session_force_candidate_pair(mediaSession, ctype, localCnd, remoteCnd);
}
}
**/
static void got_sources(GList *sourcesList, gpointer data){
OwrMediaSource *src;
OwrVideoRenderer *renderer;
gboolean haveVideo = FALSE;
g_assert(sourcesList);
while (sourcesList && (src = sourcesList->data)){
OwrMediaType mediaType;
g_assert(OWR_IS_MEDIA_SOURCE(src));
print_source_info(src);
g_object_get(src, "media-type", &mediaType, NULL);
if (!haveVideo && mediaType == OWR_MEDIA_TYPE_VIDEO){
haveVideo = TRUE;
// preparing the payload for sending
pl = owr_video_payload_new(codec_type, 103, 8000, TRUE, FALSE);
g_object_set(pl, "width", WIDTH, "height", HEIGHT, "framerate", FRATE, NULL);
// Setting up session and transport agent
owr_media_session_set_send_payload(videoSession, pl);
owr_media_session_set_send_source(videoSession, src);
//owr_transport_agent_add_session(sendingAgent, OWR_SESSION(videoSession));
// show in self view
renderer = owr_video_renderer_new(NULL);
g_assert(renderer);
g_object_set(renderer, "width", WIDTH, "height", HEIGHT, "max-framerate", FRATE, NULL);
owr_media_renderer_set_source(OWR_MEDIA_RENDERER(renderer), src);
//videoRenderer = OWR_MEDIA_RENDERER(renderer);
// If a reference to the video source is needed,uncomment this(and declare variable videoSource)
//videoSource = g_object_ref(src);
}
sourcesList = sourcesList->next;
}
}
int main(int argc, char **argv){
GList *sessionList;
owr_init(NULL);
// creating the bus for message handling (not used for now)
bus = owr_bus_new();
owr_bus_set_message_callback(bus, (OwrBusMessageCallback)bus_message_cb, translate_message_origin, NULL);
// Setting up Sending Transport Agent
sendingAgent = owr_transport_agent_new(TRUE);
g_assert(OWR_IS_TRANSPORT_AGENT(sendingAgent));
//owr_transport_agent_set_local_port_range(sendingAgent, PORT_MIN, PORT_MAX);
owr_transport_agent_add_local_address(sendingAgent, local_addr);
owr_transport_agent_add_helper_server(sendingAgent, OWR_HELPER_SERVER_TYPE_STUN,
stunServer, stunPort, NULL, NULL);
//Uncomment if you want a TURN server as well
owr_transport_agent_add_helper_server(sendingAgent, OWR_HELPER_SERVER_TYPE_TURN_UDP,
"192.158.29.39", 3478, "28224511:1379330808", "JZEOEt2V3Qb0y27GRntt2u2PAYA=");
// Creating video session
videoSession = owr_media_session_new(USE_DTLS);
sessionList = g_object_get_data(G_OBJECT(videoSession), "media-sessions");
sessionList = g_list_append(sessionList, videoSession);
g_object_set_data(G_OBJECT(videoSession), "media-sessions", sessionList);
owr_transport_agent_add_session(sendingAgent, OWR_SESSION(videoSession));
//force_candidates();
// adding message origins to bus
owr_bus_add_message_origin(bus, OWR_MESSAGE_ORIGIN(sendingAgent));
owr_bus_add_message_origin(bus, OWR_MESSAGE_ORIGIN(videoSession));
// Candidate gathering
g_signal_connect(videoSession, "on-new-candidate", G_CALLBACK(got_candidate), NULL);
g_signal_connect(videoSession, "on-candidate-gathering-done", G_CALLBACK(gathering_done), NULL);
// Capturing video source with got_sources Callback
owr_get_capture_sources(OWR_MEDIA_TYPE_VIDEO, got_sources, NULL);
owr_run();
g_free(bus);
g_free(sendingAgent);
g_free(videoSession);
return 0;
}
`
The text was updated successfully, but these errors were encountered:
Hello,
I'm trying to build a simple sender and receiver using c language and your openwebrtc libraries.
The sender and the receiver exchanges candidates correctly and my video session goes into "ready" state, but my stream won't start. Or at least, i see nothing on
the
screen where the receiver is running. It seems that no fatal errors occurs judging from libnice-debug output and from bus messages sent by transport_agent and media_session. Can someone help me?Here is the sender.c code:
`
`
The text was updated successfully, but these errors were encountered: