Commit fc736a99 authored by Michael Chinen's avatar Michael Chinen Committed by Michael Niedermayer

flac_parser.c: fix case when final frame is a false positive

Should fix https://ffmpeg.org/trac/ffmpeg/ticket/2552
Only did minimal testing on a few files and fate.
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 804c7b2c
...@@ -87,6 +87,8 @@ typedef struct FLACParseContext { ...@@ -87,6 +87,8 @@ typedef struct FLACParseContext {
int end_padded; /**< specifies if fifo_buf's end is padded */ int end_padded; /**< specifies if fifo_buf's end is padded */
uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */ uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */
int wrap_buf_allocated_size; /**< actual allocated size of the buffer */ 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; } FLACParseContext;
static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, 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) ...@@ -267,13 +269,12 @@ static int find_new_headers(FLACParseContext *fpc, int search_start)
return size; return size;
} }
static int check_header_mismatch(FLACParseContext *fpc, static int check_header_fi_mismatch(FLACParseContext *fpc,
FLACHeaderMarker *header, FLACFrameInfo *header_fi,
FLACHeaderMarker *child, FLACFrameInfo *child_fi,
int log_level_offset) int log_level_offset)
{ {
FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi; int deduction = 0;
int deduction = 0, deduction_expected = 0, i;
if (child_fi->samplerate != header_fi->samplerate) { if (child_fi->samplerate != header_fi->samplerate) {
deduction += FLAC_HEADER_CHANGED_PENALTY; deduction += FLAC_HEADER_CHANGED_PENALTY;
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
...@@ -295,6 +296,18 @@ static int check_header_mismatch(FLACParseContext *fpc, ...@@ -295,6 +296,18 @@ static int check_header_mismatch(FLACParseContext *fpc,
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 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. */ /* Check sample and frame numbers. */
if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num
!= header_fi->blocksize) && != header_fi->blocksize) &&
...@@ -399,11 +412,18 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header) ...@@ -399,11 +412,18 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
FLACHeaderMarker *child; FLACHeaderMarker *child;
int dist = 0; int dist = 0;
int child_score; int child_score;
int base_score = FLAC_HEADER_BASE_SCORE;
if (header->max_score != FLAC_HEADER_NOT_SCORED_YET) if (header->max_score != FLAC_HEADER_NOT_SCORED_YET)
return header->max_score; 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. */ /* Check and compute the children's scores. */
child = header->next; child = header->next;
...@@ -419,7 +439,7 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header) ...@@ -419,7 +439,7 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) { if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) {
/* Keep the child because the frame scoring is dynamic. */ /* Keep the child because the frame scoring is dynamic. */
header->best_child = child; header->best_child = child;
header->max_score = FLAC_HEADER_BASE_SCORE + child_score; header->max_score = base_score + child_score;
} }
child = child->next; child = child->next;
} }
...@@ -430,7 +450,7 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header) ...@@ -430,7 +450,7 @@ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header)
static void score_sequences(FLACParseContext *fpc) static void score_sequences(FLACParseContext *fpc)
{ {
FLACHeaderMarker *curr; 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. */ /* First pass to clear all old scores. */
for (curr = fpc->headers; curr; curr = curr->next) for (curr = fpc->headers; curr; curr = curr->next)
curr->max_score = FLAC_HEADER_NOT_SCORED_YET; curr->max_score = FLAC_HEADER_NOT_SCORED_YET;
...@@ -470,6 +490,9 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf, ...@@ -470,6 +490,9 @@ static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf,
&fpc->wrap_buf_allocated_size); &fpc->wrap_buf_allocated_size);
fpc->best_header_valid = 0; 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. /* Return the negative overread index so the client can compute pos.
This should be the amount overread to the beginning of the child */ This should be the amount overread to the beginning of the child */
if (child) if (child)
...@@ -629,9 +652,12 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, ...@@ -629,9 +652,12 @@ static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx,
} }
curr = fpc->headers; curr = fpc->headers;
for (curr = fpc->headers; curr; curr = curr->next) for (curr = fpc->headers; curr; curr = curr->next) {
if (!fpc->best_header || curr->max_score > fpc->best_header->max_score) if (curr->max_score > 0 &&
(!fpc->best_header || curr->max_score > fpc->best_header->max_score)) {
fpc->best_header = curr; fpc->best_header = curr;
}
}
if (fpc->best_header) { if (fpc->best_header) {
fpc->best_header_valid = 1; fpc->best_header_valid = 1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment