summaryrefslogtreecommitdiff
path: root/libavformat/rtpdec_mpeg4.c
diff options
context:
space:
mode:
authorGilles Chanteperdrix <gilles.chanteperdrix@xenomai.org>2015-02-13 22:51:32 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-02-22 00:56:18 +0100
commitfee2cc39becb1930461dff267389717337804a4a (patch)
treed696460a34aff038b5158dd085a9826bf2b61138 /libavformat/rtpdec_mpeg4.c
parent17384b1719807b42943bc8e481133d34fb05d9a5 (diff)
avformat/rtpdec_mpeg4: reassemble fragmented AAC frames
Signed-off-by: Gilles Chanteperdrix <gilles.chanteperdrix@xenomai.org> Reviewed-by: Thomas Volkert <silvo@gmx.net> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/rtpdec_mpeg4.c')
-rw-r--r--libavformat/rtpdec_mpeg4.c84
1 files changed, 76 insertions, 8 deletions
diff --git a/libavformat/rtpdec_mpeg4.c b/libavformat/rtpdec_mpeg4.c
index f22086d5a8..167322b9f0 100644
--- a/libavformat/rtpdec_mpeg4.c
+++ b/libavformat/rtpdec_mpeg4.c
@@ -33,6 +33,8 @@
#include "libavutil/avstring.h"
#include "libavcodec/get_bits.h"
+#define MAX_AAC_HBR_FRAME_SIZE 8191
+
/** Structure listing useful vars to parse RTP packet payload */
struct PayloadContext {
int sizelength;
@@ -59,8 +61,9 @@ struct PayloadContext {
int au_headers_length_bytes;
int cur_au_index;
- uint8_t buf[RTP_MAX_PACKET_LENGTH];
+ uint8_t buf[FFMAX(RTP_MAX_PACKET_LENGTH, MAX_AAC_HBR_FRAME_SIZE)];
int buf_pos, buf_size;
+ uint32_t timestamp;
};
typedef struct AttrNameMap {
@@ -168,30 +171,95 @@ static int aac_parse_packet(AVFormatContext *ctx, PayloadContext *data,
{
int ret;
+
if (!buf) {
- if (data->cur_au_index > data->nb_au_headers)
+ if (data->cur_au_index > data->nb_au_headers) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid parser state\n");
return AVERROR_INVALIDDATA;
- if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size)
+ }
+ if (data->buf_size - data->buf_pos < data->au_headers[data->cur_au_index].size) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
return AVERROR_INVALIDDATA;
- if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0)
+ }
+ if ((ret = av_new_packet(pkt, data->au_headers[data->cur_au_index].size)) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
return ret;
+ }
memcpy(pkt->data, &data->buf[data->buf_pos], data->au_headers[data->cur_au_index].size);
data->buf_pos += data->au_headers[data->cur_au_index].size;
pkt->stream_index = st->index;
data->cur_au_index++;
- return data->cur_au_index < data->nb_au_headers;
+
+ if (data->cur_au_index == data->nb_au_headers) {
+ data->buf_pos = 0;
+ return 0;
+ }
+
+ return 1;
}
- if (rtp_parse_mp4_au(data, buf, len))
+ if (rtp_parse_mp4_au(data, buf, len)) {
+ av_log(ctx, AV_LOG_ERROR, "Error parsing AU headers\n");
return -1;
+ }
buf += data->au_headers_length_bytes + 2;
len -= data->au_headers_length_bytes + 2;
+ if (data->nb_au_headers == 1 && len < data->au_headers[0].size) {
+ /* Packet is fragmented */
+
+ if (!data->buf_pos) {
+ if (data->au_headers[0].size > MAX_AAC_HBR_FRAME_SIZE) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid AU size\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ data->buf_size = data->au_headers[0].size;
+ data->timestamp = *timestamp;
+ }
+
+ if (data->timestamp != *timestamp
+ || data->au_headers[0].size != data->buf_size
+ || data->buf_pos + len > MAX_AAC_HBR_FRAME_SIZE) {
+ data->buf_pos = 0;
+ data->buf_size = 0;
+ av_log(ctx, AV_LOG_ERROR, "Invalid packet received\n");
+ return AVERROR_INVALIDDATA;
+ }
- if (len < data->au_headers[0].size)
+ memcpy(&data->buf[data->buf_pos], buf, len);
+ data->buf_pos += len;
+
+ if (!(flags & RTP_FLAG_MARKER))
+ return AVERROR(EAGAIN);
+
+ if (data->buf_pos != data->buf_size) {
+ data->buf_pos = 0;
+ av_log(ctx, AV_LOG_ERROR, "Missed some packets, discarding frame\n");
+ return AVERROR_INVALIDDATA;
+ }
+
+ data->buf_pos = 0;
+ ret = av_new_packet(pkt, data->buf_size);
+ if (ret < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
+ return ret;
+ }
+ pkt->stream_index = st->index;
+
+ memcpy(pkt->data, data->buf, data->buf_size);
+
+ return 0;
+ }
+
+ if (len < data->au_headers[0].size) {
+ av_log(ctx, AV_LOG_ERROR, "First AU larger than packet size\n");
return AVERROR_INVALIDDATA;
- if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0)
+ }
+ if ((ret = av_new_packet(pkt, data->au_headers[0].size)) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Out of memory\n");
return ret;
+ }
memcpy(pkt->data, buf, data->au_headers[0].size);
len -= data->au_headers[0].size;
buf += data->au_headers[0].size;