Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

All components ready but stream won't start #708

Open
SirUriel87 opened this issue Mar 2, 2018 · 0 comments
Open

All components ready but stream won't start #708

SirUriel87 opened this issue Mar 2, 2018 · 0 comments

Comments

@SirUriel87
Copy link

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;
}

`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant