|
@@ -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,
|
|
|
};
|
|
|
|