segment: Use the public av_write_header/av_write_trailer functions
[ffmpeg.git] / libavformat / sdp.c
index 92690f5..3791930 100644 (file)
@@ -88,7 +88,7 @@ static void sdp_write_header(char *buff, int size, struct sdp_session_level *s)
 static int resolve_destination(char *dest_addr, int size, char *type,
                                int type_size)
 {
-    struct addrinfo hints, *ai;
+    struct addrinfo hints = { 0 }, *ai;
     int is_multicast;
 
     av_strlcpy(type, "IP4", type_size);
@@ -98,7 +98,6 @@ static int resolve_destination(char *dest_addr, int size, char *type,
     /* Resolve the destination, since it must be written
      * as a numeric IP address in the SDP. */
 
-    memset(&hints, 0, sizeof(hints));
     if (getaddrinfo(dest_addr, NULL, &hints, &ai))
         return 0;
     getnameinfo(ai->ai_addr, ai->ai_addrlen, dest_addr, size,
@@ -155,7 +154,11 @@ static char *extradata2psets(AVCodecContext *c)
 {
     char *psets, *p;
     const uint8_t *r;
-    const char *pset_string = "; sprop-parameter-sets=";
+    static const char pset_string[] = "; sprop-parameter-sets=";
+    static const char profile_string[] = "; profile-level-id=";
+    uint8_t *orig_extradata = NULL;
+    int orig_extradata_size = 0;
+    const uint8_t *sps = NULL, *sps_end;
 
     if (c->extradata_size > MAX_EXTRADATA_SIZE) {
         av_log(c, AV_LOG_ERROR, "Too much extradata!\n");
@@ -172,6 +175,15 @@ static char *extradata2psets(AVCodecContext *c)
 
             return NULL;
         }
+
+        orig_extradata_size = c->extradata_size;
+        orig_extradata = av_mallocz(orig_extradata_size +
+                                    FF_INPUT_BUFFER_PADDING_SIZE);
+        if (!orig_extradata) {
+            av_bitstream_filter_close(bsfc);
+            return NULL;
+        }
+        memcpy(orig_extradata, c->extradata, orig_extradata_size);
         av_bitstream_filter_filter(bsfc, c, NULL, &dummy_p, &dummy_int, NULL, 0, 0);
         av_bitstream_filter_close(bsfc);
     }
@@ -179,6 +191,7 @@ static char *extradata2psets(AVCodecContext *c)
     psets = av_mallocz(MAX_PSET_SIZE);
     if (psets == NULL) {
         av_log(c, AV_LOG_ERROR, "Cannot allocate memory for the parameter sets.\n");
+        av_free(orig_extradata);
         return NULL;
     }
     memcpy(psets, pset_string, strlen(pset_string));
@@ -199,6 +212,10 @@ static char *extradata2psets(AVCodecContext *c)
             *p = ',';
             p++;
         }
+        if (!sps) {
+            sps = r;
+            sps_end = r1;
+        }
         if (av_base64_encode(p, MAX_PSET_SIZE - (p - psets), r, r1 - r) == NULL) {
             av_log(c, AV_LOG_ERROR, "Cannot Base64-encode %td %td!\n", MAX_PSET_SIZE - (p - psets), r1 - r);
             av_free(psets);
@@ -208,6 +225,17 @@ static char *extradata2psets(AVCodecContext *c)
         p += strlen(p);
         r = r1;
     }
+    if (sps && sps_end - sps >= 4) {
+        memcpy(p, profile_string, strlen(profile_string));
+        p += strlen(p);
+        ff_data_to_hex(p, sps + 1, 3, 0);
+        p[6] = '\0';
+    }
+    if (orig_extradata) {
+        av_free(c->extradata);
+        c->extradata      = orig_extradata;
+        c->extradata_size = orig_extradata_size;
+    }
 
     return psets;
 }
@@ -241,10 +269,10 @@ static char *xiph_extradata2config(AVCodecContext *c)
     int first_header_size;
 
     switch (c->codec_id) {
-    case CODEC_ID_THEORA:
+    case AV_CODEC_ID_THEORA:
         first_header_size = 42;
         break;
-    case CODEC_ID_VORBIS:
+    case AV_CODEC_ID_VORBIS:
         first_header_size = 30;
         break;
     default:
@@ -252,7 +280,7 @@ static char *xiph_extradata2config(AVCodecContext *c)
         return NULL;
     }
 
-    if (ff_split_xiph_headers(c->extradata, c->extradata_size,
+    if (avpriv_split_xiph_headers(c->extradata, c->extradata_size,
                               first_header_size, header_start,
                               header_len) < 0) {
         av_log(c, AV_LOG_ERROR, "Extradata corrupt.\n");
@@ -342,7 +370,7 @@ static char *latm_context2config(AVCodecContext *c)
     char *config;
 
     for (rate_index = 0; rate_index < 16; rate_index++)
-        if (ff_mpeg4audio_sample_rates[rate_index] == c->sample_rate)
+        if (avpriv_mpeg4audio_sample_rates[rate_index] == c->sample_rate)
             break;
     if (rate_index == 16) {
         av_log(c, AV_LOG_ERROR, "Unsupported sample rate\n");
@@ -372,27 +400,35 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
     char *config = NULL;
 
     switch (c->codec_id) {
-        case CODEC_ID_H264:
+        case AV_CODEC_ID_H264: {
+            int mode = 1;
+            if (fmt && fmt->oformat->priv_class &&
+                av_opt_flag_is_set(fmt->priv_data, "rtpflags", "h264_mode0"))
+                mode = 0;
             if (c->extradata_size) {
                 config = extradata2psets(c);
             }
             av_strlcatf(buff, size, "a=rtpmap:%d H264/90000\r\n"
-                                    "a=fmtp:%d packetization-mode=1%s\r\n",
+                                    "a=fmtp:%d packetization-mode=%d%s\r\n",
                                      payload_type,
-                                     payload_type, config ? config : "");
+                                     payload_type, mode, config ? config : "");
             break;
-        case CODEC_ID_H263:
-        case CODEC_ID_H263P:
+        }
+        case AV_CODEC_ID_H263:
+        case AV_CODEC_ID_H263P:
             /* a=framesize is required by 3GPP TS 26.234 (PSS). It
              * actually specifies the maximum video size, but we only know
              * the current size. This is required for playback on Android
              * stagefright and on Samsung bada. */
+            if (!fmt || !fmt->oformat->priv_class ||
+                !av_opt_flag_is_set(fmt->priv_data, "rtpflags", "rfc2190") ||
+                c->codec_id == AV_CODEC_ID_H263P)
             av_strlcatf(buff, size, "a=rtpmap:%d H263-2000/90000\r\n"
                                     "a=framesize:%d %d-%d\r\n",
                                     payload_type,
                                     payload_type, c->width, c->height);
             break;
-        case CODEC_ID_MPEG4:
+        case AV_CODEC_ID_MPEG4:
             if (c->extradata_size) {
                 config = extradata2config(c);
             }
@@ -401,7 +437,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                      payload_type,
                                      payload_type, config ? config : "");
             break;
-        case CODEC_ID_AAC:
+        case AV_CODEC_ID_AAC:
             if (fmt && fmt->oformat->priv_class &&
                 av_opt_flag_is_set(fmt->priv_data, "rtpflags", "latm")) {
                 config = latm_context2config(c);
@@ -412,57 +448,57 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                          payload_type, c->sample_rate, c->channels,
                                          payload_type, latm_context2profilelevel(c), config);
             } else {
-            if (c->extradata_size) {
-                config = extradata2config(c);
-            } else {
-                /* FIXME: maybe we can forge config information based on the
-                 *        codec parameters...
-                 */
-                av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
-                return NULL;
-            }
-            if (config == NULL) {
-                return NULL;
-            }
-            av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
-                                    "a=fmtp:%d profile-level-id=1;"
-                                    "mode=AAC-hbr;sizelength=13;indexlength=3;"
-                                    "indexdeltalength=3%s\r\n",
-                                     payload_type, c->sample_rate, c->channels,
-                                     payload_type, config);
+                if (c->extradata_size) {
+                    config = extradata2config(c);
+                } else {
+                    /* FIXME: maybe we can forge config information based on the
+                     *        codec parameters...
+                     */
+                    av_log(c, AV_LOG_ERROR, "AAC with no global headers is currently not supported.\n");
+                    return NULL;
+                }
+                if (config == NULL) {
+                    return NULL;
+                }
+                av_strlcatf(buff, size, "a=rtpmap:%d MPEG4-GENERIC/%d/%d\r\n"
+                                        "a=fmtp:%d profile-level-id=1;"
+                                        "mode=AAC-hbr;sizelength=13;indexlength=3;"
+                                        "indexdeltalength=3%s\r\n",
+                                         payload_type, c->sample_rate, c->channels,
+                                         payload_type, config);
             }
             break;
-        case CODEC_ID_PCM_S16BE:
+        case AV_CODEC_ID_PCM_S16BE:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d L16/%d/%d\r\n",
                                          payload_type,
                                          c->sample_rate, c->channels);
             break;
-        case CODEC_ID_PCM_MULAW:
+        case AV_CODEC_ID_PCM_MULAW:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d PCMU/%d/%d\r\n",
                                          payload_type,
                                          c->sample_rate, c->channels);
             break;
