Browse code

Add support for AMR audio in the RTP muxer patch by Martin Storsjö (martin AT martin DOT st)

Originally committed as revision 18375 to svn://svn.ffmpeg.org/ffmpeg/trunk

Martin Storsjö authored on 2009/04/08 16:16:14
Showing 6 changed files
... ...
@@ -7,6 +7,7 @@ version <next>:
7 7
 - Alpha channel scaler
8 8
 - PCX encoder
9 9
 - RTP packetization of H.263
10
+- RTP packetization of AMR
10 11
 
11 12
 
12 13
 
... ...
@@ -188,6 +188,7 @@ OBJS-$(CONFIG_ROQ_MUXER)                 += raw.o
188 188
 OBJS-$(CONFIG_RPL_DEMUXER)               += rpl.o
189 189
 OBJS-$(CONFIG_RTP_MUXER)                 += rtp.o         \
190 190
                                             rtp_aac.o     \
191
+                                            rtp_amr.o     \
191 192
                                             rtp_asf.o     \
192 193
                                             rtp_h263.o    \
193 194
                                             rtp_mpv.o     \
194 195
new file mode 100644
... ...
@@ -0,0 +1,66 @@
0
+/*
1
+ * RTP packetization for AMR audio
2
+ * Copyright (c) 2007 Luca Abeni
3
+ * Copyright (c) 2009 Martin Storsjo
4
+ *
5
+ * This file is part of FFmpeg.
6
+ *
7
+ * FFmpeg is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * FFmpeg is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with FFmpeg; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+
22
+#include "avformat.h"
23
+#include "rtpenc.h"
24
+
25
+/**
26
+ * Packetize AMR frames into RTP packets according to RFC 3267,
27
+ * in octet-aligned mode.
28
+ */
29
+void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size)
30
+{
31
+    RTPMuxContext *s          = s1->priv_data;
32
+    int max_header_toc_size   = 1 + s->max_frames_per_packet;
33
+    uint8_t *p;
34
+    int len;
35
+
36
+    /* Test if the packet must be sent. */
37
+    len = s->buf_ptr - s->buf;
38
+    if (s->num_frames == s->max_frames_per_packet || (len && len + size - 1 > s->max_payload_size)) {
39
+        int header_size = s->num_frames + 1;
40
+        p = s->buf + max_header_toc_size - header_size;
41
+        if (p != s->buf)
42
+            memmove(p, s->buf, header_size);
43
+
44
+        ff_rtp_send_data(s1, p, s->buf_ptr - p, 1);
45
+
46
+        s->num_frames = 0;
47
+    }
48
+
49
+    if (!s->num_frames) {
50
+        s->buf[0]    = 0xf0;
51
+        s->buf_ptr   = s->buf + max_header_toc_size;
52
+        s->timestamp = s->cur_timestamp;
53
+    } else {
54
+        /* Mark the previous TOC entry as having more entries following. */
55
+        s->buf[1 + s->num_frames - 1] |= 0x80;
56
+    }
57
+
58
+    /* Copy the frame type and quality bits. */
59
+    s->buf[1 + s->num_frames++] = buff[0] & 0x7C;
60
+    buff++;
61
+    size--;
62
+    memcpy(s->buf_ptr, buff, size);
63
+    s->buf_ptr += size;
64
+}
65
+
... ...
@@ -60,6 +60,8 @@ static int is_supported(enum CodecID id)
60 60
     case CODEC_ID_PCM_U16LE:
61 61
     case CODEC_ID_PCM_U8:
62 62
     case CODEC_ID_MPEG2TS:
63
+    case CODEC_ID_AMR_NB:
64
+    case CODEC_ID_AMR_WB:
63 65
         return 1;
64 66
     default:
65 67
         return 0;
... ...
@@ -134,6 +136,23 @@ static int rtp_write_header(AVFormatContext *s1)
134 134
         s->max_payload_size = n * TS_PACKET_SIZE;
135 135
         s->buf_ptr = s->buf;
136 136
         break;
137
+    case CODEC_ID_AMR_NB:
138
+    case CODEC_ID_AMR_WB:
139
+        if (!s->max_frames_per_packet)
140
+            s->max_frames_per_packet = 12;
141
+        if (st->codec->codec_id == CODEC_ID_AMR_NB)
142
+            n = 31;
143
+        else
144
+            n = 61;
145
+        /* max_header_toc_size + the largest AMR payload must fit */
146
+        if (1 + s->max_frames_per_packet + n > s->max_payload_size) {
147
+            av_log(s1, AV_LOG_ERROR, "RTP max payload size too small for AMR\n");
148
+            return -1;
149
+        }
150
+        if (st->codec->channels != 1) {
151
+            av_log(s1, AV_LOG_ERROR, "Only mono is supported\n");
152
+            return -1;
153
+        }
137 154
     case CODEC_ID_AAC:
138 155
         s->num_frames = 0;
139 156
     default:
... ...
@@ -366,6 +385,10 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
366 366
     case CODEC_ID_AAC:
367 367
         ff_rtp_send_aac(s1, buf1, size);
368 368
         break;
369
+    case CODEC_ID_AMR_NB:
370
+    case CODEC_ID_AMR_WB:
371
+        ff_rtp_send_amr(s1, buf1, size);
372
+        break;
369 373
     case CODEC_ID_MPEG2TS:
370 374
         rtp_send_mpegts_raw(s1, buf1, size);
371 375
         break;
... ...
@@ -59,6 +59,7 @@ void ff_rtp_send_data(AVFormatContext *s1, const uint8_t *buf1, int len, int m);
59 59
 void ff_rtp_send_h264(AVFormatContext *s1, const uint8_t *buf1, int size);
60 60
 void ff_rtp_send_h263(AVFormatContext *s1, const uint8_t *buf1, int size);
61 61
 void ff_rtp_send_aac(AVFormatContext *s1, const uint8_t *buff, int size);
62
+void ff_rtp_send_amr(AVFormatContext *s1, const uint8_t *buff, int size);
62 63
 void ff_rtp_send_mpegvideo(AVFormatContext *s1, const uint8_t *buf1, int size);
63 64
 
64 65
 #endif /* AVFORMAT_RTPENC_H */
... ...
@@ -228,6 +228,18 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
228 228
                                          payload_type,
229 229
                                          c->sample_rate, c->channels);
230 230
             break;
231
+        case CODEC_ID_AMR_NB:
232
+            av_strlcatf(buff, size, "a=rtpmap:%d AMR/%d/%d\r\n"
233
+                                    "a=fmtp:%d octet-align=1\r\n",
234
+                                     payload_type, c->sample_rate, c->channels,
235
+                                     payload_type);
236
+            break;
237
+        case CODEC_ID_AMR_WB:
238
+            av_strlcatf(buff, size, "a=rtpmap:%d AMR-WB/%d/%d\r\n"
239
+                                    "a=fmtp:%d octet-align=1\r\n",
240
+                                     payload_type, c->sample_rate, c->channels,
241
+                                     payload_type);
242
+            break;
231 243
         default:
232 244
             /* Nothing special to do here... */
233 245
             break;