[v2,5/5] rtpenc: Support packetizing iLBC

Message ID 1340008803-89076-5-git-send-email-martin@martin.st
State Superseded
Headers show

Commit Message

Martin Storsjö June 18, 2012, 8:40 a.m.
---
 libavformat/rtpenc.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 libavformat/sdp.c    |    6 ++++++
 2 files changed, 50 insertions(+)

Comments

Luca Barbato June 18, 2012, 9:30 a.m. | #1
On 06/18/2012 10:40 AM, Martin Storsjö wrote:
> +    case CODEC_ID_ILBC:
> +        if (!st->codec->block_align) {
> +            av_log(s1, AV_LOG_ERROR, "No iLBC block size specified\n");
> +            goto fail;
> +        }

who's setting this value? shall we check it is one of the two supported
one? Can we have a fallback instead of an error?

> +        case 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;

I guess we should be stricter in the check before.

lu
Martin Storsjö June 18, 2012, 9:33 a.m. | #2
On Mon, 18 Jun 2012, Luca Barbato wrote:

> On 06/18/2012 10:40 AM, Martin Storsjö wrote:
>> +    case CODEC_ID_ILBC:
>> +        if (!st->codec->block_align) {
>> +            av_log(s1, AV_LOG_ERROR, "No iLBC block size specified\n");
>> +            goto fail;
>> +        }
>
> who's setting this value? shall we check it is one of the two supported
> one? Can we have a fallback instead of an error?

It's set by the demuxer (if doing stream copy) or by the encoder - if it 
isn't set, the data is unparsable.

I guess I could make this check stricter to check for the two supported 
values.

// Martin

Patch

diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index 6752fb6..9ee9d09 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -74,6 +74,7 @@  static int is_supported(enum CodecID id)
     case CODEC_ID_VP8:
     case CODEC_ID_ADPCM_G722:
     case CODEC_ID_ADPCM_G726:
+    case CODEC_ID_ILBC:
         return 1;
     default:
         return 0;
@@ -187,6 +188,16 @@  static int rtp_write_header(AVFormatContext *s1)
          * 8000, even if the sample rate is 16000. See RFC 3551. */
         avpriv_set_pts_info(st, 32, 1, 8000);
         break;
+    case CODEC_ID_ILBC:
+        if (!st->codec->block_align) {
+            av_log(s1, AV_LOG_ERROR, "No iLBC block size specified\n");
+            goto fail;
+        }
+        if (!s->max_frames_per_packet)
+            s->max_frames_per_packet = 1;
+        s->max_frames_per_packet = FFMIN(s->max_frames_per_packet,
+                                         s->max_payload_size / st->codec->block_align);
+        goto defaultcase;
     case CODEC_ID_AMR_NB:
     case CODEC_ID_AMR_WB:
         if (!s->max_frames_per_packet)
@@ -395,6 +406,36 @@  static void rtp_send_mpegts_raw(AVFormatContext *s1,
     }
 }
 
+static int rtp_send_ilbc(AVFormatContext *s1, const uint8_t *buf, int size)
+{
+    RTPMuxContext *s = s1->priv_data;
+    AVStream *st = s1->streams[0];
+    int frame_duration = av_get_audio_frame_duration(st->codec, 0);
+    int frame_size = st->codec->block_align;
+    int frames = size / frame_size;
+
+    while (frames > 0) {
+        int n = FFMIN(s->max_frames_per_packet - s->num_frames, frames);
+
+        if (!s->num_frames) {
+            s->buf_ptr = s->buf;
+            s->timestamp = s->cur_timestamp;
+        }
+        memcpy(s->buf_ptr, buf, n * frame_size);
+        frames           -= n;
+        s->num_frames    += n;
+        s->buf_ptr       += n * frame_size;
+        buf              += n * frame_size;
+        s->cur_timestamp += n * frame_duration;
+
+        if (s->num_frames == s->max_frames_per_packet) {
+            ff_rtp_send_data(s1, s->buf, s->buf_ptr - s->buf, 1);
+            s->num_frames = 0;
+        }
+    }
+    return 0;
+}
+
 static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
 {
     RTPMuxContext *s = s1->priv_data;
@@ -483,6 +524,9 @@  static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
     case CODEC_ID_VP8:
         ff_rtp_send_vp8(s1, pkt->data, size);
         break;
+    case CODEC_ID_ILBC:
+        rtp_send_ilbc(s1, pkt->data, size);
+        break;
     default:
         /* better than nothing : send the codec raw data */
         rtp_send_raw(s1, pkt->data, size);
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 9692aab..4392646 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -544,6 +544,12 @@  static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
                                          c->sample_rate);
             break;
         }
+        case 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;
         default:
             /* Nothing special to do here... */
             break;