1/* 2 * Copyright (c) 2011 Justin Ruggles 3 * 4 * This file is part of Libav. 5 * 6 * Libav is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * Libav is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with Libav; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21/** 22 * @file 23 * ADX audio parser 24 * 25 * Splits packets into individual blocks. 26 */ 27 28#include "libavutil/intreadwrite.h" 29#include "parser.h" 30#include "adx.h" 31 32typedef struct ADXParseContext { 33 ParseContext pc; 34 int header_size; 35 int block_size; 36 int remaining; 37} ADXParseContext; 38 39static int adx_parse(AVCodecParserContext *s1, 40 AVCodecContext *avctx, 41 const uint8_t **poutbuf, int *poutbuf_size, 42 const uint8_t *buf, int buf_size) 43{ 44 ADXParseContext *s = s1->priv_data; 45 ParseContext *pc = &s->pc; 46 int next = END_NOT_FOUND; 47 int i; 48 uint64_t state = pc->state64; 49 50 if (!s->header_size) { 51 for (i = 0; i < buf_size; i++) { 52 state = (state << 8) | buf[i]; 53 /* check for fixed fields in ADX header for possible match */ 54 if ((state & 0xFFFF0000FFFFFF00) == 0x8000000003120400ULL) { 55 int channels = state & 0xFF; 56 int header_size = ((state >> 32) & 0xFFFF) + 4; 57 if (channels > 0 && header_size >= 8) { 58 s->header_size = header_size; 59 s->block_size = BLOCK_SIZE * channels; 60 s->remaining = i - 7 + s->header_size + s->block_size; 61 break; 62 } 63 } 64 } 65 pc->state64 = state; 66 } 67 68 if (s->header_size) { 69 if (!s->remaining) 70 s->remaining = s->block_size; 71 if (s->remaining <= buf_size) { 72 next = s->remaining; 73 s->remaining = 0; 74 } else 75 s->remaining -= buf_size; 76 } 77 78 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0 || !buf_size) { 79 *poutbuf = NULL; 80 *poutbuf_size = 0; 81 return buf_size; 82 } 83 *poutbuf = buf; 84 *poutbuf_size = buf_size; 85 return next; 86} 87 88AVCodecParser ff_adx_parser = { 89 .codec_ids = { CODEC_ID_ADPCM_ADX }, 90 .priv_data_size = sizeof(ADXParseContext), 91 .parser_parse = adx_parse, 92 .parser_close = ff_parse_close, 93}; 94