[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