void rtp_parse_close(RTPDemuxContext *s) { if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) { ff_mpegts_parse_close(s->ts); } av_free(s); }
void rtp_parse_close(RTPDemuxContext *s) { // TODO: fold this into the protocol specific data fields. if (!strcmp(ff_rtp_enc_name(s->payload_type), "MP2T")) { mpegts_parse_close(s->ts); } av_free(s); }
/** * open a new RTP parse context for stream 'st'. 'st' can be NULL for * MPEG2-TS streams to indicate that they should be demuxed inside the * rtp demux (otherwise AV_CODEC_ID_MPEG2TS packets are returned) */ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, int queue_size) { RTPDemuxContext *s; s = av_mallocz(sizeof(RTPDemuxContext)); if (!s) return NULL; s->payload_type = payload_type; s->last_rtcp_ntp_time = AV_NOPTS_VALUE; s->first_rtcp_ntp_time = AV_NOPTS_VALUE; s->ic = s1; s->st = st; s->queue_size = queue_size; rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp? if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) { s->ts = ff_mpegts_parse_open(s->ic); if (s->ts == NULL) { av_free(s); return NULL; } } else if (st) { switch (st->codec->codec_id) { case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: case AV_CODEC_ID_MP2: case AV_CODEC_ID_MP3: case AV_CODEC_ID_MPEG4: case AV_CODEC_ID_H263: case AV_CODEC_ID_H264: st->need_parsing = AVSTREAM_PARSE_FULL; break; case AV_CODEC_ID_VORBIS: st->need_parsing = AVSTREAM_PARSE_HEADERS; break; case AV_CODEC_ID_ADPCM_G722: /* According to RFC 3551, the stream clock rate is 8000 * even if the sample rate is 16000. */ if (st->codec->sample_rate == 8000) st->codec->sample_rate = 16000; break; default: break; } } // needed to send back RTCP RR in RTSP sessions s->rtp_ctx = rtpc; gethostname(s->hostname, sizeof(s->hostname)); return s; }
/** * open a new RTP parse context for stream 'st'. 'st' can be NULL for * MPEG2TS streams to indicate that they should be demuxed inside the * rtp demux (otherwise CODEC_ID_MPEG2TS packets are returned) * TODO: change this to not take rtp_payload data, and use the new dynamic payload system. */ RTPDemuxContext *rtp_parse_open(AVFormatContext *s1, AVStream *st, URLContext *rtpc, int payload_type, RTPPayloadData *rtp_payload_data) { RTPDemuxContext *s; s = av_mallocz(sizeof(RTPDemuxContext)); if (!s) return NULL; s->payload_type = payload_type; s->last_rtcp_ntp_time = AV_NOPTS_VALUE; s->first_rtcp_ntp_time = AV_NOPTS_VALUE; s->ic = s1; s->st = st; s->rtp_payload_data = rtp_payload_data; rtp_init_statistics(&s->statistics, 0); // do we know the initial sequence from sdp? if (!strcmp(ff_rtp_enc_name(payload_type), "MP2T")) { s->ts = ff_mpegts_parse_open(s->ic); if (s->ts == NULL) { av_free(s); return NULL; } } else { av_set_pts_info(st, 32, 1, 90000); switch(st->codec->codec_id) { case CODEC_ID_MPEG1VIDEO: case CODEC_ID_MPEG2VIDEO: case CODEC_ID_MP2: case CODEC_ID_MP3: case CODEC_ID_MPEG4: case CODEC_ID_H263: case CODEC_ID_H264: st->need_parsing = AVSTREAM_PARSE_FULL; break; default: if (st->codec->codec_type == CODEC_TYPE_AUDIO) { av_set_pts_info(st, 32, 1, st->codec->sample_rate); } break; } } // needed to send back RTCP RR in RTSP sessions s->rtp_ctx = rtpc; gethostname(s->hostname, sizeof(s->hostname)); return s; }
static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, int letter, const char *buf) { RTSPState *rt = s->priv_data; char buf1[64], st_type[64]; const char *p; int codec_type, payload_type, i; AVStream *st; RTSPStream *rtsp_st; struct in_addr sdp_ip; int ttl; #ifdef DEBUG printf("sdp: %c='%s'\n", letter, buf); #endif p = buf; switch(letter) { case 'c': get_word(buf1, sizeof(buf1), &p); if (strcmp(buf1, "IN") != 0) return; get_word(buf1, sizeof(buf1), &p); if (strcmp(buf1, "IP4") != 0) return; get_word_sep(buf1, sizeof(buf1), "/", &p); if (inet_aton(buf1, &sdp_ip) == 0) return; ttl = 16; if (*p == '/') { p++; get_word_sep(buf1, sizeof(buf1), "/", &p); ttl = atoi(buf1); } if (s->nb_streams == 0) { s1->default_ip = sdp_ip; s1->default_ttl = ttl; } else { st = s->streams[s->nb_streams - 1]; rtsp_st = st->priv_data; rtsp_st->sdp_ip = sdp_ip; rtsp_st->sdp_ttl = ttl; } break; case 's': av_strlcpy(s->title, p, sizeof(s->title)); break; case 'i': if (s->nb_streams == 0) { av_strlcpy(s->comment, p, sizeof(s->comment)); break; } break; case 'm': /* new stream */ get_word(st_type, sizeof(st_type), &p); if (!strcmp(st_type, "audio")) { codec_type = CODEC_TYPE_AUDIO; } else if (!strcmp(st_type, "video")) { codec_type = CODEC_TYPE_VIDEO; } else { return; } rtsp_st = av_mallocz(sizeof(RTSPStream)); if (!rtsp_st) return; rtsp_st->stream_index = -1; dynarray_add(&rt->rtsp_streams, &rt->nb_rtsp_streams, rtsp_st); rtsp_st->sdp_ip = s1->default_ip; rtsp_st->sdp_ttl = s1->default_ttl; get_word(buf1, sizeof(buf1), &p); /* port */ rtsp_st->sdp_port = atoi(buf1); get_word(buf1, sizeof(buf1), &p); /* protocol (ignored) */ /* XXX: handle list of formats */ get_word(buf1, sizeof(buf1), &p); /* format list */ rtsp_st->sdp_payload_type = atoi(buf1); if (!strcmp(ff_rtp_enc_name(rtsp_st->sdp_payload_type), "MP2T")) { /* no corresponding stream */ } else { st = av_new_stream(s, 0); if (!st) return; st->priv_data = rtsp_st; rtsp_st->stream_index = st->index; st->codec->codec_type = codec_type; if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) { /* if standard payload type, we can find the codec right now */ rtp_get_codec_info(st->codec, rtsp_st->sdp_payload_type); } } /* put a default control url */ av_strlcpy(rtsp_st->control_url, s->filename, sizeof(rtsp_st->control_url)); break; case 'a': if (av_strstart(p, "control:", &p) && s->nb_streams > 0) { char proto[32]; /* get the control url */ st = s->streams[s->nb_streams - 1]; rtsp_st = st->priv_data; /* XXX: may need to add full url resolution */ url_split(proto, sizeof(proto), NULL, 0, NULL, 0, NULL, NULL, 0, p); if (proto[0] == '\0') { /* relative control URL */ av_strlcat(rtsp_st->control_url, "/", sizeof(rtsp_st->control_url)); av_strlcat(rtsp_st->control_url, p, sizeof(rtsp_st->control_url)); } else { av_strlcpy(rtsp_st->control_url, p, sizeof(rtsp_st->control_url)); } } else if (av_strstart(p, "rtpmap:", &p)) { /* NOTE: rtpmap is only supported AFTER the 'm=' tag */ get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); for(i = 0; i < s->nb_streams;i++) { st = s->streams[i]; rtsp_st = st->priv_data; if (rtsp_st->sdp_payload_type == payload_type) { sdp_parse_rtpmap(st->codec, rtsp_st, payload_type, p); } } } else if (av_strstart(p, "fmtp:", &p)) { /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); for(i = 0; i < s->nb_streams;i++) { st = s->streams[i]; rtsp_st = st->priv_data; if (rtsp_st->sdp_payload_type == payload_type) { if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) { if(!rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf)) { sdp_parse_fmtp(st, p); } } else { sdp_parse_fmtp(st, p); } } } } else if(av_strstart(p, "framesize:", &p)) { // let dynamic protocol handlers have a stab at the line. get_word(buf1, sizeof(buf1), &p); payload_type = atoi(buf1); for(i = 0; i < s->nb_streams;i++) { st = s->streams[i]; rtsp_st = st->priv_data; if (rtsp_st->sdp_payload_type == payload_type) { if(rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) { rtsp_st->dynamic_handler->parse_sdp_a_line(st, rtsp_st->dynamic_protocol_context, buf); } } } } else if(av_strstart(p, "range:", &p)) { int64_t start, end; // this is so that seeking on a streamed file can work. rtsp_parse_range_npt(p, &start, &end); s->start_time= start; s->duration= (end==AV_NOPTS_VALUE)?AV_NOPTS_VALUE:end-start; // AV_NOPTS_VALUE means live broadcast (and can't seek) } else if (s->nb_streams > 0) { rtsp_st = s->streams[s->nb_streams - 1]->priv_data; if (rtsp_st->dynamic_handler && rtsp_st->dynamic_handler->parse_sdp_a_line) rtsp_st->dynamic_handler->parse_sdp_a_line(s->streams[s->nb_streams - 1], rtsp_st->dynamic_protocol_context, buf); } break; } }