/** * Score a header. * * Give FLAC_HEADER_BASE_SCORE points to a frame for existing. * If it has children, (subsequent frames of which the preceding CRC footer * validates against this one,) then take the maximum score of the children, * with a penalty of FLAC_HEADER_CHANGED_PENALTY applied for each change to * bps, sample rate, channels, but not decorrelation mode, or blocksize, * because it can change often. **/ static int score_header(FLACParseContext *fpc, FLACHeaderMarker *header) { FLACHeaderMarker *child; int dist = 0; int child_score; if (header->max_score != FLAC_HEADER_NOT_SCORED_YET) return header->max_score; header->max_score = FLAC_HEADER_BASE_SCORE; /* Check and compute the children's scores. */ child = header->next; for (dist = 0; dist < FLAC_MAX_SEQUENTIAL_HEADERS && child; dist++) { /* Look at the child's frame header info and penalize suspicious changes between the headers. */ if (header->link_penalty[dist] == FLAC_HEADER_NOT_PENALIZED_YET) { header->link_penalty[dist] = check_header_mismatch(fpc, header, child, AV_LOG_DEBUG); } child_score = score_header(fpc, child) - header->link_penalty[dist]; 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; } child = child->next; } return header->max_score; }
static int get_best_header(FLACParseContext* fpc, const uint8_t **poutbuf, int *poutbuf_size) { FLACHeaderMarker *header = fpc->best_header; FLACHeaderMarker *child = header->best_child; if (!child) { *poutbuf_size = av_fifo_size(fpc->fifo_buf) - header->offset; } else { *poutbuf_size = child->offset - header->offset; /* If the child has suspicious changes, log them */ check_header_mismatch(fpc, header, child, 0); } if (header->fi.channels != fpc->avctx->channels || !fpc->avctx->channel_layout) { fpc->avctx->channels = header->fi.channels; ff_flac_set_channel_layout(fpc->avctx); } fpc->avctx->sample_rate = header->fi.samplerate; fpc->pc->duration = header->fi.blocksize; *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size, &fpc->wrap_buf, &fpc->wrap_buf_allocated_size); fpc->best_header_valid = 0; /* 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) return child->offset - av_fifo_size(fpc->fifo_buf); return 0; }
/** * Score a header. * * Give FLAC_HEADER_BASE_SCORE points to a frame for existing. * If it has children, (subsequent frames of which the preceding CRC footer * validates against this one,) then take the maximum score of the children, * with a penalty of FLAC_HEADER_CHANGED_PENALTY applied for each change to * bps, sample rate, channels, but not decorrelation mode, or blocksize, * because it can change often. **/ 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; /* 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; for (dist = 0; dist < FLAC_MAX_SEQUENTIAL_HEADERS && child; dist++) { /* Look at the child's frame header info and penalize suspicious changes between the headers. */ if (header->link_penalty[dist] == FLAC_HEADER_NOT_PENALIZED_YET) { header->link_penalty[dist] = check_header_mismatch(fpc, header, child, AV_LOG_DEBUG); } child_score = score_header(fpc, child) - header->link_penalty[dist]; 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 = base_score + child_score; } child = child->next; } return header->max_score; }