comparison rtsp.c @ 774:820863425158 libavformat

RTP/RTSP and MPEG4-AAC audio - preliminary support for mpeg4-aac rtp payload (no interleaving support) - use udp transport as default (makes more sense with rtp, doesn't it ?) - some code factorization, so adding support for new rtp payload will be easier (I hope ;-) patch by (Romain DEGEZ: romain degez, smartjog com)
author michael
date Thu, 26 May 2005 07:47:51 +0000
parents fc254f396f15
children feca73904e67
comparison
equal deleted inserted replaced
773:a5095f5cf38a 774:820863425158
64 64
65 int sdp_port; /* port (from SDP content - not used in RTSP) */ 65 int sdp_port; /* port (from SDP content - not used in RTSP) */
66 struct in_addr sdp_ip; /* IP address (from SDP content - not used in RTSP) */ 66 struct in_addr sdp_ip; /* IP address (from SDP content - not used in RTSP) */
67 int sdp_ttl; /* IP TTL (from SDP content - not used in RTSP) */ 67 int sdp_ttl; /* IP TTL (from SDP content - not used in RTSP) */
68 int sdp_payload_type; /* payload type - only used in SDP */ 68 int sdp_payload_type; /* payload type - only used in SDP */
69 rtp_payload_data_t rtp_payload_data; /* rtp payload parsing infos from SDP */
69 } RTSPStream; 70 } RTSPStream;
70 71
71 static int rtsp_read_play(AVFormatContext *s); 72 static int rtsp_read_play(AVFormatContext *s);
72 73
73 /* XXX: currently, the only way to change the protocols consists in 74 /* XXX: currently, the only way to change the protocols consists in
74 changing this variable */ 75 changing this variable */
75 #if 0 76
76 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP) | (1 << RTSP_PROTOCOL_RTP_UDP) | (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST); 77 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_UDP);
77 #else
78 /* try it if a proxy is used */
79 int rtsp_default_protocols = (1 << RTSP_PROTOCOL_RTP_TCP);
80 #endif
81
82 /* if non zero, then set a range for RTP ports */
83 int rtsp_rtp_port_min = 0;
84 int rtsp_rtp_port_max = 0;
85 78
86 FFRTSPCallback *ff_rtsp_callback = NULL; 79 FFRTSPCallback *ff_rtsp_callback = NULL;
87 80
88 static int rtsp_probe(AVProbeData *p) 81 static int rtsp_probe(AVProbeData *p)
89 { 82 {
111 { 104 {
112 const char *p; 105 const char *p;
113 char *q; 106 char *q;
114 107
115 p = *pp; 108 p = *pp;
109 if (*p == '/')
110 p++;
116 skip_spaces(&p); 111 skip_spaces(&p);
117 q = buf; 112 q = buf;
118 while (!strchr(sep, *p) && *p != '\0') { 113 while (!strchr(sep, *p) && *p != '\0') {
119 if ((q - buf) < buf_size - 1) 114 if ((q - buf) < buf_size - 1)
120 *q++ = *p; 115 *q++ = *p;
143 *pp = p; 138 *pp = p;
144 } 139 }
145 140
146 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other 141 /* parse the rtpmap description: <codec_name>/<clock_rate>[/<other
147 params>] */ 142 params>] */
148 static int sdp_parse_rtpmap(AVCodecContext *codec, const char *p) 143 static int sdp_parse_rtpmap(AVCodecContext *codec, int payload_type, const char *p)
149 { 144 {
150 char buf[256]; 145 char buf[256];
151 146 int i;
152 /* codec name */ 147 AVCodec *c;
148 char *c_name;
149
150 /* Loop into AVRtpDynamicPayloadTypes[] and AVRtpPayloadTypes[] and
151 see if we can handle this kind of payload */
153 get_word_sep(buf, sizeof(buf), "/", &p); 152 get_word_sep(buf, sizeof(buf), "/", &p);
154 if (!strcmp(buf, "MP4V-ES")) { 153 if (payload_type >= RTP_PT_PRIVATE) {
155 codec->codec_id = CODEC_ID_MPEG4; 154 /* We are in dynmaic payload type case ... search into AVRtpDynamicPayloadTypes[] */
155 for (i = 0; AVRtpDynamicPayloadTypes[i].codec_id != CODEC_ID_NONE; ++i)
156 if (!strcmp(buf, AVRtpDynamicPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpDynamicPayloadTypes[i].codec_type)) {
157 codec->codec_id = AVRtpDynamicPayloadTypes[i].codec_id;
158 break;
159 }
160 } else {
161 /* We are in a standard case ( from http://www.iana.org/assignments/rtp-parameters) */
162 /* search into AVRtpPayloadTypes[] */
163 for (i = 0; AVRtpPayloadTypes[i].pt >= 0; ++i)
164 if (!strcmp(buf, AVRtpPayloadTypes[i].enc_name) && (codec->codec_type == AVRtpPayloadTypes[i].codec_type)){
165 codec->codec_id = AVRtpPayloadTypes[i].codec_id;
166 break;
167 }
168 }
169
170 c = avcodec_find_decoder(codec->codec_id);
171 if (c && c->name)
172 c_name = (char *)c->name;
173 else
174 c_name = (char *)NULL;
175
176 if (c_name) {
177 get_word_sep(buf, sizeof(buf), "/", &p);
178 i = atoi(buf);
179 switch (codec->codec_type) {
180 case CODEC_TYPE_AUDIO:
181 av_log(codec, AV_LOG_DEBUG, " audio codec set to : %s\n", c_name);
182 codec->sample_rate = RTSP_DEFAULT_AUDIO_SAMPLERATE;
183 codec->channels = RTSP_DEFAULT_NB_AUDIO_CHANNELS;
184 if (i > 0) {
185 codec->sample_rate = i;
186 get_word_sep(buf, sizeof(buf), "/", &p);
187 i = atoi(buf);
188 if (i > 0)
189 codec->channels = i;
190 }
191 av_log(codec, AV_LOG_DEBUG, " audio samplerate set to : %i\n", codec->sample_rate);
192 av_log(codec, AV_LOG_DEBUG, " audio channels set to : %i\n", codec->channels);
193 break;
194 case CODEC_TYPE_VIDEO:
195 av_log(codec, AV_LOG_DEBUG, " video codec set to : %s\n", c_name);
196 break;
197 default:
198 break;
199 }
156 return 0; 200 return 0;
157 } else { 201 }
158 return -1; 202
159 } 203 return -1;
160 } 204 }
161 205
162 /* return the length and optionnaly the data */ 206 /* return the length and optionnaly the data */
163 static int hex_to_data(uint8_t *data, const char *p) 207 static int hex_to_data(uint8_t *data, const char *p)
164 { 208 {
186 } 230 }
187 } 231 }
188 return len; 232 return len;
189 } 233 }
190 234
191 static void sdp_parse_fmtp(AVCodecContext *codec, const char *p) 235 static void sdp_parse_fmtp_config(AVCodecContext *codec, char *attr, char *value)
236 {
237 switch (codec->codec_id) {
238 case CODEC_ID_MPEG4:
239 case CODEC_ID_MPEG4AAC:
240 if (!strcmp(attr, "config")) {
241 /* decode the hexa encoded parameter */
242 int len = hex_to_data(NULL, value);
243 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
244 if (!codec->extradata)
245 return;
246 codec->extradata_size = len;
247 hex_to_data(codec->extradata, value);
248 }
249 break;
250 default:
251 break;
252 }
253 return;
254 }
255
256 typedef struct attrname_map
257 {
258 char *str;
259 uint16_t type;
260 uint32_t offset;
261 } attrname_map_t;
262
263 /* All known fmtp parmeters and the corresping RTPAttrTypeEnum */
264 #define ATTR_NAME_TYPE_INT 0
265 #define ATTR_NAME_TYPE_STR 1
266 static attrname_map_t attr_names[]=
267 {
268 {"SizeLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, sizelength)},
269 {"IndexLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexlength)},
270 {"IndexDeltaLength", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, indexdeltalength)},
271 {"profile-level-id", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, profile_level_id)},
272 {"StreamType", ATTR_NAME_TYPE_INT, offsetof(rtp_payload_data_t, streamtype)},
273 {"mode", ATTR_NAME_TYPE_STR, offsetof(rtp_payload_data_t, mode)},
274 {NULL, -1, -1},
275 };
276
277 /* parse a SDP line and save stream attributes */
278 static void sdp_parse_fmtp(AVStream *st, const char *p)
192 { 279 {
193 char attr[256]; 280 char attr[256];
194 char value[4096]; 281 char value[4096];
195 int len; 282 int i;
283
284 RTSPStream *rtsp_st = st->priv_data;
285 AVCodecContext *codec = &st->codec;
286 rtp_payload_data_t *rtp_payload_data = &rtsp_st->rtp_payload_data;
196 287
197 /* loop on each attribute */ 288 /* loop on each attribute */
198 for(;;) { 289 for(;;) {
199 skip_spaces(&p); 290 skip_spaces(&p);
200 if (*p == '\0') 291 if (*p == '\0')
203 if (*p == '=') 294 if (*p == '=')
204 p++; 295 p++;
205 get_word_sep(value, sizeof(value), ";", &p); 296 get_word_sep(value, sizeof(value), ";", &p);
206 if (*p == ';') 297 if (*p == ';')
207 p++; 298 p++;
208 /* handle MPEG4 video */ 299 /* grab the codec extra_data from the config parameter of the fmtp line */
209 switch(codec->codec_id) { 300 sdp_parse_fmtp_config(codec, attr, value);
210 case CODEC_ID_MPEG4: 301 /* Looking for a known attribute */
211 if (!strcmp(attr, "config")) { 302 for (i = 0; attr_names[i].str; ++i) {
212 /* decode the hexa encoded parameter */ 303 if (!strcasecmp(attr, attr_names[i].str)) {
213 len = hex_to_data(NULL, value); 304 if (attr_names[i].type == ATTR_NAME_TYPE_INT)
214 codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE); 305 *(int *)((char *)rtp_payload_data + attr_names[i].offset) = atoi(value);
215 if (!codec->extradata) 306 else if (attr_names[i].type == ATTR_NAME_TYPE_STR)
216 goto fail; 307 *(char **)((char *)rtp_payload_data + attr_names[i].offset) = av_strdup(value);
217 codec->extradata_size = len; 308 }
218 hex_to_data(codec->extradata, value); 309 }
219 }
220 break;
221 default:
222 /* ignore data for other codecs */
223 break;
224 }
225 fail: ;
226 // printf("'%s' = '%s'\n", attr, value);
227 } 310 }
228 } 311 }
229 312
230 typedef struct SDPParseState { 313 typedef struct SDPParseState {
231 /* SDP only */ 314 /* SDP only */
312 395
313 /* XXX: handle list of formats */ 396 /* XXX: handle list of formats */
314 get_word(buf1, sizeof(buf1), &p); /* format list */ 397 get_word(buf1, sizeof(buf1), &p); /* format list */
315 rtsp_st->sdp_payload_type = atoi(buf1); 398 rtsp_st->sdp_payload_type = atoi(buf1);
316 399
317 if (rtsp_st->sdp_payload_type == RTP_PT_MPEG2TS) { 400 if (!strcmp(AVRtpPayloadTypes[rtsp_st->sdp_payload_type].enc_name, "MP2T")) {
318 /* no corresponding stream */ 401 /* no corresponding stream */
319 } else { 402 } else {
320 st = av_new_stream(s, 0); 403 st = av_new_stream(s, 0);
321 if (!st) 404 if (!st)
322 return; 405 return;
323 st->priv_data = rtsp_st; 406 st->priv_data = rtsp_st;
324 rtsp_st->stream_index = st->index; 407 rtsp_st->stream_index = st->index;
325 st->codec.codec_type = codec_type; 408 st->codec.codec_type = codec_type;
326 if (rtsp_st->sdp_payload_type < 96) { 409 if (rtsp_st->sdp_payload_type < RTP_PT_PRIVATE) {
327 /* if standard payload type, we can find the codec right now */ 410 /* if standard payload type, we can find the codec right now */
328 rtp_get_codec_info(&st->codec, rtsp_st->sdp_payload_type); 411 rtp_get_codec_info(&st->codec, rtsp_st->sdp_payload_type);
329 } 412 }
330 } 413 }
331 /* put a default control url */ 414 /* put a default control url */
353 payload_type = atoi(buf1); 436 payload_type = atoi(buf1);
354 for(i = 0; i < s->nb_streams;i++) { 437 for(i = 0; i < s->nb_streams;i++) {
355 st = s->streams[i]; 438 st = s->streams[i];
356 rtsp_st = st->priv_data; 439 rtsp_st = st->priv_data;
357 if (rtsp_st->sdp_payload_type == payload_type) { 440 if (rtsp_st->sdp_payload_type == payload_type) {
358 sdp_parse_rtpmap(&st->codec, p); 441 sdp_parse_rtpmap(&st->codec, payload_type, p);
359 } 442 }
360 } 443 }
361 } else if (strstart(p, "fmtp:", &p)) { 444 } else if (strstart(p, "fmtp:", &p)) {
362 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */ 445 /* NOTE: fmtp is only supported AFTER the 'a=rtpmap:xxx' tag */
363 get_word(buf1, sizeof(buf1), &p); 446 get_word(buf1, sizeof(buf1), &p);
364 payload_type = atoi(buf1); 447 payload_type = atoi(buf1);
365 for(i = 0; i < s->nb_streams;i++) { 448 for(i = 0; i < s->nb_streams;i++) {
366 st = s->streams[i]; 449 st = s->streams[i];
367 rtsp_st = st->priv_data; 450 rtsp_st = st->priv_data;
368 if (rtsp_st->sdp_payload_type == payload_type) { 451 if (rtsp_st->sdp_payload_type == payload_type) {
369 sdp_parse_fmtp(&st->codec, p); 452 sdp_parse_fmtp(st, p);
370 } 453 }
371 } 454 }
372 } 455 }
373 break; 456 break;
374 } 457 }
713 AVFormatParameters *ap) 796 AVFormatParameters *ap)
714 { 797 {
715 RTSPState *rt = s->priv_data; 798 RTSPState *rt = s->priv_data;
716 char host[1024], path[1024], tcpname[1024], cmd[2048]; 799 char host[1024], path[1024], tcpname[1024], cmd[2048];
717 URLContext *rtsp_hd; 800 URLContext *rtsp_hd;
718 int port, i, ret, err; 801 int port, i, j, ret, err;
719 RTSPHeader reply1, *reply = &reply1; 802 RTSPHeader reply1, *reply = &reply1;
720 unsigned char *content = NULL; 803 unsigned char *content = NULL;
721 RTSPStream *rtsp_st; 804 RTSPStream *rtsp_st;
722 int protocol_mask; 805 int protocol_mask;
723 AVStream *st; 806 AVStream *st;
761 protocol_mask = rtsp_default_protocols; 844 protocol_mask = rtsp_default_protocols;
762 845
763 /* for each stream, make the setup request */ 846 /* for each stream, make the setup request */
764 /* XXX: we assume the same server is used for the control of each 847 /* XXX: we assume the same server is used for the control of each
765 RTSP stream */ 848 RTSP stream */
766 for(i=0;i<rt->nb_rtsp_streams;i++) { 849
850 for(j = RTSP_RTP_PORT_MIN, i = 0; i < rt->nb_rtsp_streams; ++i) {
767 char transport[2048]; 851 char transport[2048];
768 852
769 rtsp_st = rt->rtsp_streams[i]; 853 rtsp_st = rt->rtsp_streams[i];
770 854
771 /* compute available transports */ 855 /* compute available transports */
772 transport[0] = '\0'; 856 transport[0] = '\0';
773 857
774 /* RTP/UDP */ 858 /* RTP/UDP */
775 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) { 859 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP)) {
776 char buf[256]; 860 char buf[256];
777 int j;
778 861
779 /* first try in specified port range */ 862 /* first try in specified port range */
780 if (rtsp_rtp_port_min != 0) { 863 if (RTSP_RTP_PORT_MIN != 0) {
781 for(j=rtsp_rtp_port_min;j<=rtsp_rtp_port_max;j++) { 864 while(j <= RTSP_RTP_PORT_MAX) {
782 snprintf(buf, sizeof(buf), "rtp://?localport=%d", j); 865 snprintf(buf, sizeof(buf), "rtp://?localport=%d", j);
783 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDONLY) == 0) 866 if (url_open(&rtsp_st->rtp_handle, buf, URL_RDONLY) == 0) {
867 j += 2; /* we will use two port by rtp stream (rtp and rtcp) */
784 goto rtp_opened; 868 goto rtp_opened;
869 }
785 } 870 }
786 } 871 }
787 872
788 /* then try on any port */ 873 /* then try on any port
789 if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) { 874 ** if (url_open(&rtsp_st->rtp_handle, "rtp://", URL_RDONLY) < 0) {
790 err = AVERROR_INVALIDDATA; 875 ** err = AVERROR_INVALIDDATA;
791 goto fail; 876 ** goto fail;
792 } 877 ** }
878 */
793 879
794 rtp_opened: 880 rtp_opened:
795 port = rtp_get_local_port(rtsp_st->rtp_handle); 881 port = rtp_get_local_port(rtsp_st->rtp_handle);
796 if (transport[0] != '\0') 882 if (transport[0] != '\0')
797 pstrcat(transport, sizeof(transport), ","); 883 pstrcat(transport, sizeof(transport), ",");
799 "RTP/AVP/UDP;unicast;client_port=%d-%d", 885 "RTP/AVP/UDP;unicast;client_port=%d-%d",
800 port, port + 1); 886 port, port + 1);
801 } 887 }
802 888
803 /* RTP/TCP */ 889 /* RTP/TCP */
804 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) { 890 else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_TCP)) {
805 if (transport[0] != '\0') 891 if (transport[0] != '\0')
806 pstrcat(transport, sizeof(transport), ","); 892 pstrcat(transport, sizeof(transport), ",");
807 snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1, 893 snprintf(transport + strlen(transport), sizeof(transport) - strlen(transport) - 1,
808 "RTP/AVP/TCP"); 894 "RTP/AVP/TCP");
809 } 895 }
810 896
811 if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) { 897 else if (protocol_mask & (1 << RTSP_PROTOCOL_RTP_UDP_MULTICAST)) {
812 if (transport[0] != '\0') 898 if (transport[0] != '\0')
813 pstrcat(transport, sizeof(transport), ","); 899 pstrcat(transport, sizeof(transport), ",");
814 snprintf(transport + strlen(transport), 900 snprintf(transport + strlen(transport),
815 sizeof(transport) - strlen(transport) - 1, 901 sizeof(transport) - strlen(transport) - 1,
816 "RTP/AVP/UDP;multicast"); 902 "RTP/AVP/UDP;multicast");
885 st = NULL; 971 st = NULL;
886 if (rtsp_st->stream_index >= 0) 972 if (rtsp_st->stream_index >= 0)
887 st = s->streams[rtsp_st->stream_index]; 973 st = s->streams[rtsp_st->stream_index];
888 if (!st) 974 if (!st)
889 s->ctx_flags |= AVFMTCTX_NOHEADER; 975 s->ctx_flags |= AVFMTCTX_NOHEADER;
890 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type); 976 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
977
891 if (!rtsp_st->rtp_ctx) { 978 if (!rtsp_st->rtp_ctx) {
892 err = AVERROR_NOMEM; 979 err = AVERROR_NOMEM;
893 goto fail; 980 goto fail;
894 } 981 }
895 } 982 }
1231 st = NULL; 1318 st = NULL;
1232 if (rtsp_st->stream_index >= 0) 1319 if (rtsp_st->stream_index >= 0)
1233 st = s->streams[rtsp_st->stream_index]; 1320 st = s->streams[rtsp_st->stream_index];
1234 if (!st) 1321 if (!st)
1235 s->ctx_flags |= AVFMTCTX_NOHEADER; 1322 s->ctx_flags |= AVFMTCTX_NOHEADER;
1236 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type); 1323 rtsp_st->rtp_ctx = rtp_parse_open(s, st, rtsp_st->sdp_payload_type, &rtsp_st->rtp_payload_data);
1237 if (!rtsp_st->rtp_ctx) { 1324 if (!rtsp_st->rtp_ctx) {
1238 err = AVERROR_NOMEM; 1325 err = AVERROR_NOMEM;
1239 goto fail; 1326 goto fail;
1240 } 1327 }
1241 } 1328 }