示例#1
0
static struct rtsp *start_test_client(void)
{
	int r, fds[2] = { };

	r = sd_event_default(&event);
	ck_assert_int_ge(r, 0);

	r = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
	ck_assert_int_ge(r, 0);
	ck_assert_int_ge(fds[0], 0);
	ck_assert_int_ge(fds[1], 0);

	r = rtsp_open(&server, fds[0]);
	ck_assert_int_ge(r, 0);

	r = rtsp_attach_event(server, event, 0);
	ck_assert_int_ge(r, 0);

	r = rtsp_open(&client, fds[1]);
	ck_assert_int_ge(r, 0);

	r = rtsp_attach_event(client, event, 0);
	ck_assert_int_ge(r, 0);

	return client;
}
示例#2
0
static void sink_connected(struct ctl_sink *s)
{
	int r, val;
	socklen_t len;

	if (s->connected || s->hup)
		return;

	sd_event_source_set_enabled(s->fd_source, SD_EVENT_OFF);

	len = sizeof(val);
	r = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &len);
	if (r < 0) {
		s->hup = true;
		cli_vERRNO();
		return;
	} else if (val) {
		s->hup = true;
		errno = val;
		cli_error("cannot connect to remote host (%d): %m",
			  errno);
		return;
	}

	cli_debug("connection established");

	r = rtsp_open(&s->rtsp, s->fd);
	if (r < 0)
		goto error;

	r = rtsp_attach_event(s->rtsp, s->event, 0);
	if (r < 0)
		goto error;

	r = rtsp_add_match(s->rtsp, sink_rtsp_fn, s);
	if (r < 0)
		goto error;

	s->connected = true;
	ctl_fn_sink_connected(s);
	return;

