rtpdec_amr.c
Go to the documentation of this file.
1 /*
2  * RTP AMR Depacketizer, RFC 3267
3  * Copyright (c) 2010 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 
23 #include "avformat.h"
24 #include "rtpdec_formats.h"
25 #include "libavutil/avstring.h"
26 
27 static const uint8_t frame_sizes_nb[16] = {
28  12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0
29 };
30 static const uint8_t frame_sizes_wb[16] = {
31  17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0
32 };
33 
34 struct PayloadContext {
36  int crc;
38  int channels;
39 };
40 
42 {
44  if(!data) return data;
45  data->channels = 1;
46  return data;
47 }
48 
50 {
51  av_free(data);
52 }
53 
55  AVStream *st, AVPacket *pkt, uint32_t *timestamp,
56  const uint8_t *buf, int len, uint16_t seq,
57  int flags)
58 {
59  const uint8_t *frame_sizes = NULL;
60  int frames;
61  int i;
62  const uint8_t *speech_data;
63  uint8_t *ptr;
64 
65  if (st->codec->codec_id == AV_CODEC_ID_AMR_NB) {
66  frame_sizes = frame_sizes_nb;
67  } else if (st->codec->codec_id == AV_CODEC_ID_AMR_WB) {
68  frame_sizes = frame_sizes_wb;
69  } else {
70  av_log(ctx, AV_LOG_ERROR, "Bad codec ID\n");
71  return AVERROR_INVALIDDATA;
72  }
73 
74  if (st->codec->channels != 1) {
75  av_log(ctx, AV_LOG_ERROR, "Only mono AMR is supported\n");
76  return AVERROR_INVALIDDATA;
77  }
79 
80  /* The AMR RTP packet consists of one header byte, followed
81  * by one TOC byte for each AMR frame in the packet, followed
82  * by the speech data for all the AMR frames.
83  *
84  * The header byte contains only a codec mode request, for
85  * requesting what kind of AMR data the sender wants to
86  * receive. Not used at the moment.
87  */
88 
89  /* Count the number of frames in the packet. The highest bit
90  * is set in a TOC byte if there are more frames following.
91  */
92  for (frames = 1; frames < len && (buf[frames] & 0x80); frames++) ;
93 
94  if (1 + frames >= len) {
95  /* We hit the end of the packet while counting frames. */
96  av_log(ctx, AV_LOG_ERROR, "No speech data found\n");
97  return AVERROR_INVALIDDATA;
98  }
99 
100  speech_data = buf + 1 + frames;
101 
102  /* Everything except the codec mode request byte should be output. */
103  if (av_new_packet(pkt, len - 1)) {
104  av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
105  return AVERROR(ENOMEM);
106  }
107  pkt->stream_index = st->index;
108  ptr = pkt->data;
109 
110  for (i = 0; i < frames; i++) {
111  uint8_t toc = buf[1 + i];
112  int frame_size = frame_sizes[(toc >> 3) & 0x0f];
113 
114  if (speech_data + frame_size > buf + len) {
115  /* Too little speech data */
116  av_log(ctx, AV_LOG_WARNING, "Too little speech data in the RTP packet\n");
117  /* Set the unwritten part of the packet to zero. */
118  memset(ptr, 0, pkt->data + pkt->size - ptr);
119  pkt->size = ptr - pkt->data;
120  return 0;
121  }
122 
123  /* Extract the AMR frame mode from the TOC byte */
124  *ptr++ = toc & 0x7C;
125 
126  /* Copy the speech data */
127  memcpy(ptr, speech_data, frame_size);
128  speech_data += frame_size;
129  ptr += frame_size;
130  }
131 
132  if (speech_data < buf + len) {
133  av_log(ctx, AV_LOG_WARNING, "Too much speech data in the RTP packet?\n");
134  /* Set the unwritten part of the packet to zero. */
135  memset(ptr, 0, pkt->data + pkt->size - ptr);
136  pkt->size = ptr - pkt->data;
137  }
138 
139  return 0;
140 }
141 
143  char *attr, char *value)
144 {
145  /* Some AMR SDP configurations contain "octet-align", without
146  * the trailing =1. Therefore, if the value is empty,
147  * interpret it as "1".
148  */
149  if (!strcmp(value, "")) {
150  av_log(NULL, AV_LOG_WARNING, "AMR fmtp attribute %s had "
151  "nonstandard empty value\n", attr);
152  strcpy(value, "1");
153  }
154  if (!strcmp(attr, "octet-align"))
155  data->octet_align = atoi(value);
156  else if (!strcmp(attr, "crc"))
157  data->crc = atoi(value);
158  else if (!strcmp(attr, "interleaving"))
159  data->interleaving = atoi(value);
160  else if (!strcmp(attr, "channels"))
161  data->channels = atoi(value);
162  return 0;
163 }
164 
165 static int amr_parse_sdp_line(AVFormatContext *s, int st_index,
166  PayloadContext *data, const char *line)
167 {
168  const char *p;
169  int ret;
170 
171  if (st_index < 0)
172  return 0;
173 
174  /* Parse an fmtp line this one:
175  * a=fmtp:97 octet-align=1; interleaving=0
176  * That is, a normal fmtp: line followed by semicolon & space
177  * separated key/value pairs.
178  */
179  if (av_strstart(line, "fmtp:", &p)) {
180  ret = ff_parse_fmtp(s->streams[st_index], data, p, amr_parse_fmtp);
181  if (!data->octet_align || data->crc ||
182  data->interleaving || data->channels != 1) {
183  av_log(s, AV_LOG_ERROR, "Unsupported RTP/AMR configuration!\n");
184  return -1;
185  }
186  return ret;
187  }
188  return 0;
189 }
190 
192  .enc_name = "AMR",
193  .codec_type = AVMEDIA_TYPE_AUDIO,
194  .codec_id = AV_CODEC_ID_AMR_NB,
195  .parse_sdp_a_line = amr_parse_sdp_line,
196  .alloc = amr_new_context,
197  .free = amr_free_context,
198  .parse_packet = amr_handle_packet,
199 };
200 
202  .enc_name = "AMR-WB",
203  .codec_type = AVMEDIA_TYPE_AUDIO,
204  .codec_id = AV_CODEC_ID_AMR_WB,
205  .parse_sdp_a_line = amr_parse_sdp_line,
206  .alloc = amr_new_context,
207  .free = amr_free_context,
208  .parse_packet = amr_handle_packet,
209 };
AVPacket pkt
Definition: rtpdec_qt.c:37
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:205
const char * s
Definition: avisynth_c.h:668
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static int amr_parse_sdp_line(AVFormatContext *s, int st_index, PayloadContext *data, const char *line)
Definition: rtpdec_amr.c:165
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
RTP/JPEG specific private data.
Definition: rdt.c:83
int index
stream index in AVFormatContext
Definition: avformat.h:644
uint8_t * buf
the temporary storage buffer
Definition: rtpdec_asf.c:160
RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler
Definition: rtpdec_amr.c:201
Format I/O context.
Definition: avformat.h:944
static const uint8_t frame_sizes[]
Definition: rtpdec_qcelp.c:24
uint8_t
AVStream ** streams
Definition: avformat.h:992
static int amr_handle_packet(AVFormatContext *ctx, PayloadContext *data, AVStream *st, AVPacket *pkt, uint32_t *timestamp, const uint8_t *buf, int len, uint16_t seq, int flags)
Definition: rtpdec_amr.c:54
static int amr_parse_fmtp(AVStream *stream, PayloadContext *data, char *attr, char *value)
Definition: rtpdec_amr.c:142
uint8_t * data
static const uint8_t frame_sizes_nb[16]
Definition: rtpdec_amr.c:27
static const uint8_t frame_size[4]
Definition: g723_1_data.h:58
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
uint32_t timestamp
current frame timestamp
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
Definition: mem.c:183
Definition: graph2dot.c:48
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
uint64_t channel_layout
Audio channel layout.
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
audio channel layout utility functions
ret
Definition: avfilter.c:821
if it could not because there are no more frames
Stream structure.
Definition: avformat.h:643
NULL
Definition: eval.c:55
AVIOContext * data
Definition: rtpdec_vp8.c:35
enum AVCodecID codec_id
static const uint8_t frame_sizes_wb[16]
Definition: rtpdec_amr.c:30
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
double value
Definition: eval.c:82
synthesis window for stochastic i
static void amr_free_context(PayloadContext *data)
Definition: rtpdec_amr.c:49
const char enc_name[50]
Definition: rtpdec.h:120
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:33
Main libavformat public API header.
static PayloadContext * amr_new_context(void)
Definition: rtpdec_amr.c:41
int channels
number of audio channels
int ff_parse_fmtp(AVStream *stream, PayloadContext *data, const char *p, int(*parse_fmtp)(AVStream *stream, PayloadContext *data, char *attr, char *value))
Definition: rtpdec.c:829
#define AV_CH_LAYOUT_MONO
RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler
Definition: rtpdec_amr.c:191
This structure stores compressed data.