X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fflac_parser.c;h=87f3f9504208cb24767e3a4e4b6cbb5ab4f46068;hb=1c45c64c9d4dd52441300f0e17641e40864b53af;hp=962b37e03eca7fed8dac6353f8bb73c7d69f0eda;hpb=97f7fe687ae40f677aa48dc3be96e4842471f38e;p=ffmpeg diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c index 962b37e03ec..87f3f950420 100644 --- a/libavcodec/flac_parser.c +++ b/libavcodec/flac_parser.c @@ -2,20 +2,20 @@ * FLAC parser * Copyright (c) 2010 Michael Chinen * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -42,6 +42,8 @@ #define FLAC_MAX_SEQUENTIAL_HEADERS 3 /** minimum number of headers buffered and checked before returning frames */ #define FLAC_MIN_HEADERS 10 +/** estimate for average size of a FLAC frame */ +#define FLAC_AVG_FRAME_SIZE 8192 /** scoring settings for score_header */ #define FLAC_HEADER_BASE_SCORE 10 @@ -476,6 +478,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, FLACParseContext *fpc = s->priv_data; FLACHeaderMarker *curr; int nb_headers; + const uint8_t *read_end = buf; + const uint8_t *read_start = buf; if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { FLACFrameInfo fi; @@ -537,26 +541,36 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, } /* Find and score new headers. */ - if (buf_size || !fpc->end_padded) { + while ((buf && read_end < buf + buf_size && + fpc->nb_headers_buffered < FLAC_MIN_HEADERS) + || (!buf && !fpc->end_padded)) { int start_offset; /* Pad the end once if EOF, to check the final region for headers. */ - if (!buf_size) { - fpc->end_padded = 1; - buf_size = MAX_FRAME_HEADER_SIZE; + if (!buf) { + fpc->end_padded = 1; + buf_size = MAX_FRAME_HEADER_SIZE; + read_end = read_start + MAX_FRAME_HEADER_SIZE; + } else { + /* The maximum read size is the upper-bound of what the parser + needs to have the required number of frames buffered */ + int nb_desired = FLAC_MIN_HEADERS - fpc->nb_headers_buffered + 1; + read_end = read_end + FFMIN(buf + buf_size - read_end, + nb_desired * FLAC_AVG_FRAME_SIZE); } /* Fill the buffer. */ if (av_fifo_realloc2(fpc->fifo_buf, - buf_size + av_fifo_size(fpc->fifo_buf)) < 0) { + (read_end - read_start) + av_fifo_size(fpc->fifo_buf)) < 0) { av_log(avctx, AV_LOG_ERROR, - "couldn't reallocate buffer of size %d\n", - buf_size + av_fifo_size(fpc->fifo_buf)); + "couldn't reallocate buffer of size %td\n", + (read_end - read_start) + av_fifo_size(fpc->fifo_buf)); goto handle_error; } if (buf) { - av_fifo_generic_write(fpc->fifo_buf, (void*) buf, buf_size, NULL); + 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)); @@ -565,7 +579,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, /* Tag headers and update sequences. */ start_offset = av_fifo_size(fpc->fifo_buf) - - (buf_size + (MAX_FRAME_HEADER_SIZE - 1)); + ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1)); start_offset = FFMAX(0, start_offset); nb_headers = find_new_headers(fpc, start_offset); @@ -577,8 +591,14 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, fpc->nb_headers_buffered = nb_headers; /* Wait till FLAC_MIN_HEADERS to output a valid frame. */ - if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) - goto handle_error; + if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) { + if (buf && read_end < buf + buf_size) { + read_start = read_end; + continue; + } else { + goto handle_error; + } + } /* If headers found, update the scores since we have longer chains. */ if (fpc->end_padded || fpc->nb_headers_found) @@ -594,6 +614,7 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, fpc->fifo_buf->buffer; } buf_size = 0; + read_start = read_end = NULL; } } @@ -615,8 +636,8 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); - return buf_size ? buf_size : (fpc->best_header->offset - - av_fifo_size(fpc->fifo_buf)); + return buf_size ? (read_end - buf) : (fpc->best_header->offset - + av_fifo_size(fpc->fifo_buf)); } if (!buf_size) return get_best_header(fpc, poutbuf, poutbuf_size); @@ -625,16 +646,15 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, handle_error: *poutbuf = NULL; *poutbuf_size = 0; - return buf_size; + return read_end - buf; } static int flac_parse_init(AVCodecParserContext *c) { FLACParseContext *fpc = c->priv_data; /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before - it drains. 8192 is an approximate average size of a flac frame */ - fpc->fifo_buf = av_fifo_alloc(8192 * FLAC_MIN_HEADERS); - + it drains. This is allocated early to avoid slow reallocation. */ + fpc->fifo_buf = av_fifo_alloc(FLAC_AVG_FRAME_SIZE * (FLAC_MIN_HEADERS + 3)); return 0; } @@ -653,10 +673,10 @@ static void flac_parse_close(AVCodecParserContext *c) av_free(fpc->wrap_buf); } -AVCodecParser flac_parser = { - { CODEC_ID_FLAC }, - sizeof(FLACParseContext), - flac_parse_init, - flac_parse, - flac_parse_close, +AVCodecParser ff_flac_parser = { + .codec_ids = { CODEC_ID_FLAC }, + .priv_data_size = sizeof(FLACParseContext), + .parser_init = flac_parse_init, + .parser_parse = flac_parse, + .parser_close = flac_parse_close, };