mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-12-18 04:50:11 +01: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:
committed by
Michael Niedermayer
parent
804c7b2c62
commit
fc736a99ea
@@ -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)
|
|||||||
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,
|
||||||
@@ -288,13 +289,25 @@ static int check_header_mismatch(FLACParseContext *fpc,
|
|||||||
/* Changing blocking strategy not allowed per the spec */
|
/* Changing blocking strategy not allowed per the spec */
|
||||||
deduction += FLAC_HEADER_BASE_SCORE;
|
deduction += FLAC_HEADER_BASE_SCORE;
|
||||||
av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset,
|
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) {
|
if (child_fi->channels != header_fi->channels) {
|
||||||
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,
|
||||||
"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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
&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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
|||||||
Reference in New Issue
Block a user