/* * 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 */ #include "adts_header.h" #include "avcodec.h" #include "codec_internal.h" #include "get_bits.h" #include "decode.h" typedef struct FTRContext { AVCodecContext *aac_avctx[64]; // wrapper context for AAC int nb_context; AVPacket *packet; AVFrame *frame; } FTRContext; static av_cold int ftr_init(AVCodecContext *avctx) { FTRContext *s = avctx->priv_data; const AVCodec *codec; int ret; if (avctx->ch_layout.nb_channels > 64 || avctx->ch_layout.nb_channels <= 0) return AVERROR(EINVAL); s->packet = av_packet_alloc(); if (!s->packet) return AVERROR(ENOMEM); s->frame = av_frame_alloc(); if (!s->frame) return AVERROR(ENOMEM); s->nb_context = avctx->ch_layout.nb_channels; codec = avcodec_find_decoder(AV_CODEC_ID_AAC); if (!codec) return AVERROR_BUG; for (int i = 0; i < s->nb_context; i++) { s->aac_avctx[i] = avcodec_alloc_context3(codec); if (!s->aac_avctx[i]) return AVERROR(ENOMEM); ret = avcodec_open2(s->aac_avctx[i], codec, NULL); if (ret < 0) return ret; } avctx->sample_fmt = s->aac_avctx[0]->sample_fmt; if (!av_sample_fmt_is_planar(avctx->sample_fmt)) return AVERROR(EINVAL); return 0; } static int ftr_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame, AVPacket *avpkt) { FTRContext *s = avctx->priv_data; GetBitContext gb; int ret, ch_offset = 0; ret = init_get_bits8(&gb, avpkt->data, avpkt->size); if (ret < 0) return ret; frame->nb_samples = 0; for (int i = 0; i < s->nb_context; i++) { AVCodecContext *codec_avctx = s->aac_avctx[i]; GetBitContext gb2 = gb; AACADTSHeaderInfo hdr_info; int size; if (get_bits_left(&gb) < 64) return AVERROR_INVALIDDATA; memset(&hdr_info, 0, sizeof(hdr_info)); size = ff_adts_header_parse(&gb2, &hdr_info); if (size <= 0 || size * 8 > get_bits_left(&gb)) return AVERROR_INVALIDDATA; if (size > s->packet->size) { ret = av_grow_packet(s->packet, size - s->packet->size); if (ret < 0) return ret; } ret = av_packet_make_writable(s->packet); if (ret < 0) return ret; memcpy(s->packet->data, avpkt->data + (get_bits_count(&gb) >> 3), size); s->packet->size = size; if (size > 12) { uint8_t *buf = s->packet->data; if (buf[3] & 0x20) { int tmp = buf[8]; buf[ 9] = ~buf[9]; buf[11] = ~buf[11]; buf[12] = ~buf[12]; buf[ 8] = ~buf[10]; buf[10] = ~tmp; } } ret = avcodec_send_packet(codec_avctx, s->packet); if (ret < 0) { av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); return ret; } ret = avcodec_receive_frame(codec_avctx, s->frame); if (ret < 0) return ret; if (!avctx->sample_rate) { avctx->sample_rate = codec_avctx->sample_rate; } else { if (avctx->sample_rate != codec_avctx->sample_rate) return AVERROR_INVALIDDATA; } if (!frame->nb_samples) { frame->nb_samples = s->frame->nb_samples; if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; } else { if (frame->nb_samples != s->frame->nb_samples) return AVERROR_INVALIDDATA; } skip_bits_long(&gb, size * 8); if (ch_offset + s->frame->ch_layout.nb_channels > avctx->ch_layout.nb_channels) return AVERROR_INVALIDDATA; if (avctx->sample_fmt != codec_avctx->sample_fmt) return AVERROR_INVALIDDATA; for (int ch = 0; ch < s->frame->ch_layout.nb_channels; ch++) memcpy(frame->extended_data[ch_offset + ch], s->frame->extended_data[ch], av_get_bytes_per_sample(codec_avctx->sample_fmt) * s->frame->nb_samples); ch_offset += s->frame->ch_layout.nb_channels; if (ch_offset >= avctx->ch_layout.nb_channels) break; } *got_frame = 1; return get_bits_count(&gb) >> 3; } static void ftr_flush(AVCodecContext *avctx) { FTRContext *s = avctx->priv_data; for (int i = 0; i < s->nb_context; i++) avcodec_flush_buffers(s->aac_avctx[i]); } static av_cold int ftr_close(AVCodecContext *avctx) { FTRContext *s = avctx->priv_data; for (int i = 0; i < s->nb_context; i++) avcodec_free_context(&s->aac_avctx[i]); av_packet_free(&s->packet); av_frame_free(&s->frame); return 0; } const FFCodec ff_ftr_decoder = { .p.name = "ftr", .p.long_name = NULL_IF_CONFIG_SMALL("FTR Voice"), .p.type = AVMEDIA_TYPE_AUDIO, .p.id = AV_CODEC_ID_FTR, .init = ftr_init, FF_CODEC_DECODE_CB(ftr_decode_frame), .close = ftr_close, .flush = ftr_flush, .priv_data_size = sizeof(FTRContext), .p.capabilities = #if FF_API_SUBFRAMES AV_CODEC_CAP_SUBFRAMES | #endif AV_CODEC_CAP_DR1, .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, };