diff --git a/src/main.c b/src/main.c index 2a6ff8f78..45b187226 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,6 @@ * Gerard Castillo * * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya - * * Copyright (c) 2005-2010 CESNET z.s.p.o. * Copyright (c) 2001-2004 University of Southern California * Copyright (c) 2003-2004 University of Glasgow @@ -79,6 +78,7 @@ #include "sender.h" #include "stats.h" #include "utils/wait_obj.h" +#include "utils/sdp.h" #include "video.h" #include "video_capture.h" #include "video_display.h" @@ -249,7 +249,7 @@ static void usage(void) printf("\n"); printf("\t-c \tcompress video (see '-c help')\n"); printf("\n"); - printf("\t--h264 \tsend h264 stream following the h264 rtp standard\n"); + printf("\t--h264 \t\tsend h264 stream following the h264 rtp standard\n"); printf("\n"); printf("\t-i|--sage[=] \tiHDTV compatibility mode / SAGE TX\n"); printf("\n"); @@ -1402,8 +1402,11 @@ int main(int argc, char *argv[]) struct rtp **item; uv->connections_count = 0; /* only count how many connections has initialize_network opened */ - for(item = uv->network_devices; *item != NULL; ++item) + for(item = uv->network_devices; *item != NULL; ++item){ ++uv->connections_count; + h264_rtp.sdp = new_sdp(std_H264,uv->send_port_number); + get_sdp(h264_rtp.sdp); + } } if(bitrate == 0) { // else packet_rate defaults to 13600 or so diff --git a/src/sender.h b/src/sender.h index bc8e5ebe4..247e0e056 100644 --- a/src/sender.h +++ b/src/sender.h @@ -65,6 +65,7 @@ #endif // HAVE_CONFIG_H #include "video.h" +#include "utils/sdp.h" struct tx; struct rtp; @@ -123,6 +124,7 @@ struct h264_rtp_state { int connections_count; struct rtp **network_devices; struct tx *tx; + struct sdp *sdp; }; bool sender_init(struct sender_data *data); diff --git a/src/utils/sdp.c b/src/utils/sdp.c new file mode 100644 index 000000000..946358acd --- /dev/null +++ b/src/utils/sdp.c @@ -0,0 +1,192 @@ +/* + * FILE: sdp.c + * AUTHORS: Gerard Castillo + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif + +#include "debug.h" +#include "sender.h" +#include "utils/sdp.h" + +//TODO could be a vector of many streams +//struct sdp *sdp; + +struct sdp *new_sdp(enum rtp_standard std, int port){ + struct sdp *sdp; + sdp = NULL; + sdp = malloc(sizeof(struct sdp)); + sdp->stream_count = 0; + sdp->std_rtp = std; + sdp->port = port; + switch (std){ + case 0: //H264 + set_version(sdp); + set_origin(sdp); + set_session_name(sdp); + set_connection(sdp); + set_times(sdp); + set_stream(sdp); + + break; + default://UNKNOWN + break; + } + return sdp; +} +bool get_sdp(struct sdp *sdp){ + bool rc = 0; + + FILE *fOut = fopen ("UG_H264_STD.sdp", "w+"); + if (fOut != NULL) { + if (fprintf (fOut,sdp->version) >= 0) { + rc = 1; + } + if (fprintf (fOut,sdp->origin) >= 0) { + rc = 1; + } + if (fprintf (fOut,sdp->session_name) >= 0) { + rc = 1; + } + if (fprintf (fOut,sdp->connection) >= 0) { + rc = 1; + } + if (fprintf (fOut,sdp->times) >= 0) { + rc = 1; + } + if (fprintf (fOut,sdp->stream[sdp->stream_count]->media_info) >= 0) { + rc = 1; + } + if (fprintf (fOut,sdp->stream[sdp->stream_count]->rtpmap) >= 0) { + rc = 1; + } + fclose (fOut); // or for the paranoid: if (fclose (fOut) == EOF) rc = 0; + } + + printf("\n[SDP] printed version:\n"); + printf("%s",sdp->version); + printf("%s",sdp->origin); + printf("%s",sdp->session_name); + printf("%s",sdp->connection); + printf("%s",sdp->times); + //TODO check all stream vector (while!=NULL...) + printf("%s",sdp->stream[sdp->stream_count]->media_info); + printf("%s",sdp->stream[sdp->stream_count]->rtpmap); + printf("\n\n"); +} + +void set_version(struct sdp *sdp){ + sdp->version = malloc(strLength); + sdp->version = "v=0\n"; +} +void get_version(struct sdp *sdp); + +void set_origin(struct sdp *sdp){ + sdp->origin = malloc(strLength); + sdp->origin = "o=- 0 0 IN IP4 127.0.0.1\n"; +} +void get_origin(struct sdp *sdp); + +void set_session_name(struct sdp *sdp){ + sdp->session_name = malloc(strLength); + sdp->session_name = "s=Ultragrid streams\n"; +} +void get_session_name(struct sdp *sdp); + +void set_connection(struct sdp *sdp){ + sdp->connection =malloc(strLength); + sdp->connection = "c=IN IP4 127.0.0.1\n"; +} +void get_connection(struct sdp *sdp); + +void set_times(struct sdp *sdp){ + sdp->times = malloc(strLength); + sdp->times = "t=0 0\n"; +} +void get_times(struct sdp *sdp); + +void set_stream(struct sdp *sdp){ + if(add_stream(sdp)){ + } + else{ + printf("[SDP] stream NOT added -> error: maximum stream definition reached\n"); + } + +} +void get_stream(struct sdp *sdp); + + +bool add_stream(struct sdp *sdp){ + //struct stream_info *stream; + sdp->stream_count++; + if(sdp->stream_count < MAX_STREAMS + 1){ + sdp->stream[sdp->stream_count] = NULL; + sdp->stream[sdp->stream_count] = malloc(sizeof(struct stream_info)); + sdp->stream[sdp->stream_count]->media_info = set_stream_media_info(sdp, sdp->stream_count); + sdp->stream[sdp->stream_count]->rtpmap = set_stream_rtpmap(sdp, sdp->stream_count); + //set_stream_rtpmap(sdp, sdp->stream_count); + //set_stream_fmtp(sdp->stream[sdp->stream_count]); + return true; + } + else{ + sdp->stream[sdp->stream_count] = NULL; + return false; + } +} + +char *set_stream_media_info(struct sdp *sdp, int index){ + sdp->stream[index]->media_info =malloc(strLength); + debug_msg("[SDP] SETTING MEDIA INFO \n\n"); + + sprintf(sdp->stream[index]->media_info,"m=video %d RTP/AVP 96\n",sdp->port); + + return sdp->stream[index]->media_info; +} + +char *set_stream_rtpmap(struct sdp *sdp, int index){ + sdp->stream[index]->rtpmap = malloc(strLength); + debug_msg("[SDP] SETTING RTPMAP INFO \n\n"); + sdp->stream[index]->rtpmap="a=rtpmap:96 H264/90000\n"; + + return sdp->stream[index]->rtpmap; +} diff --git a/src/utils/sdp.h b/src/utils/sdp.h new file mode 100644 index 000000000..8d94d185e --- /dev/null +++ b/src/utils/sdp.h @@ -0,0 +1,115 @@ +/* + * FILE: sdp.h + * AUTHORS: Gerard Castillo + * + * Copyright (c) 2005-2010 Fundació i2CAT, Internet I Innovació Digital a Catalunya + * + * Redistribution and use in source and binary forms, with or without + * modification, is permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * + * This product includes software developed by CESNET z.s.p.o. + * + * 4. Neither the name of the CESNET nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#ifndef __sdp_h +#define __sdp_h + +#ifdef HAVE_CONFIG_H +#include "config.h" +#include "config_unix.h" +#include "config_win32.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_STREAMS 2 +#define strLength 2048 + +enum rtp_standard { + std_H264, + std_PCM +}; + +struct sdp { + enum rtp_standard std_rtp; + int port; + char *version; + char *origin; + char *session_name; + char *connection; + char *times; + struct stream_info *stream[MAX_STREAMS]; + int stream_count; //between 1 and MAX_STREAMS +}; + +struct stream_info { + char *media_info; + char *rtpmap; + char *fmtp; +}; + +/* + * External API + */ +struct sdp *new_sdp(enum rtp_standard std, int port); +bool get_sdp(struct sdp *sdp); + +void set_version(struct sdp *sdp); +void get_version(struct sdp *sdp); + +void set_origin(struct sdp *sdp); +void get_origin(struct sdp *sdp); + +void set_session_name(struct sdp *sdp); +void get_session_name(struct sdp *sdp); + +void set_connection(struct sdp *sdp); +void get_connection(struct sdp *sdp); + +void set_times(struct sdp *sdp); +void get_times(struct sdp *sdp); + +void set_stream(struct sdp *sdp); +void get_stream(struct sdp *sdp); + +/* + * Internal API + */ +bool add_stream(struct sdp *sdp); +char *set_stream_media_info(struct sdp *sdp, int index); +char *set_stream_rtpmap(struct sdp *sdp, int index); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/video_capture/rtsp.c b/src/video_capture/rtsp.c index a60a66a33..29ff01adc 100644 --- a/src/video_capture/rtsp.c +++ b/src/video_capture/rtsp.c @@ -710,8 +710,11 @@ void get_media_control_attribute(const char *sdp_filename, if (sdp_fp != NULL) { while (fgets(s, max_len - 2, sdp_fp) != NULL) { sscanf(s, " a = control: %s", track_ant); - if (strcmp(track_ant, "") != 0) + if (strcmp(track_ant, "") != 0){ track = strstr(track_ant, "track"); + if(track != NULL) + break; + } } fclose(sdp_fp);