1/* 2 * Copyright (c) 2021 Paul B Mahol 3 * 4 * This file is part of FFmpeg. 5 * 6 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 * AMR audio parser 24 * 25 * Splits packets into individual blocks. 26 */ 27 28#include "libavutil/channel_layout.h" 29#include "libavutil/intreadwrite.h" 30#include "parser.h" 31 32static const uint8_t amrnb_packed_size[16] = { 33 13, 14, 16, 18, 20, 21, 27, 32, 6, 1, 1, 1, 1, 1, 1, 1 34}; 35static const uint8_t amrwb_packed_size[16] = { 36 18, 24, 33, 37, 41, 47, 51, 59, 61, 6, 1, 1, 1, 1, 1, 1 37}; 38 39typedef struct AMRParseContext { 40 ParseContext pc; 41 uint64_t cumulated_size; 42 uint64_t block_count; 43 int current_channel; 44 int remaining; 45} AMRParseContext; 46 47static av_cold int amr_parse_init(AVCodecParserContext *s1) 48{ 49 AMRParseContext *s = s1->priv_data; 50 s->remaining = -1; 51 return 0; 52} 53 54static int amr_parse(AVCodecParserContext *s1, 55 AVCodecContext *avctx, 56 const uint8_t **poutbuf, int *poutbuf_size, 57 const uint8_t *buf, int buf_size) 58{ 59 AMRParseContext *s = s1->priv_data; 60 ParseContext *pc = &s->pc; 61 int next = END_NOT_FOUND; 62 63 *poutbuf_size = 0; 64 *poutbuf = NULL; 65 66 if (!avctx->ch_layout.nb_channels) { 67 av_channel_layout_uninit(&avctx->ch_layout); 68 avctx->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO; 69 } 70 71 if (s1->flags & PARSER_FLAG_COMPLETE_FRAMES) { 72 next = buf_size; 73 } else { 74 int ch, offset = 0; 75 76 for (ch = s->current_channel; ch < avctx->ch_layout.nb_channels; ch++) { 77 if (s->remaining >= 0) { 78 next = s->remaining; 79 } else { 80 int mode = (buf[offset] >> 3) & 0x0F; 81 82 if (avctx->codec_id == AV_CODEC_ID_AMR_NB) { 83 next = amrnb_packed_size[mode]; 84 } else if (avctx->codec_id == AV_CODEC_ID_AMR_WB) { 85 next = amrwb_packed_size[mode]; 86 } 87 } 88 89 offset += next; 90 if (offset >= buf_size) { 91 s->remaining = offset - buf_size; 92 next = END_NOT_FOUND; 93 break; 94 } else { 95 s->remaining = -1; 96 } 97 } 98 99 s->current_channel = ch % avctx->ch_layout.nb_channels; 100 if (s->remaining < 0) 101 next = offset; 102 103 if (next != END_NOT_FOUND) { 104 if (s->cumulated_size < UINT64_MAX - next) { 105 s->cumulated_size += next; 106 /* Both AMR formats have 50 frames per second */ 107 avctx->bit_rate = s->cumulated_size / ++s->block_count * 8 * 50; 108 } 109 } 110 111 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) { 112 *poutbuf = NULL; 113 *poutbuf_size = 0; 114 return buf_size; 115 } 116 } 117 118 s1->duration = avctx->codec_id == AV_CODEC_ID_AMR_NB ? 160 : 320; 119 120 *poutbuf = buf; 121 *poutbuf_size = buf_size; 122 return next; 123} 124 125const AVCodecParser ff_amr_parser = { 126 .codec_ids = { AV_CODEC_ID_AMR_NB, AV_CODEC_ID_AMR_WB }, 127 .priv_data_size = sizeof(AMRParseContext), 128 .parser_init = amr_parse_init, 129 .parser_parse = amr_parse, 130 .parser_close = ff_parse_close, 131}; 132