* Each time it finds and verifies a CRC-8 header it sees which of the
* FLAC_MAX_SEQUENTIAL_HEADERS that came before it have a valid CRC-16 footer
* that ends at the newly found header.
- * Headers are scored by FLAC_HEADER_BASE_SCORE plus the max of it's crc-verified
+ * Headers are scored by FLAC_HEADER_BASE_SCORE plus the max of its crc-verified
* children, penalized by changes in sample rate, frame number, etc.
* The parser returns the frame with the highest score.
**/
+#include "libavutil/attributes.h"
#include "libavutil/crc.h"
#include "libavutil/fifo.h"
#include "bytestream.h"
} FLACHeaderMarker;
typedef struct FLACParseContext {
+ AVCodecParserContext *pc; /**< parent context */
AVCodecContext *avctx; /**< codec context pointer for logging */
FLACHeaderMarker *headers; /**< linked-list that starts at the first
CRC-8 verified header within buffer */
static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
FLACFrameInfo *fi)
{
- GetBitContext gb;
- init_get_bits(&gb, buf, MAX_FRAME_HEADER_SIZE * 8);
- return !ff_flac_decode_frame_header(avctx, &gb, fi, 127);
+ BitstreamContext bc;
+ bitstream_init8(&bc, buf, MAX_FRAME_HEADER_SIZE);
+ return !ff_flac_decode_frame_header(avctx, &bc, fi, 127);
}
/**
check_header_mismatch(fpc, header, child, 0);
}
+ if (header->fi.channels != fpc->avctx->channels ||
+ !fpc->avctx->channel_layout) {
+ fpc->avctx->channels = header->fi.channels;
+ ff_flac_set_channel_layout(fpc->avctx);
+ }
fpc->avctx->sample_rate = header->fi.samplerate;
- fpc->avctx->channels = header->fi.channels;
- fpc->avctx->frame_size = header->fi.blocksize;
+ fpc->pc->duration = header->fi.blocksize;
*poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size,
&fpc->wrap_buf,
&fpc->wrap_buf_allocated_size);
if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) {
FLACFrameInfo fi;
if (frame_header_is_valid(avctx, buf, &fi))
- avctx->frame_size = fi.blocksize;
+ s->duration = fi.blocksize;
*poutbuf = buf;
*poutbuf_size = buf_size;
return buf_size;
nb_desired * FLAC_AVG_FRAME_SIZE);
}
+ if (!av_fifo_space(fpc->fifo_buf) &&
+ av_fifo_size(fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE >
+ fpc->nb_headers_buffered * 10) {
+ /* There is less than one valid flac header buffered for 10 headers
+ * buffered. Therefore the fifo is most likely filled with invalid
+ * data and the input is not a flac file. */
+ goto handle_error;
+ }
+
/* Fill the buffer. */
if (av_fifo_realloc2(fpc->fifo_buf,
(read_end - read_start) + av_fifo_size(fpc->fifo_buf)) < 0) {
av_fifo_generic_write(fpc->fifo_buf, (void*) read_start,
read_end - read_start, NULL);
} else {
- int8_t pad[MAX_FRAME_HEADER_SIZE];
- memset(pad, 0, sizeof(pad));
- av_fifo_generic_write(fpc->fifo_buf, (void*) pad, sizeof(pad), NULL);
+ int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 };
+ av_fifo_generic_write(fpc->fifo_buf, pad, sizeof(pad), NULL);
}
/* Tag headers and update sequences. */
av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n",
fpc->best_header->offset);
- /* Set frame_size to 0. It is unknown or invalid in a junk frame. */
- avctx->frame_size = 0;
+ /* Set duration to 0. It is unknown or invalid in a junk frame. */
+ s->duration = 0;
*poutbuf_size = fpc->best_header->offset;
*poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size,
&fpc->wrap_buf,
return read_end - buf;
}
-static int flac_parse_init(AVCodecParserContext *c)
+static av_cold int flac_parse_init(AVCodecParserContext *c)
{
FLACParseContext *fpc = c->priv_data;
+ fpc->pc = c;
/* There will generally be FLAC_MIN_HEADERS buffered in the fifo before
it drains. This is allocated early to avoid slow reallocation. */
fpc->fifo_buf = av_fifo_alloc(FLAC_AVG_FRAME_SIZE * (FLAC_MIN_HEADERS + 3));
}
AVCodecParser ff_flac_parser = {
- { CODEC_ID_FLAC },
- sizeof(FLACParseContext),
- flac_parse_init,
- flac_parse,
- flac_parse_close,
+ .codec_ids = { AV_CODEC_ID_FLAC },
+ .priv_data_size = sizeof(FLACParseContext),
+ .parser_init = flac_parse_init,
+ .parser_parse = flac_parse,
+ .parser_close = flac_parse_close,
};