]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/rtpdec.c
avcodec/libilbc: Support newer libiLBC versions
[ffmpeg] / libavformat / rtpdec.c
index e75a34cb93330a7e38d2cc13535eca91282025f4..d592e34893dcfcee0e72505129f6a4143c152ae7 100644 (file)
 #include "libavutil/intreadwrite.h"
 #include "libavutil/time.h"
 
+#include "libavcodec/bytestream.h"
+
 #include "avformat.h"
 #include "network.h"
 #include "srtp.h"
 #include "url.h"
 #include "rtpdec.h"
 #include "rtpdec_formats.h"
+#include "internal.h"
 
 #define MIN_FEEDBACK_INTERVAL 200000 /* 200 ms in us */
 
-static RTPDynamicProtocolHandler l24_dynamic_handler = {
+static const RTPDynamicProtocolHandler l24_dynamic_handler = {
     .enc_name   = "L24",
     .codec_type = AVMEDIA_TYPE_AUDIO,
     .codec_id   = AV_CODEC_ID_PCM_S24BE,
 };
 
-static RTPDynamicProtocolHandler gsm_dynamic_handler = {
+static const RTPDynamicProtocolHandler gsm_dynamic_handler = {
     .enc_name   = "GSM",
     .codec_type = AVMEDIA_TYPE_AUDIO,
     .codec_id   = AV_CODEC_ID_GSM,
 };
 
-static RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = {
+static const RTPDynamicProtocolHandler realmedia_mp3_dynamic_handler = {
     .enc_name   = "X-MP3-draft-00",
     .codec_type = AVMEDIA_TYPE_AUDIO,
     .codec_id   = AV_CODEC_ID_MP3ADU,
 };
 
-static RTPDynamicProtocolHandler speex_dynamic_handler = {
+static const RTPDynamicProtocolHandler speex_dynamic_handler = {
     .enc_name   = "speex",
     .codec_type = AVMEDIA_TYPE_AUDIO,
     .codec_id   = AV_CODEC_ID_SPEEX,
 };
 
-static RTPDynamicProtocolHandler opus_dynamic_handler = {
+static const RTPDynamicProtocolHandler opus_dynamic_handler = {
     .enc_name   = "opus",
     .codec_type = AVMEDIA_TYPE_AUDIO,
     .codec_id   = AV_CODEC_ID_OPUS,
 };
 
-static RTPDynamicProtocolHandler t140_dynamic_handler = { /* RFC 4103 */
+static const RTPDynamicProtocolHandler t140_dynamic_handler = { /* RFC 4103 */
     .enc_name   = "t140",
     .codec_type = AVMEDIA_TYPE_SUBTITLE,
     .codec_id   = AV_CODEC_ID_TEXT,
 };
 
-extern RTPDynamicProtocolHandler ff_rdt_video_handler;
-extern RTPDynamicProtocolHandler ff_rdt_audio_handler;
-extern RTPDynamicProtocolHandler ff_rdt_live_video_handler;
-extern RTPDynamicProtocolHandler ff_rdt_live_audio_handler;
+extern const RTPDynamicProtocolHandler ff_rdt_video_handler;
+extern const RTPDynamicProtocolHandler ff_rdt_audio_handler;
+extern const RTPDynamicProtocolHandler ff_rdt_live_video_handler;
+extern const RTPDynamicProtocolHandler ff_rdt_live_audio_handler;
 
-static const RTPDynamicProtocolHandler *rtp_dynamic_protocol_handler_list[] = {
+static const RTPDynamicProtocolHandler *const rtp_dynamic_protocol_handler_list[] = {
     /* rtp */
     &ff_ac3_dynamic_handler,
     &ff_amr_nb_dynamic_handler,
@@ -401,40 +404,26 @@ int ff_rtp_check_and_send_back_rr(RTPDemuxContext *s, URLContext *fd,
 
 void ff_rtp_send_punch_packets(URLContext *rtp_handle)
 {
-    AVIOContext *pb;
-    uint8_t *buf;
-    int len;
+    uint8_t buf[RTP_MIN_PACKET_LENGTH], *ptr = buf;
 
     /* Send a small RTP packet */
-    if (avio_open_dyn_buf(&pb) < 0)
-        return;
 
-    avio_w8(pb, (RTP_VERSION << 6));
-    avio_w8(pb, 0); /* Payload type */
-    avio_wb16(pb, 0); /* Seq */
-    avio_wb32(pb, 0); /* Timestamp */
-    avio_wb32(pb, 0); /* SSRC */
+    bytestream_put_byte(&ptr, (RTP_VERSION << 6));
+    bytestream_put_byte(&ptr, 0); /* Payload type */
+    bytestream_put_be16(&ptr, 0); /* Seq */
+    bytestream_put_be32(&ptr, 0); /* Timestamp */
+    bytestream_put_be32(&ptr, 0); /* SSRC */
 
-    avio_flush(pb);
-    len = avio_close_dyn_buf(pb, &buf);
-    if ((len > 0) && buf)
-        ffurl_write(rtp_handle, buf, len);
-    av_free(buf);
+    ffurl_write(rtp_handle, buf, ptr - buf);
 
     /* Send a minimal RTCP RR */
-    if (avio_open_dyn_buf(&pb) < 0)
-        return;
-
-    avio_w8(pb, (RTP_VERSION << 6));
-    avio_w8(pb, RTCP_RR); /* receiver report */
-    avio_wb16(pb, 1); /* length in words - 1 */
-    avio_wb32(pb, 0); /* our own SSRC */
+    ptr = buf;
+    bytestream_put_byte(&ptr, (RTP_VERSION << 6));
+    bytestream_put_byte(&ptr, RTCP_RR); /* receiver report */
+    bytestream_put_be16(&ptr, 1); /* length in words - 1 */
+    bytestream_put_be32(&ptr, 0); /* our own SSRC */
 
-    avio_flush(pb);
-    len = avio_close_dyn_buf(pb, &buf);
-    if ((len > 0) && buf)
-        ffurl_write(rtp_handle, buf, len);
-    av_free(buf);
+    ffurl_write(rtp_handle, buf, ptr - buf);
 }
 
 static int find_missing_packets(RTPDemuxContext *s, uint16_t *first_missing,
@@ -531,6 +520,43 @@ int ff_rtp_send_rtcp_feedback(RTPDemuxContext *s, URLContext *fd,
     return 0;
 }
 
+static int opus_write_extradata(AVCodecParameters *codecpar)
+{
+    uint8_t *bs;
+    int ret;
+
+    /* This function writes an extradata with a channel mapping family of 0.
+     * This mapping family only supports mono and stereo layouts. And RFC7587
+     * specifies that the number of channels in the SDP must be 2.
+     */
+    if (codecpar->channels > 2) {
+        return AVERROR_INVALIDDATA;
+    }
+
+    ret = ff_alloc_extradata(codecpar, 19);
+    if (ret < 0)
+        return ret;
+
+    bs = (uint8_t *)codecpar->extradata;
+
+    /* Opus magic */
+    bytestream_put_buffer(&bs, "OpusHead", 8);
+    /* Version */
+    bytestream_put_byte  (&bs, 0x1);
+    /* Channel count */
+    bytestream_put_byte  (&bs, codecpar->channels);
+    /* Pre skip */
+    bytestream_put_le16  (&bs, 0);
+    /* Input sample rate */
+    bytestream_put_le32  (&bs, 48000);
+    /* Output gain */
+    bytestream_put_le16  (&bs, 0x0);
+    /* Mapping family */
+    bytestream_put_byte  (&bs, 0x0);
+
+    return 0;
+}
+
 /**
  * open a new RTP parse context for stream 'st'. 'st' can be NULL for
  * MPEG-2 TS streams.
@@ -539,6 +565,7 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
                                    int payload_type, int queue_size)
 {
     RTPDemuxContext *s;
+    int ret;
 
     s = av_mallocz(sizeof(RTPDemuxContext));
     if (!s)
@@ -562,6 +589,16 @@ RTPDemuxContext *ff_rtp_parse_open(AVFormatContext *s1, AVStream *st,
             if (st->codecpar->sample_rate == 8000)
                 st->codecpar->sample_rate = 16000;
             break;
+        case AV_CODEC_ID_OPUS:
+            ret = opus_write_extradata(st->codecpar);
+            if (ret < 0) {
+                av_log(s1, AV_LOG_ERROR,
+                       "Error creating opus extradata: %s\n",
+                       av_err2str(ret));
+                av_free(s);
+                return NULL;
+            }
+            break;
         default:
             break;
         }