示例#1
0
static void
rtsp_cmd_setup(RTSPContext *ctx, const char *url, RTSPMessageHeader *h) {
	int i;
	RTSPTransportField *th;
	struct sockaddr_in destaddr, myaddr;
#ifdef WIN32
	int destaddrlen, myaddrlen;
#else
	socklen_t destaddrlen, myaddrlen;
#endif
	char path[4096];
	char channelname[VIDEO_SOURCE_CHANNEL_MAX+1][RTSP_STREAM_FORMAT_MAXLEN];
	int baselen = strlen(rtspconf->object);
	int streamid;
	int rtp_port, rtcp_port;
	enum RTSPStatusCode errcode;
	//
	av_url_split(NULL, 0, NULL, 0, NULL, 0, NULL, path, sizeof(path), url);
	for(i = 0; i < VIDEO_SOURCE_CHANNEL_MAX+1; i++) {
		snprintf(channelname[i], RTSP_STREAM_FORMAT_MAXLEN, RTSP_STREAM_FORMAT, i);
	}
	//
	if(strncmp(path, rtspconf->object, baselen) != 0) {
		ga_error("invalid object (path=%s)\n", path);
		rtsp_reply_error(ctx, RTSP_STATUS_AGGREGATE);
		return;
	}
	for(i = 0; i < VIDEO_SOURCE_CHANNEL_MAX+1; i++) {
		if(strcmp(path+baselen+1, channelname[i]) == 0) {
			streamid = i;
			break;
		}
	}
	if(i == VIDEO_SOURCE_CHANNEL_MAX+1) {
		// not found
		ga_error("invalid service (path=%s)\n", path);
		rtsp_reply_error(ctx, RTSP_STATUS_SERVICE);
		return;
	}
	//
	if(ctx->state != SERVER_STATE_IDLE
	&& ctx->state != SERVER_STATE_READY) {
		rtsp_reply_error(ctx, RTSP_STATUS_STATE);
		return;
	}
	// create session id?
	if(ctx->session_id == NULL) {
		if(h->session_id[0] == '\0') {
			snprintf(h->session_id, sizeof(h->session_id), "%04x%04x",
				rand()%0x0ffff, rand()%0x0ffff);
			ctx->session_id = strdup(h->session_id);
			ga_error("New session created (id = %s)\n", ctx->session_id);
		}
	}
	// session id must match -- we have only one session
	if(ctx->session_id == NULL
	|| strcmp(ctx->session_id, h->session_id) != 0) {
		ga_error("Bad session id %s != %s\n", h->session_id, ctx->session_id);
		errcode = RTSP_STATUS_SESSION;
		goto error_setup;
	}
	// find supported transport
	if((th = find_transport(h, RTSP_LOWER_TRANSPORT_UDP)) == NULL) {
		th = find_transport(h, RTSP_LOWER_TRANSPORT_TCP);
	}
	if(th == NULL) {
		ga_error("Cannot find transport\n");
		errcode = RTSP_STATUS_TRANSPORT;
		goto error_setup;
	}
	//
	destaddrlen = sizeof(destaddr);
	bzero(&destaddr, destaddrlen);
	if(getpeername(ctx->fd, (struct sockaddr*) &destaddr, &destaddrlen) < 0) {
		ga_error("Cannot get peername\n");
		errcode = RTSP_STATUS_INTERNAL;
		goto error_setup;
	}
	destaddr.sin_port = htons(th->client_port_min);
	//
	myaddrlen = sizeof(myaddr);
	bzero(&myaddr, myaddrlen);
	if(getsockname(ctx->fd, (struct sockaddr*) &myaddr, &myaddrlen) < 0) {
		ga_error("Cannot get sockname\n");
		errcode = RTSP_STATUS_INTERNAL;
		goto error_setup;
	}
	//
	ctx->lower_transport[streamid] = th->lower_transport;
	if(rtp_new_av_stream(ctx, &destaddr, streamid,
			streamid == video_source_channels()/*rtspconf->audio_id*/ ?
				rtspconf->audio_encoder_codec->id : rtspconf->video_encoder_codec->id) < 0) {
		ga_error("Create AV stream %d failed.\n", streamid);
		errcode = RTSP_STATUS_TRANSPORT;
		goto error_setup;
	}
	//
	ctx->state = SERVER_STATE_READY;
	rtsp_reply_header(ctx, RTSP_STATUS_OK);
	rtsp_printf(ctx, "Session: %s\r\n", ctx->session_id);
	switch(th->lower_transport) {
	case RTSP_LOWER_TRANSPORT_UDP:
#ifdef HOLE_PUNCHING
		rtp_port = ctx->rtpLocalPort[streamid*2];
		rtcp_port = ctx->rtpLocalPort[streamid*2+1];
		ctx->rtpPeerPort[streamid*2] = htons(th->client_port_min);
		ctx->rtpPeerPort[streamid*2+1] = htons(th->client_port_max);
#else
		rtp_port = ff_rtp_get_local_rtp_port((URLContext*) ctx->fmtctx[streamid]->pb->opaque);
		rtcp_port = ff_rtp_get_local_rtcp_port((URLContext*) ctx->fmtctx[streamid]->pb->opaque);
#endif
		ga_error("RTP/UDP: streamid=%d; client=%d-%d; server=%d-%d\n",
			streamid,
			th->client_port_min, th->client_port_max,
			rtp_port, rtcp_port);
		rtsp_printf(ctx, "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d;server_port=%d-%d\r\n",
		       th->client_port_min, th->client_port_max,
		       rtp_port, rtcp_port);
		break;
	case RTSP_LOWER_TRANSPORT_TCP:
		ga_error("RTP/TCP: interleaved=%d-%d\n",
			streamid*2, streamid*2+1);
		rtsp_printf(ctx, "Transport: RTP/AVP/TCP;unicast;interleaved=%d-%d\r\n",
			streamid*2, streamid*2+1, streamid*2);
		break;
	default:
		// should not happen
		break;
	}
	rtsp_printf(ctx, "\r\n");
	return;
error_setup:
	if(ctx->session_id != NULL) {
		free(ctx->session_id);
		ctx->session_id = NULL;
	}
	if(ctx->encoder[streamid] != NULL) {
		ctx->encoder[streamid] = NULL;
	}
	if(ctx->stream[streamid] != NULL) {
		ctx->stream[streamid] = NULL;
	}
	if(ctx->fmtctx[streamid] != NULL) {
		avformat_free_context(ctx->fmtctx[streamid]);
		ctx->fmtctx[streamid] = NULL;
	}
	rtsp_reply_error(ctx, errcode);
	return;
}
示例#2
0
jint Java_org_devtcg_rojocam_ffmpeg_RtpOutputContext_nativeGetLocalRtcpPort(JNIEnv *env,
        jclass clazz, jint nativeInt) {
    RtpOutputContext *rtpContext = (RtpOutputContext *)nativeInt;
    return ff_rtp_get_local_rtcp_port(rtpContext->urlContext);
}