[FFmpeg-devel] [PATCH] flac_parser.c: fix case when final frame is a false positive
Paul B Mahol
onemda at gmail.com
Fri Jun 28 13:31:26 CEST 2013
On 6/28/13, Michael Chinen <mchinen at gmail.com> wrote:
> Should fix https://ffmpeg.org/trac/ffmpeg/ticket/2552
> Only did minimal testing on a few files and fate.
>
> From e2ba4117fa728c7d86a60c5032339795bf24c170 Mon Sep 17 00:00:00 2001
> From: Michael Chinen <m at roughsoft.com>
> Date: Thu, 27 Jun 2013 18:49:11 -1000
> Subject: [PATCH] flac_parser.c: fix case when final frame is a false positive
Could you explain what is fixed and why?
I found it "odd" that this bug appeared once some internal changes to
lavf was done.
Otherwise it should be probably ok.
>
> ---
> libavcodec/flac_parser.c | 54 +++++++++++++++++++++++++++++++++++-------------
> 1 file changed, 40 insertions(+), 14 deletions(-)
>
> diff --git a/libavcodec/flac_parser.c b/libavcodec/flac_parser.c
> index 2996398..ded7bde 100644
> --- a/libavcodec/flac_parser.c
> +++ b/libavcodec/flac_parser.c
> @@ -87,6 +87,8 @@ typedef struct FLACParseContext {
> int end_padded; /**< specifies if fifo_buf's end is padded */
> uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */
> int wrap_buf_allocated_size; /**< actual allocated size of the buffer */
> + FLACFrameInfo last_fi; /**< last decoded frame header info */
> + int last_fi_valid; /**< set if last_fi is valid */
> } FLACParseContext;
>
> static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf,
> @@ -267,13 +269,12 @@ static int find_new_headers(FLACParseContext *fpc, int search_start)
> return size;
> }
>
> -static int check_header_mismatch(FLACParseContext *fpc,
> - FLACHeaderMarker *header,
> - FLACHeaderMarker *child,
> - int log_level_offset)
> +static int check_header_fi_mismatch(FLACParseContext *fpc,
> + FLACFrameInfo *header_fi,
> + FLACFrameInfo *child_fi,
> + int log_level_offset)
> {
> - FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi;
> - int deduction = 0, deduction_expected = 0, i;
> + int deduction = 0;
> if (child_fi->samplerate != header_fi->samplerate) {
> deduction += FLAC_HEADER_CHANGED_PENALTY;
> av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
> @@ -288,13 +289,25 @@ static int check_header_mismatch(FLACParseContext *fpc,
> /* Changing blocking strategy not allowed per the spec */
> deduction += FLAC_HEADER_BASE_SCORE;
> av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
> - "blocking strategy change detected in adjacent frames\n");
> + "blocking strategy change detected in adjacent frames\n");
> }
> if (child_fi->channels != header_fi->channels) {
> deduction += FLAC_HEADER_CHANGED_PENALTY;
> av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
> - "number of channels change detected in adjacent frames\n");
> + "number of channels change detected in adjacent frames\n");
> }
> + return deduction;
> +}
> +
> +static int check_header_mismatch(FLACParseContext *fpc,
> + FLACHeaderMarker *header,
> + FLACHeaderMarker *child,
> + int log_level_offset)
> +{
> + FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi;
> + int deduction, deduction_expected = 0, i;
> + deduction = check_header_fi_mismatch(fpc, header_fi, child_fi,
> + log_level_offset);
> /* Check sample and frame numbers. */
> if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num
> != header_fi->blocksize) &&
> @@ -399,11 +412,18 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
> FLACHeaderMarker *child;
> int dist = 0;
> int child_score;
> -
> + int base_score = FLAC_HEADER_BASE_SCORE;
> if (header->max_score != FLAC_HEADER_NOT_SCORED_YET)
> return header->max_score;
>
> - header->max_score = FLAC_HEADER_BASE_SCORE;
> + /* Modify the base score with changes from the last output header */
> + if (fpc->last_fi_valid) {
> + /* Silence the log since this will be repeated if selected */
> + base_score -= check_header_fi_mismatch(fpc, &fpc->last_fi, &header->fi,
> + AV_LOG_DEBUG);
> + }
> +
> + header->max_score = base_score;
>
> /* Check and compute the children's scores. */
> child = header->next;
> @@ -419,7 +439,7 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
> if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) {
> /* Keep the child because the frame scoring is dynamic. */
> header->best_child = child;
> - header->max_score = FLAC_HEADER_BASE_SCORE + child_score;
> + header->max_score = base_score + child_score;
> }
> child = child->next;
> }
> @@ -430,7 +450,7 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
> static void score_sequences(FLACParseContext *fpc)
> {
> FLACHeaderMarker *curr;
> - int best_score = FLAC_HEADER_NOT_SCORED_YET;
> + int best_score = 0;//FLAC_HEADER_NOT_SCORED_YET;
> /* First pass to clear all old scores. */
> for (curr = fpc->headers; curr; curr = curr->next)
> curr->max_score = FLAC_HEADER_NOT_SCORED_YET;
> @@ -470,6 +490,9 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf,
> &fpc->wrap_buf_allocated_size);
>
> fpc->best_header_valid = 0;
> + fpc->last_fi_valid = 1;
> + fpc->last_fi = header->fi;
> +
> /* Return the negative overread index so the client can compute pos.
> This should be the amount overread to the beginning of the child */
> if (child)
> @@ -629,9 +652,12 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
> }
>
> curr = fpc->headers;
> - for (curr = fpc->headers; curr; curr = curr->next)
> - if (!fpc->best_header || curr->max_score > fpc->best_header->max_score)
> + for (curr = fpc->headers; curr; curr = curr->next) {
> + if (curr->max_score > 0 &&
> + (!fpc->best_header || curr->max_score > fpc->best_header->max_score)) {
> fpc->best_header = curr;
> + }
> + }
>
> if (fpc->best_header) {
> fpc->best_header_valid = 1;
> --
> 1.8.2.3
>
More information about the ffmpeg-devel
mailing list