00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <string.h>
00022 #include "libavutil/avstring.h"
00023 #include "libavutil/base64.h"
00024 #include "libavcodec/xiph.h"
00025 #include "avformat.h"
00026 #include "internal.h"
00027 #include "avc.h"
00028 #include "rtp.h"
00029 #if CONFIG_NETWORK
00030 #include "network.h"
00031 #endif
00032
00033 #if CONFIG_RTP_MUXER
00034 #define MAX_EXTRADATA_SIZE ((INT_MAX - 10) / 2)
00035
00036 struct sdp_session_level {
00037 int sdp_version;
00038 int id;
00039 int version;
00040 int start_time;
00042 int end_time;
00044 int ttl;
00045 const char *user;
00046 const char *src_addr;
00047 const char *src_type;
00048 const char *dst_addr;
00049 const char *dst_type;
00050 const char *name;
00051 };
00052
00053 static void sdp_write_address(char *buff, int size, const char *dest_addr,
00054 const char *dest_type, int ttl)
00055 {
00056 if (dest_addr) {
00057 if (!dest_type)
00058 dest_type = "IP4";
00059 if (ttl > 0 && !strcmp(dest_type, "IP4")) {
00060
00061
00062 av_strlcatf(buff, size, "c=IN %s %s/%d\r\n", dest_type, dest_addr, ttl);
00063 } else {
00064 av_strlcatf(buff, size, "c=IN %s %s\r\n", dest_type, dest_addr);
00065 }
00066 }
00067 }
00068
00069 static void sdp_write_header(char *buff, int size, struct sdp_session_level *s)
00070 {
00071 av_strlcatf(buff, size, "v=%d\r\n"
00072 "o=- %d %d IN %s %s\r\n"
00073 "s=%s\r\n",
00074 s->sdp_version,
00075 s->id, s->version, s->src_type, s->src_addr,
00076 s->name);
00077 sdp_write_address(buff, size, s->dst_addr, s->dst_type, s->ttl);
00078 av_strlcatf(buff, size, "t=%d %d\r\n"
00079 "a=tool:libavformat " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\r\n",
00080 s->start_time, s->end_time);
00081 }
00082
00083 #if CONFIG_NETWORK
00084 static int resolve_destination(char *dest_addr, int size, char *type,
00085 int type_size)
00086 {
00087 struct addrinfo hints, *ai;
00088 int is_multicast;
00089
00090 av_strlcpy(type, "IP4", type_size);
00091 if (!dest_addr[0])
00092 return 0;
00093
00094
00095
00096
00097 memset(&hints, 0, sizeof(hints));
00098 if (getaddrinfo(dest_addr, NULL, &hints, &ai))
00099 return 0;
00100 getnameinfo(ai->ai_addr, ai->ai_addrlen, dest_addr, size,
00101 NULL, 0, NI_NUMERICHOST);
00102 #ifdef AF_INET6
00103 if (ai->ai_family == AF_INET6)
00104 av_strlcpy(type, "IP6", type_size);
00105 #endif
00106 is_multicast = ff_is_multicast_address(ai->ai_addr);
00107 freeaddrinfo(ai);
00108 return is_multicast;
00109 }
00110 #else
00111 static int resolve_destination(char *dest_addr, int size, char *type,
00112 int type_size)
00113 {
00114 return 0;
00115 }
00116 #endif
00117
00118 static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url)
00119 {
00120 int port;
00121 const char *p;
00122 char proto[32];
00123
00124 av_url_split(proto, sizeof(proto), NULL, 0, dest_addr, size, &port, NULL, 0, url);
00125
00126 *ttl = 0;
00127
00128 if (strcmp(proto, "rtp")) {
00129
00130
00131
00132 return 0;
00133 }
00134
00135 p = strchr(url, '?');
00136 if (p) {
00137 char buff[64];
00138
00139 if (find_info_tag(buff, sizeof(buff), "ttl", p)) {
00140 *ttl = strtol(buff, NULL, 10);
00141 } else {
00142 *ttl = 5;
00143 }
00144 }
00145
00146 return port;
00147 }
00148
00149 #define MAX_PSET_SIZE 1024
00150 static char *extradata2psets(AVCodecContext *c)
00151 {
00152 char *psets, *p;
00153 const uint8_t *r;
00154 const char *pset_string = "; sprop-parameter-sets=";
00155
00156 if (c->extradata_size > MAX_EXTRADATA_SIZE) {
00157 av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
00158
00159 return NULL;
00160 }
00161 if (c->extradata[0] == 1) {
00162 uint8_t *dummy_p;
00163 int dummy_int;
00164 AVBitStreamFilterContext *bsfc= av_bitstream_filter_init("h264_mp4toannexb");
00165
00166 if (!bsfc) {
00167 av_log(c, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n");
00168
00169 return NULL;
00170 }
00171 av_bitstream_filter_filter(bsfc, c, NULL, &dummy_p, &dummy_int, NULL, 0, 0);
00172 av_bitstream_filter_close(bsfc);
00173 }
00174
00175 psets = av_mallocz(MAX_PSET_SIZE);
00176 if (psets == NULL) {
00177 av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
00178 return NULL;
00179 }
00180 memcpy(psets, pset_string, strlen(pset_string));
00181 p = psets + strlen(pset_string);
00182 r = ff_avc_find_startcode(c->extradata, c->extradata + c->extradata_size);
00183 while (r < c->extradata + c->extradata_size) {
00184 const uint8_t *r1;
00185 uint8_t nal_type;
00186
00187 while (!*(r++));
00188 nal_type = *r & 0x1f;
00189 r1 = ff_avc_find_startcode(r, c->extradata + c->extradata_size);
00190 if (nal_type != 7 && nal_type != 8) {
00191 r = r1;
00192 continue;
00193 }
00194 if (p != (psets + strlen(pset_string))) {
00195 *p = ',';
00196 p++;
00197 }
00198 if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) {
00199 av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
00200 av_free(psets);
00201
00202 return NULL;
00203 }
00204 p += strlen(p);
00205 r = r1;
00206 }
00207
00208 return psets;
00209 }
00210
00211 static char *extradata2config(AVCodecContext *c)
00212 {
00213 char *config;
00214
00215 if (c->extradata_size > MAX_EXTRADATA_SIZE) {
00216 av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
00217
00218 return NULL;
00219 }
00220 config = av_malloc(10 + c->extradata_size * 2);
00221 if (config == NULL) {
00222 av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
00223 return NULL;
00224 }
00225 memcpy(config, "; config=", 9);
00226 ff_data_to_hex(config + 9, c->extradata, c->extradata_size, 0);
00227 config[9 + c->extradata_size * 2] = 0;
00228
00229 return config;
00230 }
00231
00232 static char *xiph_extradata2config(AVCodecContext *c)
00233 {
00234 char *config, *encoded_config;
00235 uint8_t *header_start[3];
00236 int headers_len, header_len[3], config_len;
00237 int first_header_size;
00238
00239 switch (c->codec_id) {
00240 case CODEC_ID_THEORA:
00241 first_header_size = 42;
00242 break;
00243 case CODEC_ID_VORBIS:
00244 first_header_size = 30;
00245 break;
00246 default:
00247 av_log(c, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
00248 return NULL;
00249 }
00250
00251 if (ff_split_xiph_headers(c->extradata, c->extradata_size,
00252 first_header_size, header_start,
00253 header_len) < 0) {
00254 av_log(c, AV_LOG_ERROR, "Extradata corrupt.\n");
00255 return NULL;
00256 }
00257
00258 headers_len = header_len[0] + header_len[2];
00259 config_len = 4 +
00260 3 +
00261 2 +
00262 1 +
00263 2 +
00264 headers_len;
00265
00266 config = av_malloc(config_len);
00267 if (!config)
00268 goto xiph_fail;
00269
00270 encoded_config = av_malloc(AV_BASE64_SIZE(config_len));
00271 if (!encoded_config) {
00272 av_free(config);
00273 goto xiph_fail;
00274 }
00275
00276 config[0] = config[1] = config[2] = 0;
00277 config[3] = 1;
00278 config[4] = (RTP_XIPH_IDENT >> 16) & 0xff;
00279 config[5] = (RTP_XIPH_IDENT >> 8) & 0xff;
00280 config[6] = (RTP_XIPH_IDENT ) & 0xff;
00281 config[7] = (headers_len >> 8) & 0xff;
00282 config[8] = headers_len & 0xff;
00283 config[9] = 2;
00284 config[10] = header_len[0];
00285 config[11] = 0;
00286 memcpy(config + 12, header_start[0], header_len[0]);
00287 memcpy(config + 12 + header_len[0], header_start[2], header_len[2]);
00288
00289 av_base64_encode(encoded_config, AV_BASE64_SIZE(config_len),
00290 config, config_len);
00291 av_free(config);
00292
00293 return encoded_config;
00294
00295 xiph_fail:
00296 av_log(c, AV_LOG_ERROR,
00297 "Not enough memory for configuration string\n");
00298 return NULL;
00299 }
00300
00301 static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type)
00302 {
00303 char *config = NULL;
00304
00305 switch (c->codec_id) {
00306 case CODEC_ID_H264:
00307 if (c->extradata_size) {
00308 config = extradata2psets(c);
00309 }
00310 av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
00311 "a=fmtp:%d packetization-mode=1%s\r\n",
00312 payload_type,
00313 payload_type, config ? config : "");
00314 break;
00315 case CODEC_ID_H263:
00316 case CODEC_ID_H263P:
00317
00318
00319
00320
00321 av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n"
00322 "a=framesize:%d %d-%d\r\n",
00323 payload_type,
00324 payload_type, c->width, c->height);
00325 break;
00326 case CODEC_ID_MPEG4:
00327 if (c->extradata_size) {
00328 config = extradata2config(c);
00329 }
00330 av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
00331 "a=fmtp:%d profile-level-id=1%s\r\n",
00332 payload_type,
00333 payload_type, config ? config : "");
00334 break;
00335 case CODEC_ID_AAC:
00336 if (c->extradata_size) {
00337 config = extradata2config(c);
00338 } else {
00339
00340
00341
00342 av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
00343 return NULL;
00344 }
00345 if (config == NULL) {
00346 return NULL;
00347 }
00348 av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
00349 "a=fmtp:%d profile-level-id=1;"
00350 "mode=AAC-hbr;sizelength=13;indexlength=3;"
00351 "indexdeltalength=3%s\r\n",
00352 payload_type, c->sample_rate, c->channels,
00353 payload_type, config);
00354 break;
00355 case CODEC_ID_PCM_S16BE:
00356 if (payload_type >= RTP_PT_PRIVATE)
00357 av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
00358 payload_type,
00359 c->sample_rate, c->channels);
00360 break;
00361 case CODEC_ID_PCM_MULAW:
00362 if (payload_type >= RTP_PT_PRIVATE)
00363 av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
00364 payload_type,
00365 c->sample_rate, c->channels);
00366 break;
00367 case CODEC_ID_PCM_ALAW:
00368 if (payload_type >= RTP_PT_PRIVATE)
00369 av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
00370 payload_type,
00371 c->sample_rate, c->channels);
00372 break;
00373 case CODEC_ID_AMR_NB:
00374 av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
00375 "a=fmtp:%d octet-align=1\r\n",
00376 payload_type, c->sample_rate, c->channels,
00377 payload_type);
00378 break;
00379 case CODEC_ID_AMR_WB:
00380 av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
00381 "a=fmtp:%d octet-align=1\r\n",
00382 payload_type, c->sample_rate, c->channels,
00383 payload_type);
00384 break;
00385 case CODEC_ID_VORBIS:
00386 if (c->extradata_size)
00387 config = xiph_extradata2config(c);
00388 else
00389 av_log(c, AV_LOG_ERROR, "Vorbis configuration info missing\n");
00390 if (!config)
00391 return NULL;
00392
00393 av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
00394 "a=fmtp:%d configuration=%s\r\n",
00395 payload_type, c->sample_rate, c->channels,
00396 payload_type, config);
00397 break;
00398 case CODEC_ID_THEORA: {
00399 const char *pix_fmt;
00400 if (c->extradata_size)
00401 config = xiph_extradata2config(c);
00402 else
00403 av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n");
00404 if (!config)
00405 return NULL;
00406
00407 switch (c->pix_fmt) {
00408 case PIX_FMT_YUV420P:
00409 pix_fmt = "YCbCr-4:2:0";
00410 break;
00411 case PIX_FMT_YUV422P:
00412 pix_fmt = "YCbCr-4:2:2";
00413 break;
00414 case PIX_FMT_YUV444P:
00415 pix_fmt = "YCbCr-4:4:4";
00416 break;
00417 default:
00418 av_log(c, AV_LOG_ERROR, "Unsupported pixel format.\n");
00419 return NULL;
00420 }
00421
00422 av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n"
00423 "a=fmtp:%d delivery-method=inline; "
00424 "width=%d; height=%d; sampling=%s; "
00425 "configuration=%s\r\n",
00426 payload_type, payload_type,
00427 c->width, c->height, pix_fmt, config);
00428 break;
00429 }
00430 case CODEC_ID_VP8:
00431 av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n",
00432 payload_type);
00433 break;
00434 case CODEC_ID_ADPCM_G722:
00435 if (payload_type >= RTP_PT_PRIVATE)
00436 av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n",
00437 payload_type,
00438 8000, c->channels);
00439 break;
00440 default:
00441
00442 break;
00443 }
00444
00445 av_free(config);
00446
00447 return buff;
00448 }
00449
00450 void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl)
00451 {
00452 const char *type;
00453 int payload_type;
00454
00455 payload_type = ff_rtp_get_payload_type(c);
00456 if (payload_type < 0) {
00457 payload_type = RTP_PT_PRIVATE + (c->codec_type == AVMEDIA_TYPE_AUDIO);
00458 }
00459
00460 switch (c->codec_type) {
00461 case AVMEDIA_TYPE_VIDEO : type = "video" ; break;
00462 case AVMEDIA_TYPE_AUDIO : type = "audio" ; break;
00463 case AVMEDIA_TYPE_SUBTITLE: type = "text" ; break;
00464 default : type = "application"; break;
00465 }
00466
00467 av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type);
00468 sdp_write_address(buff, size, dest_addr, dest_type, ttl);
00469 if (c->bit_rate) {
00470 av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000);
00471 }
00472
00473 sdp_write_media_attributes(buff, size, c, payload_type);
00474 }
00475
00476 int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
00477 {
00478 AVMetadataTag *title = av_metadata_get(ac[0]->metadata, "title", NULL, 0);
00479 struct sdp_session_level s;
00480 int i, j, port, ttl, is_multicast;
00481 char dst[32], dst_type[5];
00482
00483 memset(buff, 0, size);
00484 memset(&s, 0, sizeof(struct sdp_session_level));
00485 s.user = "-";
00486 s.src_addr = "127.0.0.1";
00487 s.src_type = "IP4";
00488 s.name = title ? title->value : "No Name";
00489
00490 port = 0;
00491 ttl = 0;
00492 if (n_files == 1) {
00493 port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename);
00494 is_multicast = resolve_destination(dst, sizeof(dst), dst_type,
00495 sizeof(dst_type));
00496 if (!is_multicast)
00497 ttl = 0;
00498 if (dst[0]) {
00499 s.dst_addr = dst;
00500 s.dst_type = dst_type;
00501 s.ttl = ttl;
00502 if (!strcmp(dst_type, "IP6")) {
00503 s.src_addr = "::1";
00504 s.src_type = "IP6";
00505 }
00506 }
00507 }
00508 sdp_write_header(buff, size, &s);
00509
00510 dst[0] = 0;
00511 for (i = 0; i < n_files; i++) {
00512 if (n_files != 1) {
00513 port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename);
00514 is_multicast = resolve_destination(dst, sizeof(dst), dst_type,
00515 sizeof(dst_type));
00516 if (!is_multicast)
00517 ttl = 0;
00518 }
00519 for (j = 0; j < ac[i]->nb_streams; j++) {
00520 ff_sdp_write_media(buff, size,
00521 ac[i]->streams[j]->codec, dst[0] ? dst : NULL,
00522 dst_type, (port > 0) ? port + j * 2 : 0, ttl);
00523 if (port <= 0) {
00524 av_strlcatf(buff, size,
00525 "a=control:streamid=%d\r\n", i + j);
00526 }
00527 }
00528 }
00529
00530 return 0;
00531 }
00532 #else
00533 int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
00534 {
00535 return AVERROR(ENOSYS);
00536 }
00537
00538 void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl)
00539 {
00540 }
00541 #endif