/* * FLAC parser * Copyright (c) 2010 Michael Chinen * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * FLAC parser * * The FLAC parser buffers input until FLAC_MIN_HEADERS has been found. * Each time it finds and verifies a CRC-8 header it sees which of the * FLAC_MAX_SEQUENTIAL_HEADERS that came before it have a valid CRC-16 footer * that ends at the newly found header. * Headers are scored by FLAC_HEADER_BASE_SCORE plus the max of its crc-verified * children, penalized by changes in sample rate, frame number, etc. * The parser returns the frame with the highest score. **/ #include "libavutil/attributes.h" #include "libavutil/crc.h" #include "libavutil/mem.h" #include "flac_parse.h" /** maximum number of adjacent headers that compare CRCs against each other */ #define FLAC_MAX_SEQUENTIAL_HEADERS … /** minimum number of headers buffered and checked before returning frames */ #define FLAC_MIN_HEADERS … /** estimate for average size of a FLAC frame */ #define FLAC_AVG_FRAME_SIZE … /** scoring settings for score_header */ #define FLAC_HEADER_BASE_SCORE … #define FLAC_HEADER_CHANGED_PENALTY … #define FLAC_HEADER_CRC_FAIL_PENALTY … #define FLAC_HEADER_NOT_PENALIZED_YET … #define FLAC_HEADER_NOT_SCORED_YET … /** largest possible size of flac header */ #define MAX_FRAME_HEADER_SIZE … #define MAX_FRAME_VERIFY_SIZE … FifoBuffer; FLACHeaderMarker; FLACParseContext; static int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, FLACFrameInfo *fi) { … } static size_t flac_fifo_size(const FifoBuffer *f) { … } static size_t flac_fifo_space(const FifoBuffer *f) { … } /** * Non-destructive fast fifo pointer fetching * Returns a pointer from the specified offset. * If possible the pointer points within the fifo buffer. * Otherwise (if it would cause a wrap around,) a pointer to a user-specified * buffer is used. * The pointer can be NULL. In any case it will be reallocated to hold the size. * If the returned pointer will be used after subsequent calls to flac_fifo_read_wrap * then the subsequent calls should pass in a different wrap_buf so as to not * overwrite the contents of the previous wrap_buf. * This function is based on av_fifo_generic_read, which is why there is a comment * about a memory barrier for SMP. */ static uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, uint8_t **wrap_buf, int *allocated_size) { … } /** * Return a pointer in the fifo buffer where the offset starts at until * the wrap point or end of request. * len will contain the valid length of the returned buffer. * A second call to flac_fifo_read (with new offset and len) should be called * to get the post-wrap buf if the returned len is less than the requested. **/ static uint8_t *flac_fifo_read(FifoBuffer *f, int offset, int *len) { … } static int flac_fifo_grow(FifoBuffer *f, size_t inc) { … } static int flac_fifo_write(FifoBuffer *f, const uint8_t *src, size_t size) { … } static void flac_fifo_drain(FifoBuffer *f, size_t size) { … } static int flac_fifo_alloc(FifoBuffer *f, size_t size) { … } static void flac_fifo_free(FifoBuffer *f) { … } static int find_headers_search_validate(FLACParseContext *fpc, int offset) { … } static int find_headers_search(FLACParseContext *fpc, uint8_t *buf, int buf_size, int search_start) { … } static int find_new_headers(FLACParseContext *fpc, int search_start) { … } static int check_header_fi_mismatch(FLACParseContext *fpc, FLACFrameInfo *header_fi, FLACFrameInfo *child_fi, int log_level_offset) { … } static int check_header_mismatch(FLACParseContext *fpc, FLACHeaderMarker *header, FLACHeaderMarker *child, int log_level_offset) { … } /** * 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) { … } static void score_sequences(FLACParseContext *fpc) { … } static int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, int *poutbuf_size) { … } static int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, const uint8_t **poutbuf, int *poutbuf_size, const uint8_t *buf, int buf_size) { … } static av_cold int flac_parse_init(AVCodecParserContext *c) { … } static void flac_parse_close(AVCodecParserContext *c) { … } const AVCodecParser ff_flac_parser = …;