flacdec: Split the metadata_parse() function into 2 separate functions,

parse_streaminfo() and get_metadata_size().

Originally committed as revision 17817 to svn://svn.ffmpeg.org/ffmpeg/trunk
release/0.6
Justin Ruggles 16 years ago
parent 5ef4fa87b3
commit a8ec12bc2e
  1. 86
      libavcodec/flacdec.c

@ -39,6 +39,7 @@
#include "avcodec.h" #include "avcodec.h"
#include "internal.h" #include "internal.h"
#include "bitstream.h" #include "bitstream.h"
#include "bytestream.h"
#include "golomb.h" #include "golomb.h"
#include "flac.h" #include "flac.h"
@ -220,46 +221,57 @@ void ff_flac_parse_streaminfo(AVCodecContext *avctx, struct FLACStreaminfo *s,
} }
/** /**
* Parse a list of metadata blocks. This list of blocks must begin with * Parse the STREAMINFO from an inline header.
* the fLaC marker. * @param s the flac decoding context
* @param s the flac decoding context containing the gb bit reader used to * @param buf input buffer, starting with the "fLaC" marker
* parse metadata * @param buf_size buffer size
* @return non-zero if metadata is invalid * @return non-zero if metadata is invalid
*/ */
static int metadata_parse(FLACContext *s) static int parse_streaminfo(FLACContext *s, const uint8_t *buf, int buf_size)
{ {
int i, metadata_last, metadata_type, metadata_size; int metadata_type, metadata_size;
skip_bits_long(&s->gb, 32); if (buf_size < FLAC_STREAMINFO_SIZE+8) {
/* need more data */
do { return 0;
metadata_last = get_bits1(&s->gb);
metadata_type = get_bits(&s->gb, 7);
metadata_size = get_bits_long(&s->gb, 24);
if (get_bits_count(&s->gb) + 8*metadata_size > s->gb.size_in_bits) {
/* need more data. reset the bitstream reader and return. */
init_get_bits(&s->gb, s->gb.buffer, s->gb.size_in_bits);
break;
} }
buf += 4;
if (metadata_size) { metadata_type = bytestream_get_byte(&buf) & 0x7F;
switch (metadata_type) { metadata_size = bytestream_get_be24(&buf);
case FLAC_METADATA_TYPE_STREAMINFO: if (metadata_type != FLAC_METADATA_TYPE_STREAMINFO ||
if (!s->got_streaminfo) { metadata_size != FLAC_STREAMINFO_SIZE) {
ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, return AVERROR_INVALIDDATA;
s->gb.buffer+get_bits_count(&s->gb)/8); }
ff_flac_parse_streaminfo(s->avctx, (FLACStreaminfo *)s, buf);
allocate_buffers(s); allocate_buffers(s);
s->got_streaminfo = 1; s->got_streaminfo = 1;
return 0;
}
/**
* Determine the size of an inline header.
* @param buf input buffer, starting with the "fLaC" marker
* @param buf_size buffer size
* @return number of bytes in the header, or 0 if more data is needed
*/
static int get_metadata_size(const uint8_t *buf, int buf_size)
{
int metadata_last, metadata_size;
const uint8_t *buf_end = buf + buf_size;
buf += 4;
do {
metadata_last = bytestream_get_byte(&buf) & 0x80;
metadata_size = bytestream_get_be24(&buf);
if (buf + metadata_size > buf_end) {
/* need more data in order to read the complete header */
return 0;
} }
default: buf += metadata_size;
for (i = 0; i < metadata_size; i++)
skip_bits(&s->gb, 8);
}
}
} while (!metadata_last); } while (!metadata_last);
return 0; return buf_size - (buf_end - buf);
} }
static int decode_residuals(FLACContext *s, int channel, int pred_order) static int decode_residuals(FLACContext *s, int channel, int pred_order)
@ -637,28 +649,29 @@ static int flac_decode_frame(AVCodecContext *avctx,
} }
} }
init_get_bits(&s->gb, buf, buf_size*8);
/* check that there is at least the smallest decodable amount of data. /* check that there is at least the smallest decodable amount of data.
this amount corresponds to the smallest valid FLAC frame possible. */ this amount corresponds to the smallest valid FLAC frame possible. */
if (buf_size < 24) if (buf_size < 24)
goto end; goto end;
/* check for inline header */ /* check for inline header */
if (show_bits_long(&s->gb, 32) == MKBETAG('f','L','a','C')) { if (AV_RB32(buf) == MKBETAG('f','L','a','C')) {
if (metadata_parse(s)) { if (!s->got_streaminfo && parse_streaminfo(s, buf, buf_size)) {
av_log(s->avctx, AV_LOG_ERROR, "invalid header\n"); av_log(s->avctx, AV_LOG_ERROR, "invalid header\n");
return -1; return -1;
} }
bytes_read = get_metadata_size(buf, buf_size);
goto end; goto end;
} }
init_get_bits(&s->gb, buf, buf_size*8);
tmp = show_bits(&s->gb, 16); tmp = show_bits(&s->gb, 16);
if ((tmp & 0xFFFE) != 0xFFF8) { if ((tmp & 0xFFFE) != 0xFFF8) {
av_log(s->avctx, AV_LOG_ERROR, "FRAME HEADER not here\n"); av_log(s->avctx, AV_LOG_ERROR, "FRAME HEADER not here\n");
while (get_bits_count(&s->gb)/8+2 < buf_size && (show_bits(&s->gb, 16) & 0xFFFE) != 0xFFF8) while (get_bits_count(&s->gb)/8+2 < buf_size && (show_bits(&s->gb, 16) & 0xFFFE) != 0xFFF8)
skip_bits(&s->gb, 8); skip_bits(&s->gb, 8);
goto end; // we may not have enough bits left to decode a frame, so try next time goto hdr_end; // we may not have enough bits left to decode a frame, so try next time
} }
skip_bits(&s->gb, 16); skip_bits(&s->gb, 16);
if (decode_frame(s, alloc_data_size) < 0) { if (decode_frame(s, alloc_data_size) < 0) {
@ -704,8 +717,9 @@ static int flac_decode_frame(AVCodecContext *avctx,
*data_size = s->blocksize * s->channels * (s->is32 ? 4 : 2); *data_size = s->blocksize * s->channels * (s->is32 ? 4 : 2);
end: hdr_end:
bytes_read = (get_bits_count(&s->gb)+7)/8; bytes_read = (get_bits_count(&s->gb)+7)/8;
end:
if (bytes_read > buf_size) { if (bytes_read > buf_size) {
av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size); av_log(s->avctx, AV_LOG_ERROR, "overread: %d\n", bytes_read - buf_size);
s->bitstream_size=0; s->bitstream_size=0;

Loading…
Cancel
Save