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