• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavformat/sdp.c

Go to the documentation of this file.
00001 /*
00002  * copyright (c) 2007 Luca Abeni
00003  *
00004  * This file is part of Libav.
00005  *
00006  * Libav is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * Libav is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with Libav; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include <string.h>
00022 #include "libavutil/avstring.h"
00023 #include "libavutil/base64.h"
00024 #include "libavutil/dict.h"
00025 #include "libavutil/parseutils.h"
00026 #include "libavutil/opt.h"
00027 #include "libavcodec/xiph.h"
00028 #include "libavcodec/mpeg4audio.h"
00029 #include "avformat.h"
00030 #include "internal.h"
00031 #include "avc.h"
00032 #include "rtp.h"
00033 #if CONFIG_NETWORK
00034 #include "network.h"
00035 #endif
00036 
00037 #if CONFIG_RTP_MUXER
00038 #define MAX_EXTRADATA_SIZE ((INT_MAX - 10) / 2)
00039 
00040 struct sdp_session_level {
00041     int sdp_version;      
00042     int id;               
00043     int version;          
00044     int start_time;       
00046     int end_time;         
00048     int ttl;              
00049     const char *user;     
00050     const char *src_addr; 
00051     const char *src_type; 
00052     const char *dst_addr; 
00053     const char *dst_type; 
00054     const char *name;     
00055 };
00056 
00057 static void sdp_write_address(char *buff, int size, const char *dest_addr,
00058                               const char *dest_type, int ttl)
00059 {
00060     if (dest_addr) {
00061         if (!dest_type)
00062             dest_type = "IP4";
00063         if (ttl > 0 && !strcmp(dest_type, "IP4")) {
00064             /* The TTL should only be specified for IPv4 multicast addresses,
00065              * not for IPv6. */
00066             av_strlcatf(buff, size, "c=IN %s %s/%d\r\n", dest_type, dest_addr, ttl);
00067         } else {
00068             av_strlcatf(buff, size, "c=IN %s %s\r\n", dest_type, dest_addr);
00069         }
00070     }
00071 }
00072 
00073 static void sdp_write_header(char *buff, int size, struct sdp_session_level *s)
00074 {
00075     av_strlcatf(buff, size, "v=%d\r\n"
00076                             "o=- %d %d IN %s %s\r\n"
00077                             "s=%s\r\n",
00078                             s->sdp_version,
00079                             s->id, s->version, s->src_type, s->src_addr,
00080                             s->name);
00081     sdp_write_address(buff, size, s->dst_addr, s->dst_type, s->ttl);
00082     av_strlcatf(buff, size, "t=%d %d\r\n"
00083                             "a=tool:libavformat " AV_STRINGIFY(LIBAVFORMAT_VERSION) "\r\n",
00084                             s->start_time, s->end_time);
00085 }
00086 
00087 #if CONFIG_NETWORK
00088 static int resolve_destination(char *dest_addr, int size, char *type,
00089                                int type_size)
00090 {
00091     struct addrinfo hints, *ai;
00092     int is_multicast;
00093 
00094     av_strlcpy(type, "IP4", type_size);
00095     if (!dest_addr[0])
00096         return 0;
00097 
00098     /* Resolve the destination, since it must be written
00099      * as a numeric IP address in the SDP. */
00100 
00101     memset(&hints, 0, sizeof(hints));
00102     if (getaddrinfo(dest_addr, NULL, &hints, &ai))
00103         return 0;
00104     getnameinfo(ai->ai_addr, ai->ai_addrlen, dest_addr, size,
00105                 NULL, 0, NI_NUMERICHOST);
00106 #ifdef AF_INET6
00107     if (ai->ai_family == AF_INET6)
00108         av_strlcpy(type, "IP6", type_size);
00109 #endif
00110     is_multicast = ff_is_multicast_address(ai->ai_addr);
00111     freeaddrinfo(ai);
00112     return is_multicast;
00113 }
00114 #else
00115 static int resolve_destination(char *dest_addr, int size, char *type,
00116                                int type_size)
00117 {
00118     return 0;
00119 }
00120 #endif
00121 
00122 static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url)
00123 {
00124     int port;
00125     const char *p;
00126     char proto[32];
00127 
00128     av_url_split(proto, sizeof(proto), NULL, 0, dest_addr, size, &port, NULL, 0, url);
00129 
00130     *ttl = 0;
00131 
00132     if (strcmp(proto, "rtp")) {
00133         /* The url isn't for the actual rtp sessions,
00134          * don't parse out anything else than the destination.
00135          */
00136         return 0;
00137     }
00138 
00139     p = strchr(url, '?');
00140     if (p) {
00141         char buff[64];
00142 
00143         if (av_find_info_tag(buff, sizeof(buff), "ttl", p)) {
00144             *ttl = strtol(buff, NULL, 10);
00145         } else {
00146             *ttl = 5;
00147         }
00148     }
00149 
00150     return port;
00151 }
00152 
00153 #define MAX_PSET_SIZE 1024
00154 static char *extradata2psets(AVCodecContext *c)
00155 {
00156     char *psets, *p;
00157     const uint8_t *r;
00158     const char *pset_string = "; sprop-parameter-sets=";
00159     uint8_t *orig_extradata = NULL;
00160     int orig_extradata_size = 0;
00161 
00162     if (c->extradata_size > MAX_EXTRADATA_SIZE) {
00163         av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
00164 
00165         return NULL;
00166     }
00167     if (c->extradata[0] == 1) {
00168         uint8_t *dummy_p;
00169         int dummy_int;
00170         AVBitStreamFilterContext *bsfc= av_bitstream_filter_init("h264_mp4toannexb");
00171 
00172         if (!bsfc) {
00173             av_log(c, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n");
00174 
00175             return NULL;
00176         }
00177 
00178         orig_extradata_size = c->extradata_size;
00179         orig_extradata = av_mallocz(orig_extradata_size +
00180                                     FF_INPUT_BUFFER_PADDING_SIZE);
00181         if (!orig_extradata) {
00182             av_bitstream_filter_close(bsfc);
00183             return NULL;
00184         }
00185         memcpy(orig_extradata, c->extradata, orig_extradata_size);
00186         av_bitstream_filter_filter(bsfc, c, NULL, &dummy_p, &dummy_int, NULL, 0, 0);
00187         av_bitstream_filter_close(bsfc);
00188     }
00189 
00190     psets = av_mallocz(MAX_PSET_SIZE);
00191     if (psets == NULL) {
00192         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
00193         av_free(orig_extradata);
00194         return NULL;
00195     }
00196     memcpy(psets, pset_string, strlen(pset_string));
00197     p = psets + strlen(pset_string);
00198     r = ff_avc_find_startcode(c->extradata, c->extradata + c->extradata_size);
00199     while (r < c->extradata + c->extradata_size) {
00200         const uint8_t *r1;
00201         uint8_t nal_type;
00202 
00203         while (!*(r++));
00204         nal_type = *r & 0x1f;
00205         r1 = ff_avc_find_startcode(r, c->extradata + c->extradata_size);
00206         if (nal_type != 7 && nal_type != 8) { /* Only output SPS and PPS */
00207             r = r1;
00208             continue;
00209         }
00210         if (p != (psets + strlen(pset_string))) {
00211             *p = ',';
00212             p++;
00213         }
00214         if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) {
00215             av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
00216             av_free(psets);
00217 
00218             return NULL;
00219         }
00220         p += strlen(p);
00221         r = r1;
00222     }
00223     if (orig_extradata) {
00224         av_free(c->extradata);
00225         c->extradata      = orig_extradata;
00226         c->extradata_size = orig_extradata_size;
00227     }
00228 
00229     return psets;
00230 }
00231 
00232 static char *extradata2config(AVCodecContext *c)
00233 {
00234     char *config;
00235 
00236     if (c->extradata_size > MAX_EXTRADATA_SIZE) {
00237         av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
00238 
00239         return NULL;
00240     }
00241     config = av_malloc(10 + c->extradata_size * 2);
00242     if (config == NULL) {
00243         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
00244         return NULL;
00245     }
00246     memcpy(config, "; config=", 9);
00247     ff_data_to_hex(config + 9, c->extradata, c->extradata_size, 0);
00248     config[9 + c->extradata_size * 2] = 0;
00249 
00250     return config;
00251 }
00252 
00253 static char *xiph_extradata2config(AVCodecContext *c)
00254 {
00255     char *config, *encoded_config;
00256     uint8_t *header_start[3];
00257     int headers_len, header_len[3], config_len;
00258     int first_header_size;
00259 
00260     switch (c->codec_id) {
00261     case CODEC_ID_THEORA:
00262         first_header_size = 42;
00263         break;
00264     case CODEC_ID_VORBIS:
00265         first_header_size = 30;
00266         break;
00267     default:
00268         av_log(c, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
00269         return NULL;
00270     }
00271 
00272     if (avpriv_split_xiph_headers(c->extradata, c->extradata_size,
00273                               first_header_size, header_start,
00274                               header_len) < 0) {
00275         av_log(c, AV_LOG_ERROR, "Extradata corrupt.\n");
00276         return NULL;
00277     }
00278 
00279     headers_len = header_len[0] + header_len[2];
00280     config_len = 4 +          // count
00281                  3 +          // ident
00282                  2 +          // packet size
00283                  1 +          // header count
00284                  2 +          // header size
00285                  headers_len; // and the rest
00286 
00287     config = av_malloc(config_len);
00288     if (!config)
00289         goto xiph_fail;
00290 
00291     encoded_config = av_malloc(AV_BASE64_SIZE(config_len));
00292     if (!encoded_config) {
00293         av_free(config);
00294         goto xiph_fail;
00295     }
00296 
00297     config[0] = config[1] = config[2] = 0;
00298     config[3] = 1;
00299     config[4] = (RTP_XIPH_IDENT >> 16) & 0xff;
00300     config[5] = (RTP_XIPH_IDENT >>  8) & 0xff;
00301     config[6] = (RTP_XIPH_IDENT      ) & 0xff;
00302     config[7] = (headers_len >> 8) & 0xff;
00303     config[8] = headers_len & 0xff;
00304     config[9] = 2;
00305     config[10] = header_len[0];
00306     config[11] = 0; // size of comment header; nonexistent
00307     memcpy(config + 12, header_start[0], header_len[0]);
00308     memcpy(config + 12 + header_len[0], header_start[2], header_len[2]);
00309 
00310     av_base64_encode(encoded_config, AV_BASE64_SIZE(config_len),
00311                      config, config_len);
00312     av_free(config);
00313 
00314     return encoded_config;
00315 
00316 xiph_fail:
00317     av_log(c, AV_LOG_ERROR,
00318            "Not enough memory for configuration string\n");
00319     return NULL;
00320 }
00321 
00322 static int latm_context2profilelevel(AVCodecContext *c)
00323 {
00324     /* MP4A-LATM
00325      * The RTP payload format specification is described in RFC 3016
00326      * The encoding specifications are provided in ISO/IEC 14496-3 */
00327 
00328     int profile_level = 0x2B;
00329 
00330     /* TODO: AAC Profile only supports AAC LC Object Type.
00331      * Different Object Types should implement different Profile Levels */
00332 
00333     if (c->sample_rate <= 24000) {
00334         if (c->channels <= 2)
00335             profile_level = 0x28; // AAC Profile, Level 1
00336     } else if (c->sample_rate <= 48000) {
00337         if (c->channels <= 2) {
00338             profile_level = 0x29; // AAC Profile, Level 2
00339         } else if (c->channels <= 5) {
00340             profile_level = 0x2A; // AAC Profile, Level 4
00341         }
00342     } else if (c->sample_rate <= 96000) {
00343         if (c->channels <= 5) {
00344             profile_level = 0x2B; // AAC Profile, Level 5
00345         }
00346     }
00347 
00348     return profile_level;
00349 }
00350 
00351 static char *latm_context2config(AVCodecContext *c)
00352 {
00353     /* MP4A-LATM
00354      * The RTP payload format specification is described in RFC 3016
00355      * The encoding specifications are provided in ISO/IEC 14496-3 */
00356 
00357     uint8_t config_byte[6];
00358     int rate_index;
00359     char *config;
00360 
00361     for (rate_index = 0; rate_index < 16; rate_index++)
00362         if (avpriv_mpeg4audio_sample_rates[rate_index] == c->sample_rate)
00363             break;
00364     if (rate_index == 16) {
00365         av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n");
00366         return NULL;
00367     }
00368 
00369     config_byte[0] = 0x40;
00370     config_byte[1] = 0;
00371     config_byte[2] = 0x20 | rate_index;
00372     config_byte[3] = c->channels << 4;
00373     config_byte[4] = 0x3f;
00374     config_byte[5] = 0xc0;
00375 
00376     config = av_malloc(6*2+1);
00377     if (!config) {
00378         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
00379         return NULL;
00380     }
00381     ff_data_to_hex(config, config_byte, 6, 1);
00382     config[12] = 0;
00383 
00384     return config;
00385 }
00386 
00387 static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, AVFormatContext *fmt)
00388 {
00389     char *config = NULL;
00390 
00391     switch (c->codec_id) {
00392         case CODEC_ID_H264:
00393             if (c->extradata_size) {
00394                 config = extradata2psets(c);
00395             }
00396             av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
00397                                     "a=fmtp:%d packetization-mode=1%s\r\n",
00398                                      payload_type,
00399                                      payload_type, config ? config : "");
00400             break;
00401         case CODEC_ID_H263:
00402         case CODEC_ID_H263P:
00403             /* a=framesize is required by 3GPP TS 26.234 (PSS). It
00404              * actually specifies the maximum video size, but we only know
00405              * the current size. This is required for playback on Android
00406              * stagefright and on Samsung bada. */
00407             av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n"
00408                                     "a=framesize:%d %d-%d\r\n",
00409                                     payload_type,
00410                                     payload_type, c->width, c->height);
00411             break;
00412         case CODEC_ID_MPEG4:
00413             if (c->extradata_size) {
00414                 config = extradata2config(c);
00415             }
00416             av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
00417                                     "a=fmtp:%d profile-level-id=1%s\r\n",
00418                                      payload_type,
00419                                      payload_type, config ? config : "");
00420             break;
00421         case CODEC_ID_AAC:
00422             if (fmt && fmt->oformat->priv_class &&
00423                 av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
00424                 config = latm_context2config(c);
00425                 if (!config)
00426                     return NULL;
00427                 av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
00428                                         "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
00429                                          payload_type, c->sample_rate, c->channels,
00430                                          payload_type, latm_context2profilelevel(c), config);
00431             } else {
00432                 if (c->extradata_size) {
00433                     config = extradata2config(c);
00434                 } else {
00435                     /* FIXME: maybe we can forge config information based on the
00436                      *        codec parameters...
00437                      */
00438                     av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
00439                     return NULL;
00440                 }
00441                 if (config == NULL) {
00442                     return NULL;
00443                 }
00444                 av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
00445                                         "a=fmtp:%d profile-level-id=1;"
00446                                         "mode=AAC-hbr;sizelength=13;indexlength=3;"
00447                                         "indexdeltalength=3%s\r\n",
00448                                          payload_type, c->sample_rate, c->channels,
00449                                          payload_type, config);
00450             }
00451             break;
00452         case CODEC_ID_PCM_S16BE:
00453             if (payload_type >= RTP_PT_PRIVATE)
00454                 av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
00455                                          payload_type,
00456                                          c->sample_rate, c->channels);
00457             break;
00458         case CODEC_ID_PCM_MULAW:
00459             if (payload_type >= RTP_PT_PRIVATE)
00460                 av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
00461                                          payload_type,
00462                                          c->sample_rate, c->channels);
00463             break;
00464         case CODEC_ID_PCM_ALAW:
00465             if (payload_type >= RTP_PT_PRIVATE)
00466                 av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
00467                                          payload_type,
00468                                          c->sample_rate, c->channels);
00469             break;
00470         case CODEC_ID_AMR_NB:
00471             av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
00472                                     "a=fmtp:%d octet-align=1\r\n",
00473                                      payload_type, c->sample_rate, c->channels,
00474                                      payload_type);
00475             break;
00476         case CODEC_ID_AMR_WB:
00477             av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
00478                                     "a=fmtp:%d octet-align=1\r\n",
00479                                      payload_type, c->sample_rate, c->channels,
00480                                      payload_type);
00481             break;
00482         case CODEC_ID_VORBIS:
00483             if (c->extradata_size)
00484                 config = xiph_extradata2config(c);
00485             else
00486                 av_log(c, AV_LOG_ERROR, "Vorbis configuration info missing\n");
00487             if (!config)
00488                 return NULL;
00489 
00490             av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
00491                                     "a=fmtp:%d configuration=%s\r\n",
00492                                     payload_type, c->sample_rate, c->channels,
00493                                     payload_type, config);
00494             break;
00495         case CODEC_ID_THEORA: {
00496             const char *pix_fmt;
00497             if (c->extradata_size)
00498                 config = xiph_extradata2config(c);
00499             else
00500                 av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n");
00501             if (!config)
00502                 return NULL;
00503 
00504             switch (c->pix_fmt) {
00505             case PIX_FMT_YUV420P:
00506                 pix_fmt = "YCbCr-4:2:0";
00507                 break;
00508             case PIX_FMT_YUV422P:
00509                 pix_fmt = "YCbCr-4:2:2";
00510                 break;
00511             case PIX_FMT_YUV444P:
00512                 pix_fmt = "YCbCr-4:4:4";
00513                 break;
00514             default:
00515                 av_log(c, AV_LOG_ERROR, "Unsupported pixel format.\n");
00516                 return NULL;
00517             }
00518 
00519             av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n"
00520                                     "a=fmtp:%d delivery-method=inline; "
00521                                     "width=%d; height=%d; sampling=%s; "
00522                                     "configuration=%s\r\n",
00523                                     payload_type, payload_type,
00524                                     c->width, c->height, pix_fmt, config);
00525             break;
00526         }
00527         case CODEC_ID_VP8:
00528             av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n",
00529                                      payload_type);
00530             break;
00531         case CODEC_ID_ADPCM_G722:
00532             if (payload_type >= RTP_PT_PRIVATE)
00533                 av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n",
00534                                          payload_type,
00535                                          8000, c->channels);
00536             break;
00537         case CODEC_ID_ADPCM_G726: {
00538             if (payload_type >= RTP_PT_PRIVATE)
00539                 av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n",
00540                                          payload_type,
00541                                          c->bits_per_coded_sample*8,
00542                                          c->sample_rate);
00543             break;
00544         }
00545         default:
00546             /* Nothing special to do here... */
00547             break;
00548     }
00549 
00550     av_free(config);
00551 
00552     return buff;
00553 }
00554 
00555 void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt)
00556 {
00557     const char *type;
00558     int payload_type;
00559 
00560     payload_type = ff_rtp_get_payload_type(fmt, c);
00561 
00562     switch (c->codec_type) {
00563         case AVMEDIA_TYPE_VIDEO   : type = "video"      ; break;
00564         case AVMEDIA_TYPE_AUDIO   : type = "audio"      ; break;
00565         case AVMEDIA_TYPE_SUBTITLE: type = "text"       ; break;
00566         default                 : type = "application"; break;
00567     }
00568 
00569     av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type);
00570     sdp_write_address(buff, size, dest_addr, dest_type, ttl);
00571     if (c->bit_rate) {
00572         av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000);
00573     }
00574 
00575     sdp_write_media_attributes(buff, size, c, payload_type, fmt);
00576 }
00577 
00578 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
00579 {
00580     AVDictionaryEntry *title = av_dict_get(ac[0]->metadata, "title", NULL, 0);
00581     struct sdp_session_level s;
00582     int i, j, port, ttl, is_multicast;
00583     char dst[32], dst_type[5];
00584 
00585     memset(buf, 0, size);
00586     memset(&s, 0, sizeof(struct sdp_session_level));
00587     s.user = "-";
00588     s.src_addr = "127.0.0.1";    /* FIXME: Properly set this */
00589     s.src_type = "IP4";
00590     s.name = title ? title->value : "No Name";
00591 
00592     port = 0;
00593     ttl = 0;
00594     if (n_files == 1) {
00595         port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename);
00596         is_multicast = resolve_destination(dst, sizeof(dst), dst_type,
00597                                            sizeof(dst_type));
00598         if (!is_multicast)
00599             ttl = 0;
00600         if (dst[0]) {
00601             s.dst_addr = dst;
00602             s.dst_type = dst_type;
00603             s.ttl = ttl;
00604             if (!strcmp(dst_type, "IP6")) {
00605                 s.src_addr = "::1";
00606                 s.src_type = "IP6";
00607             }
00608         }
00609     }
00610     sdp_write_header(buf, size, &s);
00611 
00612     dst[0] = 0;
00613     for (i = 0; i < n_files; i++) {
00614         if (n_files != 1) {
00615             port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename);
00616             is_multicast = resolve_destination(dst, sizeof(dst), dst_type,
00617                                                sizeof(dst_type));
00618             if (!is_multicast)
00619                 ttl = 0;
00620         }
00621         for (j = 0; j < ac[i]->nb_streams; j++) {
00622             ff_sdp_write_media(buf, size,
00623                                   ac[i]->streams[j]->codec, dst[0] ? dst : NULL,
00624                                   dst_type, (port > 0) ? port + j * 2 : 0, ttl,
00625                                   ac[i]);
00626             if (port <= 0) {
00627                 av_strlcatf(buf, size,
00628                                    "a=control:streamid=%d\r\n", i + j);
00629             }
00630         }
00631     }
00632 
00633     return 0;
00634 }
00635 #else
00636 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
00637 {
00638     return AVERROR(ENOSYS);
00639 }
00640 
00641 void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *dest_addr, const char *dest_type, int port, int ttl, AVFormatContext *fmt)
00642 {
00643 }
00644 #endif
00645 
00646 #if FF_API_SDP_CREATE
00647 int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
00648 {
00649     return av_sdp_create(ac, n_files, buff, size);
00650 }
00651 #endif
Generated on Thu Jul 11 2013 15:38:24 for Libav by doxygen 1.7.1