⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtsp.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 3 页
字号:
                ttl = reply->transports[0].ttl;                if (!ttl)                    ttl = 16;                snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",                         host,                         reply->transports[0].server_port_min,                         ttl);                if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {                    err = AVERROR_INVALIDDATA;                    goto fail;                }            }            break;        }        /* open the RTP context */        st = NULL;        if (rtsp_st->stream_index >= 0)            st = s->streams[rtsp_st->stream_index];        if (!st)            s->ctx_flags |= AVFMTCTX_NOHEADER;        rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);        if (!rtsp_st->rtp_ctx) {            err = AVERROR_NOMEM;            goto fail;        }    }    /* use callback if available to extend setup */    if (ff_rtsp_callback) {        if (ff_rtsp_callback(RTSP_ACTION_CLIENT_SETUP, rt->session_id,                             NULL, 0, rt->last_reply) < 0) {            err = AVERROR_INVALIDDATA;            goto fail;        }    }    rt->state = RTSP_STATE_IDLE;    rt->seek_timestamp = 0; /* default is to start stream at position                               zero */    if (ap->initial_pause) {        /* do not start immediately */    } else {        if (rtsp_read_play(s) < 0) {            err = AVERROR_INVALIDDATA;            goto fail;        }    }    return 0; fail:    rtsp_close_streams(rt);    av_freep(&content);    url_close(rt->rtsp_hd);    return err;}static int tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,                           uint8_t *buf, int buf_size){    RTSPState *rt = s->priv_data;    int id, len, i, ret;    RTSPStream *rtsp_st;#ifdef DEBUG_RTP_TCP    printf("tcp_read_packet:\n");#endif redo:    for(;;) {        ret = url_readbuf(rt->rtsp_hd, buf, 1);#ifdef DEBUG_RTP_TCP        printf("ret=%d c=%02x [%c]\n", ret, buf[0], buf[0]);#endif        if (ret != 1)            return -1;        if (buf[0] == '$')            break;    }    ret = url_readbuf(rt->rtsp_hd, buf, 3);    if (ret != 3)        return -1;    id = buf[0];    len = (buf[1] << 8) | buf[2];#ifdef DEBUG_RTP_TCP    printf("id=%d len=%d\n", id, len);#endif    if (len > buf_size || len < 12)        goto redo;    /* get the data */    ret = url_readbuf(rt->rtsp_hd, buf, len);    if (ret != len)        return -1;    /* find the matching stream */    for(i = 0; i < rt->nb_rtsp_streams; i++) {        rtsp_st = rt->rtsp_streams[i];        if (id >= rtsp_st->interleaved_min &&            id <= rtsp_st->interleaved_max)            goto found;    }    goto redo; found:    *prtsp_st = rtsp_st;    return len;}static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,                           uint8_t *buf, int buf_size){    RTSPState *rt = s->priv_data;    RTSPStream *rtsp_st;    fd_set rfds;    int fd1, fd2, fd_max, n, i, ret;    struct timeval tv;    for(;;) {        if (url_interrupt_cb())            return -1;        FD_ZERO(&rfds);        fd_max = -1;        for(i = 0; i < rt->nb_rtsp_streams; i++) {            rtsp_st = rt->rtsp_streams[i];            /* currently, we cannot probe RTCP handle because of blocking restrictions */            rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);            if (fd1 > fd_max)                fd_max = fd1;            FD_SET(fd1, &rfds);        }        tv.tv_sec = 0;        tv.tv_usec = 100 * 1000;        n = select(fd_max + 1, &rfds, NULL, NULL, &tv);        if (n > 0) {            for(i = 0; i < rt->nb_rtsp_streams; i++) {                rtsp_st = rt->rtsp_streams[i];                rtp_get_file_handles(rtsp_st->rtp_handle, &fd1, &fd2);                if (FD_ISSET(fd1, &rfds)) {                    ret = url_read(rtsp_st->rtp_handle, buf, buf_size);                    if (ret > 0) {                        *prtsp_st = rtsp_st;                        return ret;                    }                }            }        }    }}static int rtsp_read_packet(AVFormatContext *s,                            AVPacket *pkt){    RTSPState *rt = s->priv_data;    RTSPStream *rtsp_st;    int ret, len;    uint8_t buf[RTP_MAX_PACKET_LENGTH];    /* get next frames from the same RTP packet */    if (rt->cur_rtp) {        ret = rtp_parse_packet(rt->cur_rtp, pkt, NULL, 0);        if (ret == 0) {            rt->cur_rtp = NULL;            return 0;        } else if (ret == 1) {            return 0;        } else {            rt->cur_rtp = NULL;        }    }    /* read next RTP packet */ redo:    switch(rt->protocol) {    default:    case RTSP_PROTOCOL_RTP_TCP:        len = tcp_read_packet(s, &rtsp_st, buf, sizeof(buf));        break;    case RTSP_PROTOCOL_RTP_UDP:    case RTSP_PROTOCOL_RTP_UDP_MULTICAST:        len = udp_read_packet(s, &rtsp_st, buf, sizeof(buf));        break;    }    if (len < 0)        return AVERROR_IO;    ret = rtp_parse_packet(rtsp_st->rtp_ctx, pkt, buf, len);    if (ret < 0)        goto redo;    if (ret == 1) {        /* more packets may follow, so we save the RTP context */        rt->cur_rtp = rtsp_st->rtp_ctx;    }    return 0;}static int rtsp_read_play(AVFormatContext *s){    RTSPState *rt = s->priv_data;    RTSPHeader reply1, *reply = &reply1;    char cmd[1024];    av_log(s, AV_LOG_DEBUG, "hello state=%d\n", rt->state);    if (rt->state == RTSP_STATE_PAUSED) {        snprintf(cmd, sizeof(cmd),                 "PLAY %s RTSP/1.0\r\n",                 s->filename);    } else {        snprintf(cmd, sizeof(cmd),                 "PLAY %s RTSP/1.0\r\n"                 "Range: npt=%0.3f-\r\n",                 s->filename,                 (double)rt->seek_timestamp / AV_TIME_BASE);    }    rtsp_send_cmd(s, cmd, reply, NULL);    if (reply->status_code != RTSP_STATUS_OK) {        return -1;    } else {        rt->state = RTSP_STATE_PLAYING;        return 0;    }}/* pause the stream */static int rtsp_read_pause(AVFormatContext *s){    RTSPState *rt = s->priv_data;    RTSPHeader reply1, *reply = &reply1;    char cmd[1024];    rt = s->priv_data;    if (rt->state != RTSP_STATE_PLAYING)        return 0;    snprintf(cmd, sizeof(cmd),             "PAUSE %s RTSP/1.0\r\n",             s->filename);    rtsp_send_cmd(s, cmd, reply, NULL);    if (reply->status_code != RTSP_STATUS_OK) {        return -1;    } else {        rt->state = RTSP_STATE_PAUSED;        return 0;    }}static int rtsp_read_seek(AVFormatContext *s, int stream_index,                          int64_t timestamp, int flags){    RTSPState *rt = s->priv_data;    rt->seek_timestamp = timestamp;    switch(rt->state) {    default:    case RTSP_STATE_IDLE:        break;    case RTSP_STATE_PLAYING:        if (rtsp_read_play(s) != 0)            return -1;        break;    case RTSP_STATE_PAUSED:        rt->state = RTSP_STATE_IDLE;        break;    }    return 0;}static int rtsp_read_close(AVFormatContext *s){    RTSPState *rt = s->priv_data;    RTSPHeader reply1, *reply = &reply1;    char cmd[1024];#if 0    /* NOTE: it is valid to flush the buffer here */    if (rt->protocol == RTSP_PROTOCOL_RTP_TCP) {        url_fclose(&rt->rtsp_gb);    }#endif    snprintf(cmd, sizeof(cmd),             "TEARDOWN %s RTSP/1.0\r\n",             s->filename);    rtsp_send_cmd(s, cmd, reply, NULL);    if (ff_rtsp_callback) {        ff_rtsp_callback(RTSP_ACTION_CLIENT_TEARDOWN, rt->session_id,                         NULL, 0, NULL);    }    rtsp_close_streams(rt);    url_close(rt->rtsp_hd);    return 0;}AVInputFormat rtsp_demux = {    "rtsp",    "RTSP input format",    sizeof(RTSPState),    rtsp_probe,    rtsp_read_header,    rtsp_read_packet,    rtsp_read_close,    rtsp_read_seek,    .flags = AVFMT_NOFILE,    .read_play = rtsp_read_play,    .read_pause = rtsp_read_pause,};static int sdp_probe(AVProbeData *p1){    const char *p = p1->buf, *p_end = p1->buf + p1->buf_size;    /* we look for a line beginning "c=IN IP4" */    while (p < p_end && *p != '\0') {        if (p + sizeof("c=IN IP4") - 1 < p_end && strstart(p, "c=IN IP4", NULL))            return AVPROBE_SCORE_MAX / 2;        while(p < p_end - 1 && *p != '\n') p++;        if (++p >= p_end)            break;        if (*p == '\r')            p++;    }    return 0;}#define SDP_MAX_SIZE 8192static int sdp_read_header(AVFormatContext *s,                           AVFormatParameters *ap){    RTSPState *rt = s->priv_data;    RTSPStream *rtsp_st;    int size, i, err;    char *content;    char url[1024];    AVStream *st;    /* read the whole sdp file */    /* XXX: better loading */    content = av_malloc(SDP_MAX_SIZE);    size = get_buffer(&s->pb, content, SDP_MAX_SIZE - 1);    if (size <= 0) {        av_free(content);        return AVERROR_INVALIDDATA;    }    content[size] ='\0';    sdp_parse(s, content);    av_free(content);    /* open each RTP stream */    for(i=0;i<rt->nb_rtsp_streams;i++) {        rtsp_st = rt->rtsp_streams[i];        snprintf(url, sizeof(url), "rtp://%s:%d?multicast=1&ttl=%d",                 inet_ntoa(rtsp_st->sdp_ip),                 rtsp_st->sdp_port,                 rtsp_st->sdp_ttl);        if (url_open(&rtsp_st->rtp_handle, url, URL_RDONLY) < 0) {            err = AVERROR_INVALIDDATA;            goto fail;        }        /* open the RTP context */        st = NULL;        if (rtsp_st->stream_index >= 0)            st = s->streams[rtsp_st->stream_index];        if (!st)            s->ctx_flags |= AVFMTCTX_NOHEADER;        rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);        if (!rtsp_st->rtp_ctx) {            err = AVERROR_NOMEM;            goto fail;        }    }    return 0; fail:    rtsp_close_streams(rt);    return err;}static int sdp_read_packet(AVFormatContext *s,                            AVPacket *pkt){    return rtsp_read_packet(s, pkt);}static int sdp_read_close(AVFormatContext *s){    RTSPState *rt = s->priv_data;    rtsp_close_streams(rt);    return 0;}static AVInputFormat sdp_demux = {    "sdp",    "SDP",    sizeof(RTSPState),    sdp_probe,    sdp_read_header,    sdp_read_packet,    sdp_read_close,};/* dummy redirector format (used directly in av_open_input_file now) */static int redir_probe(AVProbeData *pd){    const char *p;    p = pd->buf;    while (redir_isspace(*p))        p++;    if (strstart(p, "http://", NULL) ||        strstart(p, "rtsp://", NULL))        return AVPROBE_SCORE_MAX;    return 0;}/* called from utils.c */int redir_open(AVFormatContext **ic_ptr, ByteIOContext *f){    char buf[4096], *q;    int c;    AVFormatContext *ic = NULL;    /* parse each URL and try to open it */    c = url_fgetc(f);    while (c != URL_EOF) {        /* skip spaces */        for(;;) {            if (!redir_isspace(c))                break;            c = url_fgetc(f);        }        if (c == URL_EOF)            break;        /* record url */        q = buf;        for(;;) {            if (c == URL_EOF || redir_isspace(c))                break;            if ((q - buf) < sizeof(buf) - 1)                *q++ = c;            c = url_fgetc(f);        }        *q = '\0';        //printf("URL='%s'\n", buf);        /* try to open the media file */        if (av_open_input_file(&ic, buf, NULL, 0, NULL) == 0)            break;    }    *ic_ptr = ic;    if (!ic)        return AVERROR_IO;    else        return 0;}AVInputFormat redir_demux = {    "redir",    "Redirector format",    0,    redir_probe,    NULL,    NULL,    NULL,};int rtsp_init(void){    av_register_input_format(&rtsp_demux);    av_register_input_format(&redir_demux);    av_register_input_format(&sdp_demux);    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -