1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-26 19:01:44 +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:
Michael Chinen 2013-06-28 14:16:39 +09:00 committed by Michael Niedermayer
parent 804c7b2c62
commit fc736a99ea

View File

@ -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,
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,
@ -295,6 +296,18 @@ static int check_header_mismatch(FLACParseContext *fpc,
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
"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;