mirror of
https://git.videolan.org/git/ffmpeg.git
synced 2024-09-10 09:31:06 +02:00
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: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
804c7b2c62
commit
fc736a99ea
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user