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