1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * FLAC parser 3cabdff1aSopenharmony_ci * Copyright (c) 2010 Michael Chinen 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * FLAC parser 25cabdff1aSopenharmony_ci * 26cabdff1aSopenharmony_ci * The FLAC parser buffers input until FLAC_MIN_HEADERS has been found. 27cabdff1aSopenharmony_ci * Each time it finds and verifies a CRC-8 header it sees which of the 28cabdff1aSopenharmony_ci * FLAC_MAX_SEQUENTIAL_HEADERS that came before it have a valid CRC-16 footer 29cabdff1aSopenharmony_ci * that ends at the newly found header. 30cabdff1aSopenharmony_ci * Headers are scored by FLAC_HEADER_BASE_SCORE plus the max of its crc-verified 31cabdff1aSopenharmony_ci * children, penalized by changes in sample rate, frame number, etc. 32cabdff1aSopenharmony_ci * The parser returns the frame with the highest score. 33cabdff1aSopenharmony_ci **/ 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci#include "libavutil/attributes.h" 36cabdff1aSopenharmony_ci#include "libavutil/crc.h" 37cabdff1aSopenharmony_ci#include "bytestream.h" 38cabdff1aSopenharmony_ci#include "parser.h" 39cabdff1aSopenharmony_ci#include "flac.h" 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci/** maximum number of adjacent headers that compare CRCs against each other */ 42cabdff1aSopenharmony_ci#define FLAC_MAX_SEQUENTIAL_HEADERS 4 43cabdff1aSopenharmony_ci/** minimum number of headers buffered and checked before returning frames */ 44cabdff1aSopenharmony_ci#define FLAC_MIN_HEADERS 10 45cabdff1aSopenharmony_ci/** estimate for average size of a FLAC frame */ 46cabdff1aSopenharmony_ci#define FLAC_AVG_FRAME_SIZE 8192 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci/** scoring settings for score_header */ 49cabdff1aSopenharmony_ci#define FLAC_HEADER_BASE_SCORE 10 50cabdff1aSopenharmony_ci#define FLAC_HEADER_CHANGED_PENALTY 7 51cabdff1aSopenharmony_ci#define FLAC_HEADER_CRC_FAIL_PENALTY 50 52cabdff1aSopenharmony_ci#define FLAC_HEADER_NOT_PENALIZED_YET 100000 53cabdff1aSopenharmony_ci#define FLAC_HEADER_NOT_SCORED_YET -100000 54cabdff1aSopenharmony_ci 55cabdff1aSopenharmony_ci/** largest possible size of flac header */ 56cabdff1aSopenharmony_ci#define MAX_FRAME_HEADER_SIZE 16 57cabdff1aSopenharmony_ci#define MAX_FRAME_VERIFY_SIZE (MAX_FRAME_HEADER_SIZE + 1) 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_citypedef struct FifoBuffer { 60cabdff1aSopenharmony_ci uint8_t *buffer; 61cabdff1aSopenharmony_ci uint8_t *end; 62cabdff1aSopenharmony_ci uint8_t *rptr; 63cabdff1aSopenharmony_ci uint8_t *wptr; 64cabdff1aSopenharmony_ci int empty; 65cabdff1aSopenharmony_ci} FifoBuffer; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_citypedef struct FLACHeaderMarker { 68cabdff1aSopenharmony_ci int offset; /**< byte offset from start of FLACParseContext->buffer */ 69cabdff1aSopenharmony_ci int link_penalty[FLAC_MAX_SEQUENTIAL_HEADERS]; /**< array of local scores 70cabdff1aSopenharmony_ci between this header and the one at a distance equal 71cabdff1aSopenharmony_ci array position */ 72cabdff1aSopenharmony_ci int max_score; /**< maximum score found after checking each child that 73cabdff1aSopenharmony_ci has a valid CRC */ 74cabdff1aSopenharmony_ci FLACFrameInfo fi; /**< decoded frame header info */ 75cabdff1aSopenharmony_ci struct FLACHeaderMarker *next; /**< next CRC-8 verified header that 76cabdff1aSopenharmony_ci immediately follows this one in 77cabdff1aSopenharmony_ci the bytestream */ 78cabdff1aSopenharmony_ci struct FLACHeaderMarker *best_child; /**< following frame header with 79cabdff1aSopenharmony_ci which this frame has the best 80cabdff1aSopenharmony_ci score with */ 81cabdff1aSopenharmony_ci} FLACHeaderMarker; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_citypedef struct FLACParseContext { 84cabdff1aSopenharmony_ci AVCodecParserContext *pc; /**< parent context */ 85cabdff1aSopenharmony_ci AVCodecContext *avctx; /**< codec context pointer for logging */ 86cabdff1aSopenharmony_ci FLACHeaderMarker *headers; /**< linked-list that starts at the first 87cabdff1aSopenharmony_ci CRC-8 verified header within buffer */ 88cabdff1aSopenharmony_ci FLACHeaderMarker *best_header; /**< highest scoring header within buffer */ 89cabdff1aSopenharmony_ci int nb_headers_found; /**< number of headers found in the last 90cabdff1aSopenharmony_ci flac_parse() call */ 91cabdff1aSopenharmony_ci int nb_headers_buffered; /**< number of headers that are buffered */ 92cabdff1aSopenharmony_ci int best_header_valid; /**< flag set when the parser returns junk; 93cabdff1aSopenharmony_ci if set return best_header next time */ 94cabdff1aSopenharmony_ci FifoBuffer fifo_buf; /**< buffer to store all data until headers 95cabdff1aSopenharmony_ci can be verified */ 96cabdff1aSopenharmony_ci int end_padded; /**< specifies if fifo_buf's end is padded */ 97cabdff1aSopenharmony_ci uint8_t *wrap_buf; /**< general fifo read buffer when wrapped */ 98cabdff1aSopenharmony_ci int wrap_buf_allocated_size; /**< actual allocated size of the buffer */ 99cabdff1aSopenharmony_ci FLACFrameInfo last_fi; /**< last decoded frame header info */ 100cabdff1aSopenharmony_ci int last_fi_valid; /**< set if last_fi is valid */ 101cabdff1aSopenharmony_ci} FLACParseContext; 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_cistatic int frame_header_is_valid(AVCodecContext *avctx, const uint8_t *buf, 104cabdff1aSopenharmony_ci FLACFrameInfo *fi) 105cabdff1aSopenharmony_ci{ 106cabdff1aSopenharmony_ci GetBitContext gb; 107cabdff1aSopenharmony_ci uint8_t subframe_type; 108cabdff1aSopenharmony_ci 109cabdff1aSopenharmony_ci // header plus one byte from first subframe 110cabdff1aSopenharmony_ci init_get_bits(&gb, buf, MAX_FRAME_VERIFY_SIZE * 8); 111cabdff1aSopenharmony_ci if (ff_flac_decode_frame_header(avctx, &gb, fi, 127)) { 112cabdff1aSopenharmony_ci return 0; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci // subframe zero bit 115cabdff1aSopenharmony_ci if (get_bits1(&gb) != 0) { 116cabdff1aSopenharmony_ci return 0; 117cabdff1aSopenharmony_ci } 118cabdff1aSopenharmony_ci // subframe type 119cabdff1aSopenharmony_ci // 000000 : SUBFRAME_CONSTANT 120cabdff1aSopenharmony_ci // 000001 : SUBFRAME_VERBATIM 121cabdff1aSopenharmony_ci // 00001x : reserved 122cabdff1aSopenharmony_ci // 0001xx : reserved 123cabdff1aSopenharmony_ci // 001xxx : if(xxx <= 4) SUBFRAME_FIXED, xxx=order ; else reserved 124cabdff1aSopenharmony_ci // 01xxxx : reserved 125cabdff1aSopenharmony_ci // 1xxxxx : SUBFRAME_LPC, xxxxx=order-1 126cabdff1aSopenharmony_ci subframe_type = get_bits(&gb, 6); 127cabdff1aSopenharmony_ci if (!(subframe_type == 0 || 128cabdff1aSopenharmony_ci subframe_type == 1 || 129cabdff1aSopenharmony_ci ((subframe_type >= 8) && (subframe_type <= 12)) || 130cabdff1aSopenharmony_ci (subframe_type >= 32))) { 131cabdff1aSopenharmony_ci return 0; 132cabdff1aSopenharmony_ci } 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci return 1; 135cabdff1aSopenharmony_ci} 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_cistatic size_t flac_fifo_size(const FifoBuffer *f) 138cabdff1aSopenharmony_ci{ 139cabdff1aSopenharmony_ci if (f->wptr <= f->rptr && !f->empty) 140cabdff1aSopenharmony_ci return (f->wptr - f->buffer) + (f->end - f->rptr); 141cabdff1aSopenharmony_ci return f->wptr - f->rptr; 142cabdff1aSopenharmony_ci} 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_cistatic size_t flac_fifo_space(const FifoBuffer *f) 145cabdff1aSopenharmony_ci{ 146cabdff1aSopenharmony_ci return f->end - f->buffer - flac_fifo_size(f); 147cabdff1aSopenharmony_ci} 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci/** 150cabdff1aSopenharmony_ci * Non-destructive fast fifo pointer fetching 151cabdff1aSopenharmony_ci * Returns a pointer from the specified offset. 152cabdff1aSopenharmony_ci * If possible the pointer points within the fifo buffer. 153cabdff1aSopenharmony_ci * Otherwise (if it would cause a wrap around,) a pointer to a user-specified 154cabdff1aSopenharmony_ci * buffer is used. 155cabdff1aSopenharmony_ci * The pointer can be NULL. In any case it will be reallocated to hold the size. 156cabdff1aSopenharmony_ci * If the returned pointer will be used after subsequent calls to flac_fifo_read_wrap 157cabdff1aSopenharmony_ci * then the subsequent calls should pass in a different wrap_buf so as to not 158cabdff1aSopenharmony_ci * overwrite the contents of the previous wrap_buf. 159cabdff1aSopenharmony_ci * This function is based on av_fifo_generic_read, which is why there is a comment 160cabdff1aSopenharmony_ci * about a memory barrier for SMP. 161cabdff1aSopenharmony_ci */ 162cabdff1aSopenharmony_cistatic uint8_t *flac_fifo_read_wrap(FLACParseContext *fpc, int offset, int len, 163cabdff1aSopenharmony_ci uint8_t **wrap_buf, int *allocated_size) 164cabdff1aSopenharmony_ci{ 165cabdff1aSopenharmony_ci FifoBuffer *f = &fpc->fifo_buf; 166cabdff1aSopenharmony_ci uint8_t *start = f->rptr + offset; 167cabdff1aSopenharmony_ci uint8_t *tmp_buf; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci if (start >= f->end) 170cabdff1aSopenharmony_ci start -= f->end - f->buffer; 171cabdff1aSopenharmony_ci if (f->end - start >= len) 172cabdff1aSopenharmony_ci return start; 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci tmp_buf = av_fast_realloc(*wrap_buf, allocated_size, len); 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci if (!tmp_buf) { 177cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_ERROR, 178cabdff1aSopenharmony_ci "couldn't reallocate wrap buffer of size %d", len); 179cabdff1aSopenharmony_ci return NULL; 180cabdff1aSopenharmony_ci } 181cabdff1aSopenharmony_ci *wrap_buf = tmp_buf; 182cabdff1aSopenharmony_ci do { 183cabdff1aSopenharmony_ci int seg_len = FFMIN(f->end - start, len); 184cabdff1aSopenharmony_ci memcpy(tmp_buf, start, seg_len); 185cabdff1aSopenharmony_ci tmp_buf = (uint8_t*)tmp_buf + seg_len; 186cabdff1aSopenharmony_ci// memory barrier needed for SMP here in theory 187cabdff1aSopenharmony_ci 188cabdff1aSopenharmony_ci start += seg_len - (f->end - f->buffer); 189cabdff1aSopenharmony_ci len -= seg_len; 190cabdff1aSopenharmony_ci } while (len > 0); 191cabdff1aSopenharmony_ci 192cabdff1aSopenharmony_ci return *wrap_buf; 193cabdff1aSopenharmony_ci} 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_ci/** 196cabdff1aSopenharmony_ci * Return a pointer in the fifo buffer where the offset starts at until 197cabdff1aSopenharmony_ci * the wrap point or end of request. 198cabdff1aSopenharmony_ci * len will contain the valid length of the returned buffer. 199cabdff1aSopenharmony_ci * A second call to flac_fifo_read (with new offset and len) should be called 200cabdff1aSopenharmony_ci * to get the post-wrap buf if the returned len is less than the requested. 201cabdff1aSopenharmony_ci **/ 202cabdff1aSopenharmony_cistatic uint8_t *flac_fifo_read(FifoBuffer *f, int offset, int *len) 203cabdff1aSopenharmony_ci{ 204cabdff1aSopenharmony_ci uint8_t *start = f->rptr + offset; 205cabdff1aSopenharmony_ci 206cabdff1aSopenharmony_ci if (start >= f->end) 207cabdff1aSopenharmony_ci start -= f->end - f->buffer; 208cabdff1aSopenharmony_ci *len = FFMIN(*len, f->end - start); 209cabdff1aSopenharmony_ci return start; 210cabdff1aSopenharmony_ci} 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_cistatic int flac_fifo_grow(FifoBuffer *f, size_t inc) 213cabdff1aSopenharmony_ci{ 214cabdff1aSopenharmony_ci size_t size_old = f->end - f->buffer; 215cabdff1aSopenharmony_ci size_t offset_r = f->rptr - f->buffer; 216cabdff1aSopenharmony_ci size_t offset_w = f->wptr - f->buffer; 217cabdff1aSopenharmony_ci size_t size_new; 218cabdff1aSopenharmony_ci 219cabdff1aSopenharmony_ci uint8_t *tmp; 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci if (size_old > SIZE_MAX - inc) 222cabdff1aSopenharmony_ci return AVERROR(EINVAL); 223cabdff1aSopenharmony_ci size_new = size_old + inc; 224cabdff1aSopenharmony_ci 225cabdff1aSopenharmony_ci tmp = av_realloc(f->buffer, size_new); 226cabdff1aSopenharmony_ci if (!tmp) 227cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 228cabdff1aSopenharmony_ci 229cabdff1aSopenharmony_ci // move the data from the beginning of the ring buffer 230cabdff1aSopenharmony_ci // to the newly allocated space 231cabdff1aSopenharmony_ci if (offset_w <= offset_r && !f->empty) { 232cabdff1aSopenharmony_ci const size_t copy = FFMIN(inc, offset_w); 233cabdff1aSopenharmony_ci memcpy(tmp + size_old, tmp, copy); 234cabdff1aSopenharmony_ci if (copy < offset_w) { 235cabdff1aSopenharmony_ci memmove(tmp, tmp + copy, offset_w - copy); 236cabdff1aSopenharmony_ci offset_w -= copy; 237cabdff1aSopenharmony_ci } else 238cabdff1aSopenharmony_ci offset_w = size_old + copy; 239cabdff1aSopenharmony_ci } 240cabdff1aSopenharmony_ci 241cabdff1aSopenharmony_ci f->buffer = tmp; 242cabdff1aSopenharmony_ci f->end = f->buffer + size_new; 243cabdff1aSopenharmony_ci f->rptr = f->buffer + offset_r; 244cabdff1aSopenharmony_ci f->wptr = f->buffer + offset_w; 245cabdff1aSopenharmony_ci 246cabdff1aSopenharmony_ci return 0; 247cabdff1aSopenharmony_ci} 248cabdff1aSopenharmony_ci 249cabdff1aSopenharmony_cistatic int flac_fifo_write(FifoBuffer *f, const uint8_t *src, size_t size) 250cabdff1aSopenharmony_ci{ 251cabdff1aSopenharmony_ci uint8_t *wptr; 252cabdff1aSopenharmony_ci 253cabdff1aSopenharmony_ci if (flac_fifo_space(f) < size) { 254cabdff1aSopenharmony_ci int ret = flac_fifo_grow(f, FFMAX(flac_fifo_size(f), size)); 255cabdff1aSopenharmony_ci if (ret < 0) 256cabdff1aSopenharmony_ci return ret; 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci 259cabdff1aSopenharmony_ci if (size) 260cabdff1aSopenharmony_ci f->empty = 0; 261cabdff1aSopenharmony_ci 262cabdff1aSopenharmony_ci wptr = f->wptr; 263cabdff1aSopenharmony_ci do { 264cabdff1aSopenharmony_ci size_t len = FFMIN(f->end - wptr, size); 265cabdff1aSopenharmony_ci memcpy(wptr, src, len); 266cabdff1aSopenharmony_ci src += len; 267cabdff1aSopenharmony_ci wptr += len; 268cabdff1aSopenharmony_ci if (wptr >= f->end) 269cabdff1aSopenharmony_ci wptr = f->buffer; 270cabdff1aSopenharmony_ci size -= len; 271cabdff1aSopenharmony_ci } while (size > 0); 272cabdff1aSopenharmony_ci 273cabdff1aSopenharmony_ci f->wptr = wptr; 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci return 0; 276cabdff1aSopenharmony_ci} 277cabdff1aSopenharmony_ci 278cabdff1aSopenharmony_cistatic void flac_fifo_drain(FifoBuffer *f, size_t size) 279cabdff1aSopenharmony_ci{ 280cabdff1aSopenharmony_ci size_t size_cur = flac_fifo_size(f); 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci av_assert0(size_cur >= size); 283cabdff1aSopenharmony_ci if (size_cur == size) 284cabdff1aSopenharmony_ci f->empty = 1; 285cabdff1aSopenharmony_ci 286cabdff1aSopenharmony_ci f->rptr += size; 287cabdff1aSopenharmony_ci if (f->rptr >= f->end) 288cabdff1aSopenharmony_ci f->rptr -= f->end - f->buffer; 289cabdff1aSopenharmony_ci} 290cabdff1aSopenharmony_ci 291cabdff1aSopenharmony_cistatic int flac_fifo_alloc(FifoBuffer *f, size_t size) 292cabdff1aSopenharmony_ci{ 293cabdff1aSopenharmony_ci memset(f, 0, sizeof(*f)); 294cabdff1aSopenharmony_ci 295cabdff1aSopenharmony_ci f->buffer = av_realloc(NULL, size); 296cabdff1aSopenharmony_ci if (!f->buffer) 297cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 298cabdff1aSopenharmony_ci 299cabdff1aSopenharmony_ci f->wptr = f->buffer; 300cabdff1aSopenharmony_ci f->rptr = f->buffer; 301cabdff1aSopenharmony_ci f->end = f->buffer + size; 302cabdff1aSopenharmony_ci 303cabdff1aSopenharmony_ci f->empty = 1; 304cabdff1aSopenharmony_ci 305cabdff1aSopenharmony_ci return 0; 306cabdff1aSopenharmony_ci} 307cabdff1aSopenharmony_ci 308cabdff1aSopenharmony_cistatic void flac_fifo_free(FifoBuffer *f) 309cabdff1aSopenharmony_ci{ 310cabdff1aSopenharmony_ci av_freep(&f->buffer); 311cabdff1aSopenharmony_ci memset(f, 0, sizeof(*f)); 312cabdff1aSopenharmony_ci} 313cabdff1aSopenharmony_ci 314cabdff1aSopenharmony_cistatic int find_headers_search_validate(FLACParseContext *fpc, int offset) 315cabdff1aSopenharmony_ci{ 316cabdff1aSopenharmony_ci FLACFrameInfo fi; 317cabdff1aSopenharmony_ci uint8_t *header_buf; 318cabdff1aSopenharmony_ci int size = 0; 319cabdff1aSopenharmony_ci header_buf = flac_fifo_read_wrap(fpc, offset, 320cabdff1aSopenharmony_ci MAX_FRAME_VERIFY_SIZE + AV_INPUT_BUFFER_PADDING_SIZE, 321cabdff1aSopenharmony_ci &fpc->wrap_buf, 322cabdff1aSopenharmony_ci &fpc->wrap_buf_allocated_size); 323cabdff1aSopenharmony_ci if (frame_header_is_valid(fpc->avctx, header_buf, &fi)) { 324cabdff1aSopenharmony_ci FLACHeaderMarker **end_handle = &fpc->headers; 325cabdff1aSopenharmony_ci int i; 326cabdff1aSopenharmony_ci 327cabdff1aSopenharmony_ci size = 0; 328cabdff1aSopenharmony_ci while (*end_handle) { 329cabdff1aSopenharmony_ci end_handle = &(*end_handle)->next; 330cabdff1aSopenharmony_ci size++; 331cabdff1aSopenharmony_ci } 332cabdff1aSopenharmony_ci 333cabdff1aSopenharmony_ci *end_handle = av_mallocz(sizeof(**end_handle)); 334cabdff1aSopenharmony_ci if (!*end_handle) { 335cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_ERROR, 336cabdff1aSopenharmony_ci "couldn't allocate FLACHeaderMarker\n"); 337cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 338cabdff1aSopenharmony_ci } 339cabdff1aSopenharmony_ci (*end_handle)->fi = fi; 340cabdff1aSopenharmony_ci (*end_handle)->offset = offset; 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_ci for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) 343cabdff1aSopenharmony_ci (*end_handle)->link_penalty[i] = FLAC_HEADER_NOT_PENALIZED_YET; 344cabdff1aSopenharmony_ci 345cabdff1aSopenharmony_ci fpc->nb_headers_found++; 346cabdff1aSopenharmony_ci size++; 347cabdff1aSopenharmony_ci } 348cabdff1aSopenharmony_ci return size; 349cabdff1aSopenharmony_ci} 350cabdff1aSopenharmony_ci 351cabdff1aSopenharmony_cistatic int find_headers_search(FLACParseContext *fpc, uint8_t *buf, 352cabdff1aSopenharmony_ci int buf_size, int search_start) 353cabdff1aSopenharmony_ci{ 354cabdff1aSopenharmony_ci int size = 0, mod_offset = (buf_size - 1) % 4, i, j; 355cabdff1aSopenharmony_ci uint32_t x; 356cabdff1aSopenharmony_ci 357cabdff1aSopenharmony_ci for (i = 0; i < mod_offset; i++) { 358cabdff1aSopenharmony_ci if ((AV_RB16(buf + i) & 0xFFFE) == 0xFFF8) { 359cabdff1aSopenharmony_ci int ret = find_headers_search_validate(fpc, search_start + i); 360cabdff1aSopenharmony_ci size = FFMAX(size, ret); 361cabdff1aSopenharmony_ci } 362cabdff1aSopenharmony_ci } 363cabdff1aSopenharmony_ci 364cabdff1aSopenharmony_ci for (; i < buf_size - 1; i += 4) { 365cabdff1aSopenharmony_ci x = AV_RN32(buf + i); 366cabdff1aSopenharmony_ci if (((x & ~(x + 0x01010101)) & 0x80808080)) { 367cabdff1aSopenharmony_ci for (j = 0; j < 4; j++) { 368cabdff1aSopenharmony_ci if ((AV_RB16(buf + i + j) & 0xFFFE) == 0xFFF8) { 369cabdff1aSopenharmony_ci int ret = find_headers_search_validate(fpc, search_start + i + j); 370cabdff1aSopenharmony_ci size = FFMAX(size, ret); 371cabdff1aSopenharmony_ci } 372cabdff1aSopenharmony_ci } 373cabdff1aSopenharmony_ci } 374cabdff1aSopenharmony_ci } 375cabdff1aSopenharmony_ci return size; 376cabdff1aSopenharmony_ci} 377cabdff1aSopenharmony_ci 378cabdff1aSopenharmony_cistatic int find_new_headers(FLACParseContext *fpc, int search_start) 379cabdff1aSopenharmony_ci{ 380cabdff1aSopenharmony_ci FLACHeaderMarker *end; 381cabdff1aSopenharmony_ci int search_end, size = 0, read_len, temp; 382cabdff1aSopenharmony_ci uint8_t *buf; 383cabdff1aSopenharmony_ci fpc->nb_headers_found = 0; 384cabdff1aSopenharmony_ci 385cabdff1aSopenharmony_ci /* Search for a new header of at most 16 bytes. */ 386cabdff1aSopenharmony_ci search_end = flac_fifo_size(&fpc->fifo_buf) - (MAX_FRAME_HEADER_SIZE - 1); 387cabdff1aSopenharmony_ci read_len = search_end - search_start + 1; 388cabdff1aSopenharmony_ci buf = flac_fifo_read(&fpc->fifo_buf, search_start, &read_len); 389cabdff1aSopenharmony_ci size = find_headers_search(fpc, buf, read_len, search_start); 390cabdff1aSopenharmony_ci search_start += read_len - 1; 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_ci /* If fifo end was hit do the wrap around. */ 393cabdff1aSopenharmony_ci if (search_start != search_end) { 394cabdff1aSopenharmony_ci uint8_t wrap[2]; 395cabdff1aSopenharmony_ci 396cabdff1aSopenharmony_ci wrap[0] = buf[read_len - 1]; 397cabdff1aSopenharmony_ci /* search_start + 1 is the post-wrap offset in the fifo. */ 398cabdff1aSopenharmony_ci read_len = search_end - (search_start + 1) + 1; 399cabdff1aSopenharmony_ci 400cabdff1aSopenharmony_ci buf = flac_fifo_read(&fpc->fifo_buf, search_start + 1, &read_len); 401cabdff1aSopenharmony_ci wrap[1] = buf[0]; 402cabdff1aSopenharmony_ci 403cabdff1aSopenharmony_ci if ((AV_RB16(wrap) & 0xFFFE) == 0xFFF8) { 404cabdff1aSopenharmony_ci temp = find_headers_search_validate(fpc, search_start); 405cabdff1aSopenharmony_ci size = FFMAX(size, temp); 406cabdff1aSopenharmony_ci } 407cabdff1aSopenharmony_ci search_start++; 408cabdff1aSopenharmony_ci 409cabdff1aSopenharmony_ci /* Continue to do the last half of the wrap. */ 410cabdff1aSopenharmony_ci temp = find_headers_search(fpc, buf, read_len, search_start); 411cabdff1aSopenharmony_ci size = FFMAX(size, temp); 412cabdff1aSopenharmony_ci search_start += read_len - 1; 413cabdff1aSopenharmony_ci } 414cabdff1aSopenharmony_ci 415cabdff1aSopenharmony_ci /* Return the size even if no new headers were found. */ 416cabdff1aSopenharmony_ci if (!size && fpc->headers) 417cabdff1aSopenharmony_ci for (end = fpc->headers; end; end = end->next) 418cabdff1aSopenharmony_ci size++; 419cabdff1aSopenharmony_ci return size; 420cabdff1aSopenharmony_ci} 421cabdff1aSopenharmony_ci 422cabdff1aSopenharmony_cistatic int check_header_fi_mismatch(FLACParseContext *fpc, 423cabdff1aSopenharmony_ci FLACFrameInfo *header_fi, 424cabdff1aSopenharmony_ci FLACFrameInfo *child_fi, 425cabdff1aSopenharmony_ci int log_level_offset) 426cabdff1aSopenharmony_ci{ 427cabdff1aSopenharmony_ci int deduction = 0; 428cabdff1aSopenharmony_ci if (child_fi->samplerate != header_fi->samplerate) { 429cabdff1aSopenharmony_ci deduction += FLAC_HEADER_CHANGED_PENALTY; 430cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 431cabdff1aSopenharmony_ci "sample rate change detected in adjacent frames\n"); 432cabdff1aSopenharmony_ci } 433cabdff1aSopenharmony_ci if (child_fi->bps != header_fi->bps) { 434cabdff1aSopenharmony_ci deduction += FLAC_HEADER_CHANGED_PENALTY; 435cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 436cabdff1aSopenharmony_ci "bits per sample change detected in adjacent frames\n"); 437cabdff1aSopenharmony_ci } 438cabdff1aSopenharmony_ci if (child_fi->is_var_size != header_fi->is_var_size) { 439cabdff1aSopenharmony_ci /* Changing blocking strategy not allowed per the spec */ 440cabdff1aSopenharmony_ci deduction += FLAC_HEADER_BASE_SCORE; 441cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 442cabdff1aSopenharmony_ci "blocking strategy change detected in adjacent frames\n"); 443cabdff1aSopenharmony_ci } 444cabdff1aSopenharmony_ci if (child_fi->channels != header_fi->channels) { 445cabdff1aSopenharmony_ci deduction += FLAC_HEADER_CHANGED_PENALTY; 446cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 447cabdff1aSopenharmony_ci "number of channels change detected in adjacent frames\n"); 448cabdff1aSopenharmony_ci } 449cabdff1aSopenharmony_ci return deduction; 450cabdff1aSopenharmony_ci} 451cabdff1aSopenharmony_ci 452cabdff1aSopenharmony_cistatic int check_header_mismatch(FLACParseContext *fpc, 453cabdff1aSopenharmony_ci FLACHeaderMarker *header, 454cabdff1aSopenharmony_ci FLACHeaderMarker *child, 455cabdff1aSopenharmony_ci int log_level_offset) 456cabdff1aSopenharmony_ci{ 457cabdff1aSopenharmony_ci FLACFrameInfo *header_fi = &header->fi, *child_fi = &child->fi; 458cabdff1aSopenharmony_ci int deduction, deduction_expected = 0, i; 459cabdff1aSopenharmony_ci deduction = check_header_fi_mismatch(fpc, header_fi, child_fi, 460cabdff1aSopenharmony_ci log_level_offset); 461cabdff1aSopenharmony_ci /* Check sample and frame numbers. */ 462cabdff1aSopenharmony_ci if ((child_fi->frame_or_sample_num - header_fi->frame_or_sample_num 463cabdff1aSopenharmony_ci != header_fi->blocksize) && 464cabdff1aSopenharmony_ci (child_fi->frame_or_sample_num 465cabdff1aSopenharmony_ci != header_fi->frame_or_sample_num + 1)) { 466cabdff1aSopenharmony_ci FLACHeaderMarker *curr; 467cabdff1aSopenharmony_ci int64_t expected_frame_num, expected_sample_num; 468cabdff1aSopenharmony_ci /* If there are frames in the middle we expect this deduction, 469cabdff1aSopenharmony_ci as they are probably valid and this one follows it */ 470cabdff1aSopenharmony_ci 471cabdff1aSopenharmony_ci expected_frame_num = expected_sample_num = header_fi->frame_or_sample_num; 472cabdff1aSopenharmony_ci curr = header; 473cabdff1aSopenharmony_ci while (curr != child) { 474cabdff1aSopenharmony_ci /* Ignore frames that failed all crc checks */ 475cabdff1aSopenharmony_ci for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS; i++) { 476cabdff1aSopenharmony_ci if (curr->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY) { 477cabdff1aSopenharmony_ci expected_frame_num++; 478cabdff1aSopenharmony_ci expected_sample_num += curr->fi.blocksize; 479cabdff1aSopenharmony_ci break; 480cabdff1aSopenharmony_ci } 481cabdff1aSopenharmony_ci } 482cabdff1aSopenharmony_ci curr = curr->next; 483cabdff1aSopenharmony_ci } 484cabdff1aSopenharmony_ci 485cabdff1aSopenharmony_ci if (expected_frame_num == child_fi->frame_or_sample_num || 486cabdff1aSopenharmony_ci expected_sample_num == child_fi->frame_or_sample_num) 487cabdff1aSopenharmony_ci deduction_expected = deduction ? 0 : 1; 488cabdff1aSopenharmony_ci 489cabdff1aSopenharmony_ci deduction += FLAC_HEADER_CHANGED_PENALTY; 490cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 491cabdff1aSopenharmony_ci "sample/frame number mismatch in adjacent frames\n"); 492cabdff1aSopenharmony_ci } 493cabdff1aSopenharmony_ci 494cabdff1aSopenharmony_ci /* If we have suspicious headers, check the CRC between them */ 495cabdff1aSopenharmony_ci if (deduction && !deduction_expected) { 496cabdff1aSopenharmony_ci FLACHeaderMarker *curr; 497cabdff1aSopenharmony_ci int read_len; 498cabdff1aSopenharmony_ci uint8_t *buf; 499cabdff1aSopenharmony_ci uint32_t crc = 1; 500cabdff1aSopenharmony_ci int inverted_test = 0; 501cabdff1aSopenharmony_ci 502cabdff1aSopenharmony_ci /* Since CRC is expensive only do it if we haven't yet. 503cabdff1aSopenharmony_ci This assumes a CRC penalty is greater than all other check penalties */ 504cabdff1aSopenharmony_ci curr = header->next; 505cabdff1aSopenharmony_ci for (i = 0; i < FLAC_MAX_SEQUENTIAL_HEADERS && curr != child; i++) 506cabdff1aSopenharmony_ci curr = curr->next; 507cabdff1aSopenharmony_ci 508cabdff1aSopenharmony_ci if (header->link_penalty[i] < FLAC_HEADER_CRC_FAIL_PENALTY || 509cabdff1aSopenharmony_ci header->link_penalty[i] == FLAC_HEADER_NOT_PENALIZED_YET) { 510cabdff1aSopenharmony_ci FLACHeaderMarker *start, *end; 511cabdff1aSopenharmony_ci 512cabdff1aSopenharmony_ci /* Although overlapping chains are scored, the crc should never 513cabdff1aSopenharmony_ci have to be computed twice for a single byte. */ 514cabdff1aSopenharmony_ci start = header; 515cabdff1aSopenharmony_ci end = child; 516cabdff1aSopenharmony_ci if (i > 0 && 517cabdff1aSopenharmony_ci header->link_penalty[i - 1] >= FLAC_HEADER_CRC_FAIL_PENALTY) { 518cabdff1aSopenharmony_ci while (start->next != child) 519cabdff1aSopenharmony_ci start = start->next; 520cabdff1aSopenharmony_ci inverted_test = 1; 521cabdff1aSopenharmony_ci } else if (i > 0 && 522cabdff1aSopenharmony_ci header->next->link_penalty[i-1] >= 523cabdff1aSopenharmony_ci FLAC_HEADER_CRC_FAIL_PENALTY ) { 524cabdff1aSopenharmony_ci end = header->next; 525cabdff1aSopenharmony_ci inverted_test = 1; 526cabdff1aSopenharmony_ci } 527cabdff1aSopenharmony_ci 528cabdff1aSopenharmony_ci read_len = end->offset - start->offset; 529cabdff1aSopenharmony_ci buf = flac_fifo_read(&fpc->fifo_buf, start->offset, &read_len); 530cabdff1aSopenharmony_ci crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, buf, read_len); 531cabdff1aSopenharmony_ci read_len = (end->offset - start->offset) - read_len; 532cabdff1aSopenharmony_ci 533cabdff1aSopenharmony_ci if (read_len) { 534cabdff1aSopenharmony_ci buf = flac_fifo_read(&fpc->fifo_buf, end->offset - read_len, &read_len); 535cabdff1aSopenharmony_ci crc = av_crc(av_crc_get_table(AV_CRC_16_ANSI), crc, buf, read_len); 536cabdff1aSopenharmony_ci } 537cabdff1aSopenharmony_ci } 538cabdff1aSopenharmony_ci 539cabdff1aSopenharmony_ci if (!crc ^ !inverted_test) { 540cabdff1aSopenharmony_ci deduction += FLAC_HEADER_CRC_FAIL_PENALTY; 541cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_WARNING + log_level_offset, 542cabdff1aSopenharmony_ci "crc check failed from offset %i (frame %"PRId64") to %i (frame %"PRId64")\n", 543cabdff1aSopenharmony_ci header->offset, header_fi->frame_or_sample_num, 544cabdff1aSopenharmony_ci child->offset, child_fi->frame_or_sample_num); 545cabdff1aSopenharmony_ci } 546cabdff1aSopenharmony_ci } 547cabdff1aSopenharmony_ci return deduction; 548cabdff1aSopenharmony_ci} 549cabdff1aSopenharmony_ci 550cabdff1aSopenharmony_ci/** 551cabdff1aSopenharmony_ci * Score a header. 552cabdff1aSopenharmony_ci * 553cabdff1aSopenharmony_ci * Give FLAC_HEADER_BASE_SCORE points to a frame for existing. 554cabdff1aSopenharmony_ci * If it has children, (subsequent frames of which the preceding CRC footer 555cabdff1aSopenharmony_ci * validates against this one,) then take the maximum score of the children, 556cabdff1aSopenharmony_ci * with a penalty of FLAC_HEADER_CHANGED_PENALTY applied for each change to 557cabdff1aSopenharmony_ci * bps, sample rate, channels, but not decorrelation mode, or blocksize, 558cabdff1aSopenharmony_ci * because it can change often. 559cabdff1aSopenharmony_ci **/ 560cabdff1aSopenharmony_cistatic int score_header(FLACParseContext *fpc, FLACHeaderMarker *header) 561cabdff1aSopenharmony_ci{ 562cabdff1aSopenharmony_ci FLACHeaderMarker *child; 563cabdff1aSopenharmony_ci int dist = 0; 564cabdff1aSopenharmony_ci int child_score; 565cabdff1aSopenharmony_ci int base_score = FLAC_HEADER_BASE_SCORE; 566cabdff1aSopenharmony_ci if (header->max_score != FLAC_HEADER_NOT_SCORED_YET) 567cabdff1aSopenharmony_ci return header->max_score; 568cabdff1aSopenharmony_ci 569cabdff1aSopenharmony_ci /* Modify the base score with changes from the last output header */ 570cabdff1aSopenharmony_ci if (fpc->last_fi_valid) { 571cabdff1aSopenharmony_ci /* Silence the log since this will be repeated if selected */ 572cabdff1aSopenharmony_ci base_score -= check_header_fi_mismatch(fpc, &fpc->last_fi, &header->fi, 573cabdff1aSopenharmony_ci AV_LOG_DEBUG); 574cabdff1aSopenharmony_ci } 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_ci header->max_score = base_score; 577cabdff1aSopenharmony_ci 578cabdff1aSopenharmony_ci /* Check and compute the children's scores. */ 579cabdff1aSopenharmony_ci child = header->next; 580cabdff1aSopenharmony_ci for (dist = 0; dist < FLAC_MAX_SEQUENTIAL_HEADERS && child; dist++) { 581cabdff1aSopenharmony_ci /* Look at the child's frame header info and penalize suspicious 582cabdff1aSopenharmony_ci changes between the headers. */ 583cabdff1aSopenharmony_ci if (header->link_penalty[dist] == FLAC_HEADER_NOT_PENALIZED_YET) { 584cabdff1aSopenharmony_ci header->link_penalty[dist] = check_header_mismatch(fpc, header, 585cabdff1aSopenharmony_ci child, AV_LOG_DEBUG); 586cabdff1aSopenharmony_ci } 587cabdff1aSopenharmony_ci child_score = score_header(fpc, child) - header->link_penalty[dist]; 588cabdff1aSopenharmony_ci 589cabdff1aSopenharmony_ci if (FLAC_HEADER_BASE_SCORE + child_score > header->max_score) { 590cabdff1aSopenharmony_ci /* Keep the child because the frame scoring is dynamic. */ 591cabdff1aSopenharmony_ci header->best_child = child; 592cabdff1aSopenharmony_ci header->max_score = base_score + child_score; 593cabdff1aSopenharmony_ci } 594cabdff1aSopenharmony_ci child = child->next; 595cabdff1aSopenharmony_ci } 596cabdff1aSopenharmony_ci 597cabdff1aSopenharmony_ci return header->max_score; 598cabdff1aSopenharmony_ci} 599cabdff1aSopenharmony_ci 600cabdff1aSopenharmony_cistatic void score_sequences(FLACParseContext *fpc) 601cabdff1aSopenharmony_ci{ 602cabdff1aSopenharmony_ci FLACHeaderMarker *curr; 603cabdff1aSopenharmony_ci int best_score = 0;//FLAC_HEADER_NOT_SCORED_YET; 604cabdff1aSopenharmony_ci /* First pass to clear all old scores. */ 605cabdff1aSopenharmony_ci for (curr = fpc->headers; curr; curr = curr->next) 606cabdff1aSopenharmony_ci curr->max_score = FLAC_HEADER_NOT_SCORED_YET; 607cabdff1aSopenharmony_ci 608cabdff1aSopenharmony_ci /* Do a second pass to score them all. */ 609cabdff1aSopenharmony_ci for (curr = fpc->headers; curr; curr = curr->next) { 610cabdff1aSopenharmony_ci if (score_header(fpc, curr) > best_score) { 611cabdff1aSopenharmony_ci fpc->best_header = curr; 612cabdff1aSopenharmony_ci best_score = curr->max_score; 613cabdff1aSopenharmony_ci } 614cabdff1aSopenharmony_ci } 615cabdff1aSopenharmony_ci} 616cabdff1aSopenharmony_ci 617cabdff1aSopenharmony_cistatic int get_best_header(FLACParseContext *fpc, const uint8_t **poutbuf, 618cabdff1aSopenharmony_ci int *poutbuf_size) 619cabdff1aSopenharmony_ci{ 620cabdff1aSopenharmony_ci FLACHeaderMarker *header = fpc->best_header; 621cabdff1aSopenharmony_ci FLACHeaderMarker *child = header->best_child; 622cabdff1aSopenharmony_ci if (!child) { 623cabdff1aSopenharmony_ci *poutbuf_size = flac_fifo_size(&fpc->fifo_buf) - header->offset; 624cabdff1aSopenharmony_ci } else { 625cabdff1aSopenharmony_ci *poutbuf_size = child->offset - header->offset; 626cabdff1aSopenharmony_ci 627cabdff1aSopenharmony_ci /* If the child has suspicious changes, log them */ 628cabdff1aSopenharmony_ci check_header_mismatch(fpc, header, child, 0); 629cabdff1aSopenharmony_ci } 630cabdff1aSopenharmony_ci 631cabdff1aSopenharmony_ci ff_flac_set_channel_layout(fpc->avctx, header->fi.channels); 632cabdff1aSopenharmony_ci 633cabdff1aSopenharmony_ci fpc->avctx->sample_rate = header->fi.samplerate; 634cabdff1aSopenharmony_ci fpc->pc->duration = header->fi.blocksize; 635cabdff1aSopenharmony_ci *poutbuf = flac_fifo_read_wrap(fpc, header->offset, *poutbuf_size, 636cabdff1aSopenharmony_ci &fpc->wrap_buf, 637cabdff1aSopenharmony_ci &fpc->wrap_buf_allocated_size); 638cabdff1aSopenharmony_ci 639cabdff1aSopenharmony_ci if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) { 640cabdff1aSopenharmony_ci if (header->fi.is_var_size) 641cabdff1aSopenharmony_ci fpc->pc->pts = header->fi.frame_or_sample_num; 642cabdff1aSopenharmony_ci else if (header->best_child) 643cabdff1aSopenharmony_ci fpc->pc->pts = header->fi.frame_or_sample_num * header->fi.blocksize; 644cabdff1aSopenharmony_ci } 645cabdff1aSopenharmony_ci 646cabdff1aSopenharmony_ci fpc->best_header_valid = 0; 647cabdff1aSopenharmony_ci fpc->last_fi_valid = 1; 648cabdff1aSopenharmony_ci fpc->last_fi = header->fi; 649cabdff1aSopenharmony_ci 650cabdff1aSopenharmony_ci /* Return the negative overread index so the client can compute pos. 651cabdff1aSopenharmony_ci This should be the amount overread to the beginning of the child */ 652cabdff1aSopenharmony_ci if (child) 653cabdff1aSopenharmony_ci return child->offset - flac_fifo_size(&fpc->fifo_buf); 654cabdff1aSopenharmony_ci return 0; 655cabdff1aSopenharmony_ci} 656cabdff1aSopenharmony_ci 657cabdff1aSopenharmony_cistatic int flac_parse(AVCodecParserContext *s, AVCodecContext *avctx, 658cabdff1aSopenharmony_ci const uint8_t **poutbuf, int *poutbuf_size, 659cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 660cabdff1aSopenharmony_ci{ 661cabdff1aSopenharmony_ci FLACParseContext *fpc = s->priv_data; 662cabdff1aSopenharmony_ci FLACHeaderMarker *curr; 663cabdff1aSopenharmony_ci int nb_headers; 664cabdff1aSopenharmony_ci const uint8_t *read_end = buf; 665cabdff1aSopenharmony_ci const uint8_t *read_start = buf; 666cabdff1aSopenharmony_ci 667cabdff1aSopenharmony_ci if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { 668cabdff1aSopenharmony_ci FLACFrameInfo fi; 669cabdff1aSopenharmony_ci if (frame_header_is_valid(avctx, buf, &fi)) { 670cabdff1aSopenharmony_ci s->duration = fi.blocksize; 671cabdff1aSopenharmony_ci if (!avctx->sample_rate) 672cabdff1aSopenharmony_ci avctx->sample_rate = fi.samplerate; 673cabdff1aSopenharmony_ci if (fpc->pc->flags & PARSER_FLAG_USE_CODEC_TS) { 674cabdff1aSopenharmony_ci fpc->pc->pts = fi.frame_or_sample_num; 675cabdff1aSopenharmony_ci if (!fi.is_var_size) 676cabdff1aSopenharmony_ci fpc->pc->pts *= fi.blocksize; 677cabdff1aSopenharmony_ci } 678cabdff1aSopenharmony_ci } 679cabdff1aSopenharmony_ci *poutbuf = buf; 680cabdff1aSopenharmony_ci *poutbuf_size = buf_size; 681cabdff1aSopenharmony_ci return buf_size; 682cabdff1aSopenharmony_ci } 683cabdff1aSopenharmony_ci 684cabdff1aSopenharmony_ci fpc->avctx = avctx; 685cabdff1aSopenharmony_ci if (fpc->best_header_valid) 686cabdff1aSopenharmony_ci return get_best_header(fpc, poutbuf, poutbuf_size); 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci /* If a best_header was found last call remove it with the buffer data. */ 689cabdff1aSopenharmony_ci if (fpc->best_header && fpc->best_header->best_child) { 690cabdff1aSopenharmony_ci FLACHeaderMarker *temp; 691cabdff1aSopenharmony_ci FLACHeaderMarker *best_child = fpc->best_header->best_child; 692cabdff1aSopenharmony_ci 693cabdff1aSopenharmony_ci /* Remove headers in list until the end of the best_header. */ 694cabdff1aSopenharmony_ci for (curr = fpc->headers; curr != best_child; curr = temp) { 695cabdff1aSopenharmony_ci if (curr != fpc->best_header) { 696cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, 697cabdff1aSopenharmony_ci "dropping low score %i frame header from offset %i to %i\n", 698cabdff1aSopenharmony_ci curr->max_score, curr->offset, curr->next->offset); 699cabdff1aSopenharmony_ci } 700cabdff1aSopenharmony_ci temp = curr->next; 701cabdff1aSopenharmony_ci av_free(curr); 702cabdff1aSopenharmony_ci fpc->nb_headers_buffered--; 703cabdff1aSopenharmony_ci } 704cabdff1aSopenharmony_ci /* Release returned data from ring buffer. */ 705cabdff1aSopenharmony_ci flac_fifo_drain(&fpc->fifo_buf, best_child->offset); 706cabdff1aSopenharmony_ci 707cabdff1aSopenharmony_ci /* Fix the offset for the headers remaining to match the new buffer. */ 708cabdff1aSopenharmony_ci for (curr = best_child->next; curr; curr = curr->next) 709cabdff1aSopenharmony_ci curr->offset -= best_child->offset; 710cabdff1aSopenharmony_ci 711cabdff1aSopenharmony_ci best_child->offset = 0; 712cabdff1aSopenharmony_ci fpc->headers = best_child; 713cabdff1aSopenharmony_ci if (fpc->nb_headers_buffered >= FLAC_MIN_HEADERS) { 714cabdff1aSopenharmony_ci fpc->best_header = best_child; 715cabdff1aSopenharmony_ci return get_best_header(fpc, poutbuf, poutbuf_size); 716cabdff1aSopenharmony_ci } 717cabdff1aSopenharmony_ci fpc->best_header = NULL; 718cabdff1aSopenharmony_ci } else if (fpc->best_header) { 719cabdff1aSopenharmony_ci /* No end frame no need to delete the buffer; probably eof */ 720cabdff1aSopenharmony_ci FLACHeaderMarker *temp; 721cabdff1aSopenharmony_ci 722cabdff1aSopenharmony_ci for (curr = fpc->headers; curr != fpc->best_header; curr = temp) { 723cabdff1aSopenharmony_ci temp = curr->next; 724cabdff1aSopenharmony_ci av_free(curr); 725cabdff1aSopenharmony_ci fpc->nb_headers_buffered--; 726cabdff1aSopenharmony_ci } 727cabdff1aSopenharmony_ci fpc->headers = fpc->best_header->next; 728cabdff1aSopenharmony_ci av_freep(&fpc->best_header); 729cabdff1aSopenharmony_ci fpc->nb_headers_buffered--; 730cabdff1aSopenharmony_ci } 731cabdff1aSopenharmony_ci 732cabdff1aSopenharmony_ci /* Find and score new headers. */ 733cabdff1aSopenharmony_ci /* buf_size is zero when flushing, so check for this since we do */ 734cabdff1aSopenharmony_ci /* not want to try to read more input once we have found the end. */ 735cabdff1aSopenharmony_ci /* Also note that buf can't be NULL. */ 736cabdff1aSopenharmony_ci while ((buf_size && read_end < buf + buf_size && 737cabdff1aSopenharmony_ci fpc->nb_headers_buffered < FLAC_MIN_HEADERS) 738cabdff1aSopenharmony_ci || (!buf_size && !fpc->end_padded)) { 739cabdff1aSopenharmony_ci int start_offset, ret; 740cabdff1aSopenharmony_ci 741cabdff1aSopenharmony_ci /* Pad the end once if EOF, to check the final region for headers. */ 742cabdff1aSopenharmony_ci if (!buf_size) { 743cabdff1aSopenharmony_ci fpc->end_padded = 1; 744cabdff1aSopenharmony_ci read_end = read_start + MAX_FRAME_HEADER_SIZE; 745cabdff1aSopenharmony_ci } else { 746cabdff1aSopenharmony_ci /* The maximum read size is the upper-bound of what the parser 747cabdff1aSopenharmony_ci needs to have the required number of frames buffered */ 748cabdff1aSopenharmony_ci int nb_desired = FLAC_MIN_HEADERS - fpc->nb_headers_buffered + 1; 749cabdff1aSopenharmony_ci read_end = read_end + FFMIN(buf + buf_size - read_end, 750cabdff1aSopenharmony_ci nb_desired * FLAC_AVG_FRAME_SIZE); 751cabdff1aSopenharmony_ci } 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_ci if (!flac_fifo_space(&fpc->fifo_buf) && 754cabdff1aSopenharmony_ci flac_fifo_size(&fpc->fifo_buf) / FLAC_AVG_FRAME_SIZE > 755cabdff1aSopenharmony_ci fpc->nb_headers_buffered * 20) { 756cabdff1aSopenharmony_ci /* There is less than one valid flac header buffered for 20 headers 757cabdff1aSopenharmony_ci * buffered. Therefore the fifo is most likely filled with invalid 758cabdff1aSopenharmony_ci * data and the input is not a flac file. */ 759cabdff1aSopenharmony_ci goto handle_error; 760cabdff1aSopenharmony_ci } 761cabdff1aSopenharmony_ci 762cabdff1aSopenharmony_ci /* Fill the buffer. */ 763cabdff1aSopenharmony_ci if (buf_size) { 764cabdff1aSopenharmony_ci ret = flac_fifo_write(&fpc->fifo_buf, read_start, 765cabdff1aSopenharmony_ci read_end - read_start); 766cabdff1aSopenharmony_ci } else { 767cabdff1aSopenharmony_ci int8_t pad[MAX_FRAME_HEADER_SIZE] = { 0 }; 768cabdff1aSopenharmony_ci ret = flac_fifo_write(&fpc->fifo_buf, pad, sizeof(pad)); 769cabdff1aSopenharmony_ci } 770cabdff1aSopenharmony_ci if (ret < 0) { 771cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Error buffering data\n"); 772cabdff1aSopenharmony_ci goto handle_error; 773cabdff1aSopenharmony_ci } 774cabdff1aSopenharmony_ci 775cabdff1aSopenharmony_ci /* Tag headers and update sequences. */ 776cabdff1aSopenharmony_ci start_offset = flac_fifo_size(&fpc->fifo_buf) - 777cabdff1aSopenharmony_ci ((read_end - read_start) + (MAX_FRAME_HEADER_SIZE - 1)); 778cabdff1aSopenharmony_ci start_offset = FFMAX(0, start_offset); 779cabdff1aSopenharmony_ci nb_headers = find_new_headers(fpc, start_offset); 780cabdff1aSopenharmony_ci 781cabdff1aSopenharmony_ci if (nb_headers < 0) { 782cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 783cabdff1aSopenharmony_ci "find_new_headers couldn't allocate FLAC header\n"); 784cabdff1aSopenharmony_ci goto handle_error; 785cabdff1aSopenharmony_ci } 786cabdff1aSopenharmony_ci 787cabdff1aSopenharmony_ci fpc->nb_headers_buffered = nb_headers; 788cabdff1aSopenharmony_ci /* Wait till FLAC_MIN_HEADERS to output a valid frame. */ 789cabdff1aSopenharmony_ci if (!fpc->end_padded && fpc->nb_headers_buffered < FLAC_MIN_HEADERS) { 790cabdff1aSopenharmony_ci if (read_end < buf + buf_size) { 791cabdff1aSopenharmony_ci read_start = read_end; 792cabdff1aSopenharmony_ci continue; 793cabdff1aSopenharmony_ci } else { 794cabdff1aSopenharmony_ci goto handle_error; 795cabdff1aSopenharmony_ci } 796cabdff1aSopenharmony_ci } 797cabdff1aSopenharmony_ci 798cabdff1aSopenharmony_ci /* If headers found, update the scores since we have longer chains. */ 799cabdff1aSopenharmony_ci if (fpc->end_padded || fpc->nb_headers_found) 800cabdff1aSopenharmony_ci score_sequences(fpc); 801cabdff1aSopenharmony_ci 802cabdff1aSopenharmony_ci /* restore the state pre-padding */ 803cabdff1aSopenharmony_ci if (fpc->end_padded) { 804cabdff1aSopenharmony_ci int empty = flac_fifo_size(&fpc->fifo_buf) == MAX_FRAME_HEADER_SIZE; 805cabdff1aSopenharmony_ci int warp = fpc->fifo_buf.wptr - fpc->fifo_buf.buffer < MAX_FRAME_HEADER_SIZE; 806cabdff1aSopenharmony_ci /* HACK: drain the tail of the fifo */ 807cabdff1aSopenharmony_ci fpc->fifo_buf.wptr -= MAX_FRAME_HEADER_SIZE; 808cabdff1aSopenharmony_ci if (warp) { 809cabdff1aSopenharmony_ci fpc->fifo_buf.wptr += fpc->fifo_buf.end - 810cabdff1aSopenharmony_ci fpc->fifo_buf.buffer; 811cabdff1aSopenharmony_ci } 812cabdff1aSopenharmony_ci fpc->fifo_buf.empty = empty; 813cabdff1aSopenharmony_ci read_start = read_end = NULL; 814cabdff1aSopenharmony_ci } 815cabdff1aSopenharmony_ci } 816cabdff1aSopenharmony_ci 817cabdff1aSopenharmony_ci for (curr = fpc->headers; curr; curr = curr->next) { 818cabdff1aSopenharmony_ci if (!fpc->best_header || curr->max_score > fpc->best_header->max_score) { 819cabdff1aSopenharmony_ci fpc->best_header = curr; 820cabdff1aSopenharmony_ci } 821cabdff1aSopenharmony_ci } 822cabdff1aSopenharmony_ci 823cabdff1aSopenharmony_ci if (fpc->best_header && fpc->best_header->max_score <= 0) { 824cabdff1aSopenharmony_ci // Only accept a bad header if there is no other option to continue 825cabdff1aSopenharmony_ci if (!buf_size || read_end != buf || fpc->nb_headers_buffered < FLAC_MIN_HEADERS) 826cabdff1aSopenharmony_ci fpc->best_header = NULL; 827cabdff1aSopenharmony_ci } 828cabdff1aSopenharmony_ci 829cabdff1aSopenharmony_ci if (fpc->best_header) { 830cabdff1aSopenharmony_ci fpc->best_header_valid = 1; 831cabdff1aSopenharmony_ci if (fpc->best_header->offset > 0) { 832cabdff1aSopenharmony_ci /* Output a junk frame. */ 833cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "Junk frame till offset %i\n", 834cabdff1aSopenharmony_ci fpc->best_header->offset); 835cabdff1aSopenharmony_ci 836cabdff1aSopenharmony_ci /* Set duration to 0. It is unknown or invalid in a junk frame. */ 837cabdff1aSopenharmony_ci s->duration = 0; 838cabdff1aSopenharmony_ci *poutbuf_size = fpc->best_header->offset; 839cabdff1aSopenharmony_ci *poutbuf = flac_fifo_read_wrap(fpc, 0, *poutbuf_size, 840cabdff1aSopenharmony_ci &fpc->wrap_buf, 841cabdff1aSopenharmony_ci &fpc->wrap_buf_allocated_size); 842cabdff1aSopenharmony_ci return buf_size ? (read_end - buf) : (fpc->best_header->offset - 843cabdff1aSopenharmony_ci flac_fifo_size(&fpc->fifo_buf)); 844cabdff1aSopenharmony_ci } 845cabdff1aSopenharmony_ci if (!buf_size) 846cabdff1aSopenharmony_ci return get_best_header(fpc, poutbuf, poutbuf_size); 847cabdff1aSopenharmony_ci } 848cabdff1aSopenharmony_ci 849cabdff1aSopenharmony_cihandle_error: 850cabdff1aSopenharmony_ci *poutbuf = NULL; 851cabdff1aSopenharmony_ci *poutbuf_size = 0; 852cabdff1aSopenharmony_ci return buf_size ? read_end - buf : 0; 853cabdff1aSopenharmony_ci} 854cabdff1aSopenharmony_ci 855cabdff1aSopenharmony_cistatic av_cold int flac_parse_init(AVCodecParserContext *c) 856cabdff1aSopenharmony_ci{ 857cabdff1aSopenharmony_ci FLACParseContext *fpc = c->priv_data; 858cabdff1aSopenharmony_ci int ret; 859cabdff1aSopenharmony_ci 860cabdff1aSopenharmony_ci fpc->pc = c; 861cabdff1aSopenharmony_ci /* There will generally be FLAC_MIN_HEADERS buffered in the fifo before 862cabdff1aSopenharmony_ci it drains. This is allocated early to avoid slow reallocation. */ 863cabdff1aSopenharmony_ci ret = flac_fifo_alloc(&fpc->fifo_buf, (FLAC_MIN_HEADERS + 3) * FLAC_AVG_FRAME_SIZE); 864cabdff1aSopenharmony_ci if (ret < 0) { 865cabdff1aSopenharmony_ci av_log(fpc->avctx, AV_LOG_ERROR, 866cabdff1aSopenharmony_ci "couldn't allocate fifo_buf\n"); 867cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 868cabdff1aSopenharmony_ci } 869cabdff1aSopenharmony_ci return 0; 870cabdff1aSopenharmony_ci} 871cabdff1aSopenharmony_ci 872cabdff1aSopenharmony_cistatic void flac_parse_close(AVCodecParserContext *c) 873cabdff1aSopenharmony_ci{ 874cabdff1aSopenharmony_ci FLACParseContext *fpc = c->priv_data; 875cabdff1aSopenharmony_ci FLACHeaderMarker *curr = fpc->headers, *temp; 876cabdff1aSopenharmony_ci 877cabdff1aSopenharmony_ci while (curr) { 878cabdff1aSopenharmony_ci temp = curr->next; 879cabdff1aSopenharmony_ci av_free(curr); 880cabdff1aSopenharmony_ci curr = temp; 881cabdff1aSopenharmony_ci } 882cabdff1aSopenharmony_ci fpc->headers = NULL; 883cabdff1aSopenharmony_ci flac_fifo_free(&fpc->fifo_buf); 884cabdff1aSopenharmony_ci av_freep(&fpc->wrap_buf); 885cabdff1aSopenharmony_ci} 886cabdff1aSopenharmony_ci 887cabdff1aSopenharmony_ciconst AVCodecParser ff_flac_parser = { 888cabdff1aSopenharmony_ci .codec_ids = { AV_CODEC_ID_FLAC }, 889cabdff1aSopenharmony_ci .priv_data_size = sizeof(FLACParseContext), 890cabdff1aSopenharmony_ci .parser_init = flac_parse_init, 891cabdff1aSopenharmony_ci .parser_parse = flac_parse, 892cabdff1aSopenharmony_ci .parser_close = flac_parse_close, 893cabdff1aSopenharmony_ci}; 894