error:
	s->hup = true;
	cli_vERR(r);
}
示例#3
0
static demuxer_t* demux_open_rtp(demuxer_t* demuxer)
{
    nms_rtsp_hints hints;
    char * url = demuxer->stream->streaming_ctrl->url->url;
    rtsp_ctrl * ctl;
    RTSP_Error reply;
    rtsp_medium * media;
    Nemesi_DemuxerStreamData * ndsd = calloc(1, sizeof(Nemesi_DemuxerStreamData));

    memset(&hints,0,sizeof(hints));
    if (rtsp_port) hints.first_rtp_port = rtsp_port;
    if (rtsp_transport_tcp) {
        hints.pref_rtsp_proto = TCP;
        hints.pref_rtp_proto = TCP;
    }
    if (rtsp_transport_sctp) {
        hints.pref_rtsp_proto = SCTP;
        hints.pref_rtp_proto = SCTP;
    }

    mp_msg(MSGT_DEMUX, MSGL_INFO, "Initializing libNemesi\n");
    if ((ctl = rtsp_init(&hints)) == NULL) {
        free(ndsd);
        return STREAM_ERROR;
    }

    ndsd->rtsp = ctl;
    demuxer->priv = ndsd;
    //nms_verbosity_set(1);

    mp_msg(MSGT_DEMUX, MSGL_INFO, "Opening: %s\n", url);
    if (rtsp_open(ctl, url)) {
        mp_msg(MSGT_DEMUX, MSGL_ERR, "rtsp_open failed.\n");
        return demuxer;
    }

    reply = rtsp_wait(ctl);
    if (reply.got_error) {
        mp_msg(MSGT_DEMUX, MSGL_ERR,
               "OPEN Error from the server: %s\n",
               reply.message.reply_str);
        return demuxer;
    }

    rtsp_play(ctl, 0, 0);
    reply = rtsp_wait(ctl);
    if (reply.got_error) {
        mp_msg(MSGT_DEMUX, MSGL_ERR,
               "PLAY Error from the server: %s\n",
               reply.message.reply_str);
        return demuxer;
    }

    if (!ctl->rtsp_queue)
        return demuxer;

    media = ctl->rtsp_queue->media_queue;
    for (; media; media=media->next) {
        sdp_medium_info * info = media->medium_info;
        rtp_session * sess = media->rtp_sess;
        rtp_buff buff;

        int media_format = atoi(info->fmts);
        rtp_pt * ptinfo = rtp_get_pt_info(sess, media_format);
        char const * format_name = ptinfo ? ptinfo->name : NULL;

        memset(&buff, 0, sizeof(rtp_buff));

        if (sess->parsers[media_format] == NULL) {
            mp_msg(MSGT_DEMUX, MSGL_ERR,
                   "libNemesi unsupported media format: %s\n",
                   format_name ? format_name : info->fmts);
            continue;
        }
        else {
            mp_msg(MSGT_DEMUX, MSGL_INFO,
                   "libNemesi supported media: %s\n",
                   format_name);
        }

        if (ptinfo->type == AU) {
            if (ndsd->session[NEMESI_SESSION_AUDIO] == NULL) {
                sh_audio_t* sh_audio = new_sh_audio(demuxer,0, NULL);
                WAVEFORMATEX* wf;
                demux_stream_t* d_audio = demuxer->audio;
                demuxer->audio->id = 0;

                mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as AUDIO stream...\n");

                link_session_and_fetch_conf(ndsd, NEMESI_SESSION_AUDIO,
                                            sess, &buff, NULL);

                wf = calloc(1,sizeof(*wf)+buff.len);
                wf->cbSize = buff.len;
                memcpy(wf+1, buff.data, buff.len);

                sh_audio->wf = wf;
                d_audio->sh = sh_audio;
                wf->nSamplesPerSec = 0;

                wf->wFormatTag =
                sh_audio->format = get4CC(supported_audio, format_name);
                if ( !(wf->wFormatTag) )
                    mp_msg(MSGT_DEMUX, MSGL_WARN,
                           "Unknown MPlayer format code for MIME"
                           " type \"audio/%s\"\n", format_name);
            } else {
                mp_msg(MSGT_DEMUX, MSGL_ERR,
                       "There is already an audio session registered,"
                       " ignoring...\n");
            }
        } else if (ptinfo->type == VI) {
            if (ndsd->session[NEMESI_SESSION_VIDEO] == NULL) {
                sh_video_t* sh_video;
                BITMAPINFOHEADER* bih;
                demux_stream_t* d_video;
                int fps = 0;

                mp_msg(MSGT_DEMUX, MSGL_INFO, "Detected as VIDEO stream...\n");

                link_session_and_fetch_conf(ndsd, NEMESI_SESSION_VIDEO,
                                            sess, &buff, &fps);

                bih = calloc(1,sizeof(*bih)+buff.len);
                bih->biSize = sizeof(*bih)+buff.len;
                memcpy(bih+1, buff.data, buff.len);

                sh_video = new_sh_video(demuxer,0);
                sh_video->bih = bih;
                d_video = demuxer->video;
                d_video->sh = sh_video;

                if (fps) {
                    sh_video->fps = fps;
                    sh_video->frametime = 1.0/fps;
                }

                bih->biCompression =
                sh_video->format = get4CC(supported_video, format_name);
                if ( !(bih->biCompression) ) {
                    mp_msg(MSGT_DEMUX, MSGL_WARN,
                        "Unknown MPlayer format code for MIME"
                        " type \"video/%s\"\n", format_name);
                }
            } else {
                mp_msg(MSGT_DEMUX, MSGL_ERR,
                       "There is already a video session registered,"
                       " ignoring...\n");
            }
        } else {
            mp_msg(MSGT_DEMUX, MSGL_ERR, "Unsupported media type\n");
        }
    }

    demuxer->stream->eof = 0;

    return demuxer;
}
示例#4
0
TEST_END_CASE