-        case CODEC_ID_PCM_ALAW:
+        case AV_CODEC_ID_PCM_ALAW:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d PCMA/%d/%d\r\n",
                                          payload_type,
                                          c->sample_rate, c->channels);
             break;
-        case CODEC_ID_AMR_NB:
+        case AV_CODEC_ID_AMR_NB:
             av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
                                     "a=fmtp:%d octet-align=1\r\n",
                                      payload_type, c->sample_rate, c->channels,
                                      payload_type);
             break;
-        case CODEC_ID_AMR_WB:
+        case AV_CODEC_ID_AMR_WB:
             av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
                                     "a=fmtp:%d octet-align=1\r\n",
                                      payload_type, c->sample_rate, c->channels,
                                      payload_type);
             break;
-        case CODEC_ID_VORBIS:
+        case AV_CODEC_ID_VORBIS:
             if (c->extradata_size)
                 config = xiph_extradata2config(c);
             else
@@ -475,7 +511,7 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                     payload_type, c->sample_rate, c->channels,
                                     payload_type, config);
             break;
-        case CODEC_ID_THEORA: {
+        case AV_CODEC_ID_THEORA: {
             const char *pix_fmt;
             if (c->extradata_size)
                 config = xiph_extradata2config(c);
@@ -507,16 +543,39 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                     c->width, c->height, pix_fmt, config);
             break;
         }
