|
|
|
@ -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; |
|
|
|
|