START_TEST(msg_new_invalid)
{
	char data[128] = { };
	struct rtsp *bus;
	struct rtsp_message *m;
	int r, fd;

	fd = dup(0);
	ck_assert_int_ge(fd, 0);
	r = rtsp_open(&bus, fd);
	ck_assert_int_ge(r, 0);

	/* request messages */

	m = TEST_INVALID_PTR;
	r = rtsp_message_new_request(NULL, &m, "method", "uri");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_request(bus, NULL, "method", "uri");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_request(bus, &m, "", "uri");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_request(bus, &m, NULL, "uri");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_request(bus, &m, "method", "");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_request(bus, &m, "method", NULL);
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);

	r = rtsp_message_new_request(bus, &m, "method", "uri");
	ck_assert_int_ge(r, 0);
	ck_assert(m != TEST_INVALID_PTR);
	rtsp_message_unref(m);

	/* reply-for messages */

	m = TEST_INVALID_PTR;
	r = rtsp_message_new_reply(NULL, &m, 1, 200, "OK");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_reply(bus, NULL, 1, 200, "OK");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_reply(bus, &m, 0, 200, "OK");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_reply(bus, &m, 1, RTSP_ANY_CODE, "OK");
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);

	r = rtsp_message_new_reply(bus, &m, 1, 200, "OK");
	ck_assert_int_ge(r, 0);
	ck_assert(m != TEST_INVALID_PTR);
	rtsp_message_unref(m);

	/* data messages */

	m = TEST_INVALID_PTR;
	r = rtsp_message_new_data(NULL, &m, 0, data, sizeof(data));
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_data(bus, NULL, 0, data, sizeof(data));
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_data(bus, &m, RTSP_ANY_CHANNEL, data, sizeof(data));
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);
	r = rtsp_message_new_data(bus, &m, 0, NULL, sizeof(data));
	ck_assert_int_lt(r, 0);
	ck_assert(m == TEST_INVALID_PTR);

	r = rtsp_message_new_data(bus, &m, 0, data, sizeof(data));
	ck_assert_int_ge(r, 0);
	ck_assert(m != TEST_INVALID_PTR);
	rtsp_message_unref(m);

	/* invalid ops */

	rtsp_message_ref(NULL);
	rtsp_message_unref(NULL);

	ck_assert_int_eq(rtsp_message_get_type(NULL), 0);
	ck_assert(!rtsp_message_get_method(NULL));
	ck_assert(!rtsp_message_get_uri(NULL));
	ck_assert_int_eq(rtsp_message_get_code(NULL), RTSP_ANY_CODE);
	ck_assert(!rtsp_message_get_phrase(NULL));
	ck_assert_int_eq(rtsp_message_get_channel(NULL), RTSP_ANY_CHANNEL);
	ck_assert(!rtsp_message_get_payload(NULL));
	ck_assert_int_eq(rtsp_message_get_payload_size(NULL), 0);

	ck_assert(!rtsp_message_is_request(NULL, NULL, NULL));
	ck_assert(!rtsp_message_is_reply(NULL, RTSP_ANY_CODE, NULL));
	ck_assert(!rtsp_message_is_data(NULL, RTSP_ANY_CHANNEL));

	ck_assert(!rtsp_message_get_bus(NULL));
	ck_assert(!rtsp_message_get_cookie(NULL));
	ck_assert(!rtsp_message_is_sealed(NULL));

	rtsp_unref(bus);
}
int main(int argc, char **argv)
{

        int opt;
        char *url, *out = "nemesi.dump";
        FILE *outfile = NULL;
        rtsp_ctrl *ctl;
        rtsp_session *sess;
        rtsp_medium *med;
        nms_rtsp_hints rtsp_hints = { -1 };
        sdp_attr *attr;
        RTSP_Error reply;

        if (argc < 2) {
                fprintf(stderr, "\tPlease specify at least an url.\n");
                fprintf(stderr,
                        "\tUsage: %s [-f outputfile ] [-p rtp_port] [-t url\n",
                        argv[0]);
                exit(1);
        }

#ifndef WIN32
        while ((opt = getopt(argc, argv, "df:p:v:")) != -1) {
                switch (opt) {

                        /*  Set output file  */
                case 'f':
                        out = strdup(optarg);
                        break;
                        /*  Set rtp port  */
                case 'p':
                        rtsp_hints.first_rtp_port = atoi(optarg);
                        break;
                        /*  Set verbosity  */
                case 'v':
                        nms_verbosity_set(atoi(optarg));
                        break;
                        /* Unknown option  */
                case '?':
                        fprintf(stderr, "\n  Unknown option `-%c'.\n", optopt);
                        fprintf(stderr,
                                "\tUsage: %s [-f outputfile ] [-d] url\n\n",
                                argv[0]);

                        return 1;
                }
        }
#endif

        outfile = fopen(out, "rb");
        if (outfile == NULL)
                outfile = stderr;

        url = argv[argc - 1];

        fprintf(stderr, "URL %s.\n", url);

        /* initialize the rtsp state machine, starts the rtsp and the rtp threads
         * the hints available are just one:
         *  - the first port to use (instead of picking one at random)
         */
        if ((ctl = rtsp_init(&rtsp_hints)) == NULL) {
                fprintf(stderr, "Cannot init rtsp.\n");
                return 1;
        }

        if (rtsp_open(ctl, url)) {
                fprintf(stderr, "rtsp_open failed.\n");
                // die
                return 1;
        }

        // you must call rtsp_wait after issuing any command
        reply = rtsp_wait(ctl);
        printf("OPEN: Received reply from server: %s\n", reply.message.reply_str);

        // Get the session information
        sess = ctl->rtsp_queue;

        if (!sess) {
                fprintf(stderr, "No session available.\n");
                return 1;
        }

        while (sess) {        // foreach session...
                fprintf(outfile, "\tSession %s\n", sess->pathname);
                fprintf(outfile, "\tSession Duration %s\n", sess->info->t);
                for (attr = sess->info->attr_list;
                                attr;
                                attr = attr->next) {
                        fprintf(outfile, "\t* %s %s\n", attr->name, attr->value);
                }

                med = sess->media_queue;
                while (med) {    //... foreach medium
                        switch (med->medium_info->media_type) {
                                // Just care about audio and video
                        case 'A':
                        case 'V':
                                fprintf(outfile, "\tTransport %s\n",
                                        med->medium_info->transport);
                                fprintf(outfile, "\tMedia Type %s\n",
                                        (med->medium_info->media_type == 'A'?
                                         "Audio" : "Video"));
                                fprintf(outfile, "\tMedia format %s\n",
                                        med->medium_info->fmts);
                                break;
                        default:
                                //do nothing
                                break;
                        }

                        // attributes are already parsed, get them from the list
                        for (attr = med->medium_info->attr_list;
                                        attr;
                                        attr = attr->next) {
                                fprintf(outfile, "\t* %s %s\n", attr->name, attr->value);
                        }

                        med = med->next;
                }
                sess = sess->next;
        }

        /*
         * Close the rtsp connection, we are polite
         */

        rtsp_close(ctl);
        reply = rtsp_wait(ctl);
        printf("CLOSE: Received reply from server: %s\n", reply.message.reply_str);

        /*
         * Kill the threads, dealloc everything.
         */

        rtsp_uninit(ctl);

        return 0;
}
示例#6
0
/**
 * @brief scan status code of an RTSP reply
 *
 * @param status_line the status line in the reply
 * @return reply status code or -1 on error
 */