-        case CODEC_ID_VP8:
+        case AV_CODEC_ID_VP8:
             av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n",
                                      payload_type);
             break;
-        case CODEC_ID_ADPCM_G722:
+        case AV_CODEC_ID_MJPEG:
+            if (payload_type >= RTP_PT_PRIVATE)
+                av_strlcatf(buff, size, "a=rtpmap:%d JPEG/90000\r\n",
+                                         payload_type);
+            break;
+        case AV_CODEC_ID_ADPCM_G722:
             if (payload_type >= RTP_PT_PRIVATE)
                 av_strlcatf(buff, size, "a=rtpmap:%d G722/%d/%d\r\n",
                                          payload_type,
                                          8000, c->channels);
             break;
+        case AV_CODEC_ID_ADPCM_G726: {
+            if (payload_type >= RTP_PT_PRIVATE)
+                av_strlcatf(buff, size, "a=rtpmap:%d G726-%d/%d\r\n",
+                                         payload_type,
+                                         c->bits_per_coded_sample*8,
+                                         c->sample_rate);
+            break;
+        }
+        case AV_CODEC_ID_ILBC:
+            av_strlcatf(buff, size, "a=rtpmap:%d iLBC/%d\r\n"
+                                    "a=fmtp:%d mode=%d\r\n",
+                                     payload_type, c->sample_rate,
+                                     payload_type, c->block_align == 38 ? 20 : 30);
+            break;
+        case AV_CODEC_ID_SPEEX:
+            av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n",
+                                     payload_type, c->sample_rate);
+            break;
         default:
             /* Nothing special to do here... */
             break;
@@ -532,10 +591,7 @@ void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *des
     const char *type;
     int payload_type;
 
-    payload_type = ff_rtp_get_payload_type(c);
-    if (payload_type < 0) {
-        payload_type = RTP_PT_PRIVATE + (c->codec_type == AVMEDIA_TYPE_AUDIO);
-    }
+    payload_type = ff_rtp_get_payload_type(fmt, c);
 
     switch (c->codec_type) {
         case AVMEDIA_TYPE_VIDEO   : type = "video"      ; break;
@@ -556,12 +612,11 @@ void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *des
 int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
 {
     AVDictionaryEntry *title = av_dict_get(ac[0]->metadata, "title", NULL, 0);
-    struct sdp_session_level s;
+    struct sdp_session_level s = { 0 };
     int i, j, port, ttl, is_multicast;
     char dst[32], dst_type[5];
 
     memset(buf, 0, size);
-    memset(&s, 0, sizeof(struct sdp_session_level));
     s.user = "-";
     s.src_addr = "127.0.0.1";    /* FIXME: Properly set this */
     s.src_type = "IP4";
@@ -620,10 +675,3 @@ void ff_sdp_write_media(char *buff, int size, AVCodecContext *c, const char *des
 {
 }
 #endif
-
-#if FF_API_SDP_CREATE
-int avf_sdp_create(AVFormatContext *ac[], int n_files, char *buff, int size)
-{
-    return av_sdp_create(ac, n_files, buff, size);
-}
-#endif