Commit a4942951 authored by Josh Allmann's avatar Josh Allmann Committed by Martin Storsjö

rtpdec: Clean up FMTP parsing code in AMR RTP depacketizer

Patch by Josh Allmann, joshua dot allmann at gmail

Originally committed as revision 23861 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent af1308f0
......@@ -30,6 +30,26 @@ static const uint8_t frame_sizes_wb[16] = {
17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0
};
struct PayloadContext {
int octet_align;
int crc;
int interleaving;
int channels;
};
static PayloadContext *amr_new_context(void)
{
PayloadContext *data = av_mallocz(sizeof(PayloadContext));
if(!data) return data;
data->channels = 1;
return data;
}
static void amr_free_context(PayloadContext *data)
{
av_free(data);
}
static int amr_handle_packet(AVFormatContext *ctx,
PayloadContext *data,
AVStream *st,
......@@ -120,50 +140,48 @@ static int amr_handle_packet(AVFormatContext *ctx,
return 0;
}
static int amr_parse_sdp_line(AVFormatContext *s, int st_index,
PayloadContext *data, const char *line)
static int amr_parse_fmtp(AVStream *stream, PayloadContext *data,
char *attr, char *value)
{
const char *p;
char attr[25], value[25];
/* Parse an fmtp line this one:
* a=fmtp:97 octet-align=1; interleaving=0
* That is, a normal fmtp: line followed by semicolon & space
* separated key/value pairs.
*/
if (av_strstart(line, "fmtp:", &p)) {
int octet_align = 0;
int crc = 0;
int interleaving = 0;
int channels = 1;
while (*p && *p == ' ') p++; /* strip spaces */
while (*p && *p != ' ') p++; /* eat protocol identifier */
while (*p && *p == ' ') p++; /* strip trailing spaces */
while (ff_rtsp_next_attr_and_value(&p, attr, sizeof(attr), value, sizeof(value))) {
/* Some AMR SDP configurations contain "octet-align", without
* the trailing =1. Therefore, if the value is empty,
* interpret it as "1".
*/
if (!strcmp(value, "")) {
av_log(s, AV_LOG_WARNING, "AMR fmtp attribute %s had "
"nonstandard empty value\n", attr);
av_log(NULL, AV_LOG_WARNING, "AMR fmtp attribute %s had "
"nonstandard empty value\n", attr);
strcpy(value, "1");
}
if (!strcmp(attr, "octet-align"))
octet_align = atoi(value);
data->octet_align = atoi(value);
else if (!strcmp(attr, "crc"))
crc = atoi(value);
data->crc = atoi(value);
else if (!strcmp(attr, "interleaving"))
interleaving = atoi(value);
data->interleaving = atoi(value);
else if (!strcmp(attr, "channels"))
channels = atoi(value);
}
if (!octet_align || crc || interleaving || channels != 1) {
data->channels = atoi(value);
return 0;
}
static int amr_parse_sdp_line(AVFormatContext *s, int st_index,
PayloadContext *data, const char *line)
{
const char *p;
int ret;
/* Parse an fmtp line this one:
* a=fmtp:97 octet-align=1; interleaving=0
* That is, a normal fmtp: line followed by semicolon & space
* separated key/value pairs.
*/
if (av_strstart(line, "fmtp:", &p)) {
ret = ff_parse_fmtp(s->streams[st_index], data, p, amr_parse_fmtp);
if (!data->octet_align || data->crc ||
data->interleaving || data->channels != 1) {
av_log(s, AV_LOG_ERROR, "Unsupported RTP/AMR configuration!\n");
return -1;
}
return ret;
}
return 0;
}
......@@ -173,6 +191,8 @@ RTPDynamicProtocolHandler ff_amr_nb_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_AMR_NB,
.parse_sdp_a_line = amr_parse_sdp_line,
.open = amr_new_context,
.close = amr_free_context,
.parse_packet = amr_handle_packet,
};
......@@ -181,6 +201,8 @@ RTPDynamicProtocolHandler ff_amr_wb_dynamic_handler = {
.codec_type = AVMEDIA_TYPE_AUDIO,
.codec_id = CODEC_ID_AMR_WB,
.parse_sdp_a_line = amr_parse_sdp_line,
.open = amr_new_context,
.close = amr_free_context,
.parse_packet = amr_handle_packet,
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment