]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/sdp.c
lavc decoders: properly initialize AVFrame.
[ffmpeg] / libavformat / sdp.c
index 7df8b13b67edbe983e36b9cd9cf5569e6bfa3e3e..186f83b1a01761c3dd5fafa0401c8d3d48ffd6a4 100644 (file)
@@ -128,7 +128,7 @@ static int sdp_get_address(char *dest_addr, int size, int *ttl, const char *url)
 
     *ttl = 0;
 
-    if (strcmp(proto, "rtp")) {
+    if (strcmp(proto, "rtp") && strcmp(proto, "srtp")) {
         /* The url isn't for the actual rtp sessions,
          * don't parse out anything else than the destination.
          */
@@ -154,9 +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");
@@ -210,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);
@@ -219,6 +225,12 @@ 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;
@@ -257,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:
@@ -388,7 +400,7 @@ 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"))
@@ -402,21 +414,21 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                      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 == CODEC_ID_H263P)
+                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);
             }
@@ -425,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);
@@ -456,37 +468,37 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                          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
@@ -499,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);
@@ -509,13 +521,13 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                 return NULL;
 
             switch (c->pix_fmt) {
-            case PIX_FMT_YUV420P:
+            case AV_PIX_FMT_YUV420P:
                 pix_fmt = "YCbCr-4:2:0";
                 break;
-            case PIX_FMT_YUV422P:
+            case AV_PIX_FMT_YUV422P:
                 pix_fmt = "YCbCr-4:2:2";
                 break;
-            case PIX_FMT_YUV444P:
+            case AV_PIX_FMT_YUV444P:
                 pix_fmt = "YCbCr-4:4:4";
                 break;
             default:
@@ -531,17 +543,22 @@ 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 CODEC_ID_ADPCM_G726: {
+        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,
@@ -549,6 +566,20 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                          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;
+        case AV_CODEC_ID_OPUS:
+            av_strlcatf(buff, size, "a=rtpmap:%d opus/48000\r\n",
+                                     payload_type);
+            break;
         default:
             /* Nothing special to do here... */
             break;
@@ -559,12 +590,15 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
     return buff;
 }
 
-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)
+void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx,
+                        const char *dest_addr, const char *dest_type,
+                        int port, int ttl, AVFormatContext *fmt)
 {
+    AVCodecContext *c = st->codec;
     const char *type;
     int payload_type;
 
-    payload_type = ff_rtp_get_payload_type(fmt, c);
+    payload_type = ff_rtp_get_payload_type(fmt, c, idx);
 
     switch (c->codec_type) {
         case AVMEDIA_TYPE_VIDEO   : type = "video"      ; break;
@@ -586,7 +620,7 @@ 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 = { 0 };
-    int i, j, port, ttl, is_multicast;
+    int i, j, port, ttl, is_multicast, index = 0;
     char dst[32], dst_type[5];
 
     memset(buf, 0, size);
@@ -625,14 +659,27 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
                 ttl = 0;
         }
         for (j = 0; j < ac[i]->nb_streams; j++) {
-            ff_sdp_write_media(buf, size,
-                                  ac[i]->streams[j]->codec, dst[0] ? dst : NULL,
-                                  dst_type, (port > 0) ? port + j * 2 : 0, ttl,
-                                  ac[i]);
+            ff_sdp_write_media(buf, size, ac[i]->streams[j], index++,
+                               dst[0] ? dst : NULL, dst_type,
+                               (port > 0) ? port + j * 2 : 0,
+                               ttl, ac[i]);
             if (port <= 0) {
                 av_strlcatf(buf, size,
                                    "a=control:streamid=%d\r\n", i + j);
             }
+            if (ac[i]->pb && ac[i]->pb->av_class) {
+                uint8_t *crypto_suite = NULL, *crypto_params = NULL;
+                av_opt_get(ac[i]->pb, "srtp_out_suite",  AV_OPT_SEARCH_CHILDREN,
+                           &crypto_suite);
+                av_opt_get(ac[i]->pb, "srtp_out_params", AV_OPT_SEARCH_CHILDREN,
+                           &crypto_params);
+                if (crypto_suite && crypto_suite[0])
+                    av_strlcatf(buf, size,
+                                "a=crypto:1 %s inline:%s\r\n",
+                                crypto_suite, crypto_params);
+                av_free(crypto_suite);
+                av_free(crypto_params);
+            }
         }
     }
 
@@ -644,7 +691,9 @@ int av_sdp_create(AVFormatContext *ac[], int n_files, char *buf, int size)
     return AVERROR(ENOSYS);
 }
 
-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)
+void ff_sdp_write_media(char *buff, int size, AVStream *st, int idx,
+                        const char *dest_addr, const char *dest_type,
+                        int port, int ttl, AVFormatContext *fmt)
 {
 }
 #endif