|
|
|
@@ -25,34 +25,42 @@ |
|
|
|
* Determines the duration for each packet. |
|
|
|
*/ |
|
|
|
|
|
|
|
#include "libavutil/log.h" |
|
|
|
|
|
|
|
#include "get_bits.h" |
|
|
|
#include "parser.h" |
|
|
|
#include "xiph.h" |
|
|
|
#include "vorbis_parser.h" |
|
|
|
|
|
|
|
static int parse_id_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
static const AVClass vorbis_parser_class = { |
|
|
|
.class_name = "Vorbis parser", |
|
|
|
.item_name = av_default_item_name, |
|
|
|
.version = LIBAVUTIL_VERSION_INT, |
|
|
|
}; |
|
|
|
|
|
|
|
static int parse_id_header(VorbisParseContext *s, |
|
|
|
const uint8_t *buf, int buf_size) |
|
|
|
{ |
|
|
|
/* Id header should be 30 bytes */ |
|
|
|
if (buf_size < 30) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Id header is too short\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Id header is too short\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* make sure this is the Id header */ |
|
|
|
if (buf[0] != 1) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Id header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Wrong packet type in Id header\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* check for header signature */ |
|
|
|
if (memcmp(&buf[1], "vorbis", 6)) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Id header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid packet signature in Id header\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
if (!(buf[29] & 0x1)) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid framing bit in Id header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid framing bit in Id header\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
@@ -62,7 +70,7 @@ static int parse_id_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
static int parse_setup_header(VorbisParseContext *s, |
|
|
|
const uint8_t *buf, int buf_size) |
|
|
|
{ |
|
|
|
GetBitContext gb, gb0; |
|
|
|
@@ -72,25 +80,25 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
|
|
|
|
/* avoid overread */ |
|
|
|
if (buf_size < 7) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Setup header is too short\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Setup header is too short\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* make sure this is the Setup header */ |
|
|
|
if (buf[0] != 5) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Wrong packet type in Setup header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Wrong packet type in Setup header\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* check for header signature */ |
|
|
|
if (memcmp(&buf[1], "vorbis", 6)) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid packet signature in Setup header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid packet signature in Setup header\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
|
|
|
|
/* reverse bytes so we can easily read backwards with get_bits() */ |
|
|
|
if (!(rev_buf = av_malloc(buf_size))) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Out of memory\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Out of memory\n"); |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
for (i = 0; i < buf_size; i++) |
|
|
|
@@ -105,7 +113,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
} |
|
|
|
} |
|
|
|
if (!got_framing_bit) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid Setup header\n"); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
goto bad_header; |
|
|
|
} |
|
|
|
@@ -132,7 +140,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
} |
|
|
|
} |
|
|
|
if (!got_mode_header) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Invalid Setup header\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid Setup header\n"); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
goto bad_header; |
|
|
|
} |
|
|
|
@@ -141,7 +149,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
* we may need to approach this the long way and parse the whole Setup |
|
|
|
* header, but I hope very much that it never comes to that. */ |
|
|
|
if (last_mode_count > 2) { |
|
|
|
avpriv_request_sample(avctx, |
|
|
|
avpriv_request_sample(s, |
|
|
|
"%d modes (either a false positive or a " |
|
|
|
"sample from an unknown encoder)", |
|
|
|
last_mode_count); |
|
|
|
@@ -149,7 +157,7 @@ static int parse_setup_header(AVCodecContext *avctx, VorbisParseContext *s, |
|
|
|
/* We're limiting the mode count to 63 so that we know that the previous |
|
|
|
* block flag will be in the first packet byte. */ |
|
|
|
if (last_mode_count > 63) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Unsupported mode count: %d\n", |
|
|
|
av_log(s, AV_LOG_ERROR, "Unsupported mode count: %d\n", |
|
|
|
last_mode_count); |
|
|
|
ret = AVERROR_INVALIDDATA; |
|
|
|
goto bad_header; |
|
|
|
@@ -179,20 +187,20 @@ int avpriv_vorbis_parse_extradata(AVCodecContext *avctx, VorbisParseContext *s) |
|
|
|
int header_len[3]; |
|
|
|
int ret; |
|
|
|
|
|
|
|
s->avctx = avctx; |
|
|
|
s->class = &vorbis_parser_class; |
|
|
|
s->extradata_parsed = 1; |
|
|
|
|
|
|
|
if ((ret = avpriv_split_xiph_headers(avctx->extradata, |
|
|
|
avctx->extradata_size, 30, |
|
|
|
header_start, header_len)) < 0) { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Extradata corrupt.\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Extradata corrupt.\n"); |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
if ((ret = parse_id_header(avctx, s, header_start[0], header_len[0])) < 0) |
|
|
|
if ((ret = parse_id_header(s, header_start[0], header_len[0])) < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
if ((ret = parse_setup_header(avctx, s, header_start[2], header_len[2])) < 0) |
|
|
|
if ((ret = parse_setup_header(s, header_start[2], header_len[2])) < 0) |
|
|
|
return ret; |
|
|
|
|
|
|
|
s->valid_extradata = 1; |
|
|
|
@@ -227,7 +235,7 @@ int avpriv_vorbis_parse_frame_flags(VorbisParseContext *s, const uint8_t *buf, |
|
|
|
return 0; |
|
|
|
|
|
|
|
bad_packet: |
|
|
|
av_log(s->avctx, AV_LOG_ERROR, "Invalid packet\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid packet\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
if (s->mode_count == 1) |
|
|
|
@@ -235,7 +243,7 @@ bad_packet: |
|
|
|
else |
|
|
|
mode = (buf[0] & s->mode_mask) >> 1; |
|
|
|
if (mode >= s->mode_count) { |
|
|
|
av_log(s->avctx, AV_LOG_ERROR, "Invalid mode in packet\n"); |
|
|
|
av_log(s, AV_LOG_ERROR, "Invalid mode in packet\n"); |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
} |
|
|
|
if(s->mode_blocksize[mode]){ |
|
|
|
|