Libav 0.7.1
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 
00160     if (c->extradata_size > MAX_EXTRADATA_SIZE) {
00161         av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
00162 
00163         return NULL;
00164     }
00165     if (c->extradata[0] == 1) {
00166         uint8_t *dummy_p;
00167         int dummy_int;
00168         AVBitStreamFilterContext *bsfc= av_bitstream_filter_init("h264_mp4toannexb");
00169 
00170         if (!bsfc) {
00171             av_log(c, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n");
00172 
00173             return NULL;
00174         }
00175         av_bitstream_filter_filter(bsfc, c, NULL, &dummy_p, &dummy_int, NULL, 0, 0);
00176         av_bitstream_filter_close(bsfc);
00177     }
00178 
00179     psets = av_mallocz(MAX_PSET_SIZE);
00180     if (psets == NULL) {
00181         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
00182         return NULL;
00183     }
00184     memcpy(psets, pset_string, strlen(pset_string));
00185     p = psets + strlen(pset_string);
00186     r = ff_avc_find_startcode(c->extradata, c->extradata + c->extradata_size);
00187     while (r < c->extradata + c->extradata_size) {
00188         const uint8_t *r1;
00189         uint8_t nal_type;
00190 
00191         while (!*(r++));
00192         nal_type = *r & 0x1f;
00193         r1 = ff_avc_find_startcode(r, c->extradata + c->extradata_size);
00194         if (nal_type != 7 && nal_type != 8) { /* Only output SPS and PPS */
00195             r = r1;
00196             continue;
00197         }
00198         if (p != (psets + strlen(pset_string))) {
00199             *p = ',';
00200             p++;
00201         }
00202         if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) {
00203             av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
00204             av_free(psets);
00205 
00206             return NULL;
00207         }
00208         p += strlen(p);
00209         r = r1;
00210     }
00211 
00212     return psets;
00213 }
00214 
00215 static char *extradata2config(AVCodecContext *c)
00216 {
00217     char *config;
00218 
00219     if (c->extradata_size > MAX_EXTRADATA_SIZE) {
00220         av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
00221 
00222         return NULL;
00223     }
00224     config = av_malloc(10 + c->extradata_size * 2);
00225     if (config == NULL) {
00226         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
00227         return NULL;
00228     }
00229     memcpy(config, "; config=", 9);
00230     ff_data_to_hex(config + 9, c->extradata, c->extradata_size, 0);
00231     config[9 + c->extradata_size * 2] = 0;
00232 
00233     return config;
00234 }
00235 
00236 static char *xiph_extradata2config(AVCodecContext *c)
00237 {
00238     char *config, *encoded_config;
00239     uint8_t *header_start[3];
00240     int headers_len, header_len[3], config_len;
00241     int first_header_size;
00242 
00243     switch (c->codec_id) {
00244     case CODEC_ID_THEORA:
00245         first_header_size = 42;
00246         break;
00247     case CODEC_ID_VORBIS:
00248         first_header_size = 30;
00249         break;
00250     default:
00251         av_log(c, AV_LOG_ERROR, "Unsupported Xiph codec ID\n");
00252         return NULL;
00253     }
00254 
00255     if (ff_split_xiph_headers(c->extradata, c->extradata_size,
00256                               first_header_size, header_start,
00257                               header_len) < 0) {
00258         av_log(c, AV_LOG_ERROR, "Extradata corrupt.\n");
00259         return NULL;
00260     }
00261 
00262     headers_len = header_len[0] + header_len[2];
00263     config_len = 4 +          // count
00264                  3 +          // ident
00265                  2 +          // packet size
00266                  1 +          // header count
00267                  2 +          // header size
00268                  headers_len; // and the rest
00269 
00270     config = av_malloc(config_len);
00271     if (!config)
00272         goto xiph_fail;
00273 
00274     encoded_config = av_malloc(AV_BASE64_SIZE(config_len));
00275     if (!encoded_config) {
00276         av_free(config);
00277         goto xiph_fail;
00278     }
00279 
00280     config[0] = config[1] = config[2] = 0;
00281     config[3] = 1;
00282     config[4] = (RTP_XIPH_IDENT >> 16) & 0xff;
00283     config[5] = (RTP_XIPH_IDENT >>  8) & 0xff;
00284     config[6] = (RTP_XIPH_IDENT      ) & 0xff;
00285     config[7] = (headers_len >> 8) & 0xff;
00286     config[8] = headers_len & 0xff;
00287     config[9] = 2;
00288     config[10] = header_len[0];
00289     config[11] = 0; // size of comment header; nonexistent
00290     memcpy(config + 12, header_start[0], header_len[0]);
00291     memcpy(config + 12 + header_len[0], header_start[2], header_len[2]);
00292 
00293     av_base64_encode(encoded_config, AV_BASE64_SIZE(config_len),
00294                      config, config_len);
00295     av_free(config);
00296 
00297     return encoded_config;
00298 
00299 xiph_fail:
00300     av_log(c, AV_LOG_ERROR,
00301            "Not enough memory for configuration string\n");
00302     return NULL;
00303 }
00304 
00305 static int latm_context2profilelevel(AVCodecContext *c)
00306 {
00307     /* MP4A-LATM
00308      * The RTP payload format specification is described in RFC 3016
00309      * The encoding specifications are provided in ISO/IEC 14496-3 */
00310 
00311     int profile_level = 0x2B;
00312 
00313     /* TODO: AAC Profile only supports AAC LC Object Type.
00314      * Different Object Types should implement different Profile Levels */
00315 
00316     if (c->sample_rate <= 24000) {
00317         if (c->channels <= 2)
00318             profile_level = 0x28; // AAC Profile, Level 1
00319     } else if (c->sample_rate <= 48000) {
00320         if (c->channels <= 2) {
00321             profile_level = 0x29; // AAC Profile, Level 2
00322         } else if (c->channels <= 5) {
00323             profile_level = 0x2A; // AAC Profile, Level 4
00324         }
00325     } else if (c->sample_rate <= 96000) {
00326         if (c->channels <= 5) {
00327             profile_level = 0x2B; // AAC Profile, Level 5
00328         }
00329     }
00330 
00331     return profile_level;
00332 }
00333 
00334 static char *latm_context2config(AVCodecContext *c)
00335 {
00336     /* MP4A-LATM
00337      * The RTP payload format specification is described in RFC 3016
00338      * The encoding specifications are provided in ISO/IEC 14496-3 */
00339 
00340     uint8_t config_byte[6];
00341     int rate_index;
00342     char *config;
00343 
00344     for (rate_index = 0; rate_index < 16; rate_index++)
00345         if (ff_mpeg4audio_sample_rates[rate_index] == c->sample_rate)
00346             break;
00347     if (rate_index == 16) {
00348         av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n");
00349         return NULL;
00350     }
00351 
00352     config_byte[0] = 0x40;
00353     config_byte[1] = 0;
00354     config_byte[2] = 0x20 | rate_index;
00355     config_byte[3] = c->channels << 4;
00356     config_byte[4] = 0x3f;
00357     config_byte[5] = 0xc0;
00358 
00359     config = av_malloc(6*2+1);
00360     if (!config) {
00361         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the config info.\n");
00362         return NULL;
00363     }
00364     ff_data_to_hex(config, config_byte, 6, 1);
00365     config[12] = 0;
00366 
00367     return config;
00368 }
00369 
00370 static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c, int payload_type, AVFormatContext *fmt)
00371 {
00372     char *config = NULL;
00373 
00374     switch (c->codec_id) {
00375         case CODEC_ID_H264:
00376             if (c->extradata_size) {
00377                 config = extradata2psets(c);
00378             }
00379             av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
00380                                     "a=fmtp:%d packetization-mode=1%s\r\n",
00381                                      payload_type,
00382                                      payload_type, config ? config : "");
00383             break;
00384         case CODEC_ID_H263:
00385         case CODEC_ID_H263P:
00386             /* a=framesize is required by 3GPP TS 26.234 (PSS). It
00387              * actually specifies the maximum video size, but we only know
00388              * the current size. This is required for playback on Android
00389              * stagefright and on Samsung bada. */
00390             av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n"
00391                                     "a=framesize:%d %d-%d\r\n",
00392                                     payload_type,
00393                                     payload_type, c->width, c->height);
00394             break;
00395         case CODEC_ID_MPEG4:
00396             if (c->extradata_size) {
00397                 config = extradata2config(c);
00398             }
00399             av_strlcatf(buff, size, "a=rtpmap:%d MP4V-ES/90000\r\n"
00400                                     "a=fmtp:%d profile-level-id=1%s\r\n",
00401                                      payload_type,
00402                                      payload_type, config ? config : "");
00403             break;
00404         case CODEC_ID_AAC:
00405             if (fmt && fmt->oformat->priv_class &&
00406                 av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
00407                 config = latm_context2config(c);
00408                 if (!config)
00409                     return NULL;
00410                 av_strlcatf(buff, size, "a=rtpmap:%d MP4A-LATM/%d/%d\r\n"
00411                                         "a=fmtp:%d profile-level-id=%d;cpresent=0;config=%s\r\n",
00412                                          payload_type, c->sample_rate, c->channels,
00413                                          payload_type, latm_context2profilelevel(c), config);
00414             } else {
00415                 if (c->extradata_size) {
00416                     config = extradata2config(c);
00417                 } else {
00418                     /* FIXME: maybe we can forge config information based on the
00419                      *        codec parameters...
00420                      */
00421                     av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
00422                     return NULL;
00423                 }
00424                 if (config == NULL) {
00425                     return NULL;
00426                 }
00427                 av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
00428                                         "a=fmtp:%d profile-level-id=1;"
00429                                         "mode=AAC-hbr;sizelength=13;indexlength=3;"
00430                                         "indexdeltalength=3%s\r\n",
00431                                          payload_type, c->sample_rate, c->channels,
00432                                          payload_type, config);
00433             }
00434             break;
00435         case CODEC_ID_PCM_S16BE:
00436             if (payload_type >= RTP_PT_PRIVATE)
00437                 av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
00438                                          payload_type,
00439                                          c->sample_rate, c->channels);
00440             break;
00441         case CODEC_ID_PCM_MULAW:
00442             if (payload_type >= RTP_PT_PRIVATE)
00443                 av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
00444                                          payload_type,
00445                                          c->sample_rate, c->channels);
00446             break;
00447         case CODEC_ID_PCM_ALAW:
00448             if (payload_type >= RTP_PT_PRIVATE)
00449                 av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
00450                                          payload_type,
00451                                          c->sample_rate, c->channels);
00452             break;
00453         case CODEC_ID_AMR_NB:
00454             av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
00455                                     "a=fmtp:%d octet-align=1\r\n",
00456                                      payload_type, c->sample_rate, c->channels,
00457                                      payload_type);
00458             break;
00459         case CODEC_ID_AMR_WB:
00460             av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
00461                                     "a=fmtp:%d octet-align=1\r\n",
00462                                      payload_type, c->sample_rate, c->channels,
00463                                      payload_type);
00464             break;
00465         case CODEC_ID_VORBIS:
00466             if (c->extradata_size)
00467                 config = xiph_extradata2config(c);
00468             else
00469                 av_log(c, AV_LOG_ERROR, "Vorbis configuration info missing\n");
00470             if (!config)
00471                 return NULL;
00472 
00473             av_strlcatf(buff, size, "a=rtpmap:%d vorbis/%d/%d\r\n"
00474                                     "a=fmtp:%d configuration=%s\r\n",
00475                                     payload_type, c->sample_rate, c->channels,
00476                                     payload_type, config);
00477             break;
00478         case CODEC_ID_THEORA: {
00479             const char *pix_fmt;
00480             if (c->extradata_size)
00481                 config = xiph_extradata2config(c);
00482             else
00483                 av_log(c, AV_LOG_ERROR, "Theora configuation info missing\n");
00484             if (!config)
00485                 return NULL;
00486 
00487             switch (c->pix_fmt) {
00488             case PIX_FMT_YUV420P:
00489                 pix_fmt = "YCbCr-4:2:0";
00490                 break;
00491             case PIX_FMT_YUV422P:
00492                 pix_fmt = "YCbCr-4:2:2";
00493                 break;
00494             case PIX_FMT_YUV444P:
00495                 pix_fmt = "YCbCr-4:4:4";
00496                 break;
00497             default:
00498                 av_log(c, AV_LOG_ERROR, "Unsupported pixel format.\n");
00499                 return NULL;
00500             }
00501 
00502             av_strlcatf(buff, size, "a=rtpmap:%d theora/90000\r\n"
00503                                     "a=fmtp:%d delivery-method=inline; "
00504                                     "width=%d; height=%d; sampling=%s; "
00505                                     "configuration=%s\r\n",
00506                                     payload_type, payload_type,
00507                                     c->width, c->height, pix_fmt, config);
00508             break;
00509         }
00510         case CODEC_ID_VP8:
00511             av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n",
00512                                      payload_type);
00513             break;
00514         case CODEC_ID_ADPCM_G722:
00515             if (payload_type >= RTP_PT_PRIVATE)
00516                 av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n",
00517                                          payload_type,
00518                                          8000, c->channels);
00519             break;
00520         default:
00521             /* Nothing special to do here... */
00522             break;
00523     }
00524 
00525     av_free(config);
00526 
00527     return buff;
00528 }
00529 
00530 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)
00531 {
00532     const char *type;
00533     int payload_type;
00534 
00535     payload_type = ff_rtp_get_payload_type(c);
00536     if (payload_type < 0) {
00537         payload_type = RTP_PT_PRIVATE + (c->codec_type == AVMEDIA_TYPE_AUDIO);
00538     }
00539 
00540     switch (c->codec_type) {
00541         case AVMEDIA_TYPE_VIDEO   : type = "video"      ; break;
00542         case AVMEDIA_TYPE_AUDIO   : type = "audio"      ; break;
00543         case AVMEDIA_TYPE_SUBTITLE: type = "text"       ; break;
00544         default                 : type = "application"; break;
00545     }
00546 
00547     av_strlcatf(buff, size, "m=%s %d RTP/AVP %d\r\n", type, port, payload_type);
00548     sdp_write_address(buff, size, dest_addr, dest_type, ttl);
00549     if (c->bit_rate) {
00550         av_strlcatf(buff, size, "b=AS:%d\r\n", c->bit_rate / 1000);
00551     }
00552 
00553     sdp_write_media_attributes(buff, size, c, payload_type, fmt);
00554 }
00555 
00556 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
00557 {
00558     AVDictionaryEntry *title = av_dict_get(ac[0]->metadata, "title", NULL, 0);
00559     struct sdp_session_level s;
00560     int i, j, port, ttl, is_multicast;
00561     char dst[32], dst_type[5];
00562 
00563     memset(buf, 0, size);
00564     memset(&s, 0, sizeof(struct sdp_session_level));
00565     s.user = "-";
00566     s.src_addr = "127.0.0.1";    /* FIXME: Properly set this */
00567     s.src_type = "IP4";
00568     s.name = title ? title->value : "No Name";
00569 
00570     port = 0;
00571     ttl = 0;
00572     if (n_files == 1) {
00573         port = sdp_get_address(dst, sizeof(dst), &ttl, ac[0]->filename);
00574         is_multicast = resolve_destination(dst, sizeof(dst), dst_type,
00575                                            sizeof(dst_type));
00576         if (!is_multicast)
00577             ttl = 0;
00578         if (dst[0]) {
00579             s.dst_addr = dst;
00580             s.dst_type = dst_type;
00581             s.ttl = ttl;
00582             if (!strcmp(dst_type, "IP6")) {
00583                 s.src_addr = "::1";
00584                 s.src_type = "IP6";
00585             }
00586         }
00587     }
00588     sdp_write_header(buf, size, &s);
00589 
00590     dst[0] = 0;
00591     for (i = 0; i < n_files; i++) {
00592         if (n_files != 1) {
00593             port = sdp_get_address(dst, sizeof(dst), &ttl, ac[i]->filename);
00594             is_multicast = resolve_destination(dst, sizeof(dst), dst_type,
00595                                                sizeof(dst_type));
00596             if (!is_multicast)
00597                 ttl = 0;
00598         }
00599         for (j = 0; j < ac[i]->nb_streams; j++) {
00600             ff_sdp_write_media(buf, size,
00601                                   ac[i]->streams[j]->codec, dst[0] ? dst : NULL,
00602                                   dst_type, (port > 0) ? port + j * 2 : 0, ttl,
00603                                   ac[i]);
00604             if (port <= 0) {
00605                 av_strlcatf(buf, size,
00606                                    "a=control:streamid=%d\r\n", i + j);
00607             }
00608         }
00609     }
00610 
00611     return 0;
00612 }
00613 #else
00614 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
00615 {
00616     return AVERROR(ENOSYS);
00617 }
00618 
00619 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)
00620 {
00621 }
00622 #endif
00623 
00624 #if FF_API_SDP_CREATE
00625 int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
00626 {
00627     return av_sdp_create(ac, n_files, buff, size);
00628 }
00629 #endif