int check_status(char *status_line, rtsp_thread * rtsp_th)
{
    char ver[32];
    unsigned short res_state;
    char *reason_phrase;
    char *location = NULL;
    // string tokenizers
    char *tkn, *prev_tkn, *step = NULL;

    if (sscanf(status_line, "%31s %hu ", ver, &res_state) < 2) {
        nms_printf(NMSML_ERR,
               "invalid Status-Line in DESCRIBE Response\n");
        return -1;
    }
    reason_phrase = strchr(strchr(status_line, ' ') + 1, ' ') + 1;

    rtsp_th->response_id = res_state;

    if (RTSP_IS_SUCCESS(res_state))
        return res_state;
    else if (RTSP_IS_REDIRECT(res_state)) {
        nms_printf(NMSML_NORM,
               "WARNING: Redirection. reply was: %hu %s\n",
               res_state, reason_phrase);
        switch (res_state) {
        case RTSP_FOUND:
            if ((prev_tkn =
                 strtok_r(rtsp_th->in_buffer.data +
                          strlen(status_line) + 1, "\n", &step)) == NULL) {
                nms_printf(NMSML_ERR,
                       "Could not find \"Location\" so..."
                       " Where I'll redirect you?\n");
                return -1;
            }
            while (((tkn = strtok_r(NULL, "\n", &step)) != NULL)
                   && ((tkn - prev_tkn) > 1)) {
                if (((tkn - prev_tkn) == 2) && (*prev_tkn == '\r'))
                    break;
                if (!strncasecmp(prev_tkn, "Location", 8)) {
                    prev_tkn += 8;
                    while ((*(prev_tkn) == ' ') || (*(prev_tkn) == ':'))
                        prev_tkn++;
                    location = strdup(prev_tkn);
                    // sscanf(prev_tkn,"%d",&location);
                }
                prev_tkn = tkn;
            }
            if (location) {
                nms_printf(NMSML_NORM, "Redirecting to %s\n", location);
                rtsp_open((rtsp_ctrl*)rtsp_th, location);
            } else
                return -nms_printf(NMSML_ERR, "No location string\n");
        }
    } else if (RTSP_IS_CLIENT_ERROR(res_state))
        nms_printf(NMSML_ERR, "Client error. Reply was: %hu %s\n",
               res_state, reason_phrase);
    else if (RTSP_IS_SERVER_ERROR(res_state))
        nms_printf(NMSML_ERR, "Server error. Reply was: %hu %s\n",
               res_state, reason_phrase);
    return -1;
}