Unified · Split
| @@ -361,6 +361,7 @@ OBJS-$(CONFIG_FMVC_DECODER) += fmvc.o · 360 unmodified lines | ||
| 361 | 361 | OBJS-$(CONFIG_FOURXM_DECODER) += 4xm.o |
| 362 | 362 | OBJS-$(CONFIG_FRAPS_DECODER) += fraps.o |
| 363 | 363 | OBJS-$(CONFIG_FRWU_DECODER) += frwu.o |
| 364 | +OBJS-$(CONFIG_FTR_DECODER) += ftr.o | |
| 364 | 365 | OBJS-$(CONFIG_G2M_DECODER) += g2meet.o elsdec.o mjpegdec_common.o |
| 365 | 366 | OBJS-$(CONFIG_G723_1_DECODER) += g723_1dec.o g723_1.o \ |
| 366 | 367 | acelp_vectors.o celp_filters.o celp_math.o |
| @@ -1133,6 +1134,7 @@ OBJS-$(CONFIG_DVBSUB_PARSER) += dvbsub_parser.o · 766 unmodified lines | ||
| 1133 | 1134 | OBJS-$(CONFIG_DVD_NAV_PARSER) += dvd_nav_parser.o |
| 1134 | 1135 | OBJS-$(CONFIG_DVDSUB_PARSER) += dvdsub_parser.o |
| 1135 | 1136 | OBJS-$(CONFIG_FLAC_PARSER) += flac_parser.o flacdata.o flac.o |
| 1137 | +OBJS-$(CONFIG_FTR_PARSER) += ftr_parser.o | |
| 1136 | 1138 | OBJS-$(CONFIG_G723_1_PARSER) += g723_1_parser.o |
| 1137 | 1139 | OBJS-$(CONFIG_G729_PARSER) += g729_parser.o |
| 1138 | 1140 | OBJS-$(CONFIG_GIF_PARSER) += gif_parser.o |
| @@ -468,6 +468,7 @@ extern const FFCodec ff_fastaudio_decoder; · 467 unmodified lines | ||
| 468 | 468 | extern const FFCodec ff_ffwavesynth_decoder; |
| 469 | 469 | extern const FFCodec ff_flac_encoder; |
| 470 | 470 | extern const FFCodec ff_flac_decoder; |
| 471 | +extern const FFCodec ff_ftr_decoder; | |
| 471 | 472 | extern const FFCodec ff_g723_1_encoder; |
| 472 | 473 | extern const FFCodec ff_g723_1_decoder; |
| 473 | 474 | extern const FFCodec ff_g729_decoder; |
| @@ -3311,6 +3311,13 @@ static const AVCodecDescriptor codec_descriptors[] = { · 3310 unmodified lines | ||
| 3311 | 3311 | .long_name = NULL_IF_CONFIG_SMALL("Marian's A-pac audio"), |
| 3312 | 3312 | .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, |
| 3313 | 3313 | }, |
| 3314 | + { | |
| 3315 | + .id = AV_CODEC_ID_FTR, | |
| 3316 | + .type = AVMEDIA_TYPE_AUDIO, | |
| 3317 | + .name = "ftr", | |
| 3318 | + .long_name = NULL_IF_CONFIG_SMALL("FTR Voice"), | |
| 3319 | + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, | |
| 3320 | + }, | |
| 3314 | 3321 | |
| 3315 | 3322 | /* subtitle codecs */ |
| 3316 | 3323 | { |
| @@ -530,6 +530,7 @@ enum AVCodecID { · 529 unmodified lines | ||
| 530 | 530 | AV_CODEC_ID_BONK, |
| 531 | 531 | AV_CODEC_ID_MISC4, |
| 532 | 532 | AV_CODEC_ID_APAC, |
| 533 | + AV_CODEC_ID_FTR, | |
| 533 | 534 | |
| 534 | 535 | /* subtitle codecs */ |
| 535 | 536 | AV_CODEC_ID_FIRST_SUBTITLE = 0x17000, ///< A dummy ID pointing at the start of subtitle codecs. |
| @@ -0,0 +1,208 @@ | ||
| 1 | +/* | |
| 2 | + * This file is part of FFmpeg. | |
| 3 | + * | |
| 4 | + * FFmpeg is free software; you can redistribute it and/or | |
| 5 | + * modify it under the terms of the GNU Lesser General Public | |
| 6 | + * License as published by the Free Software Foundation; either | |
| 7 | + * version 2.1 of the License, or (at your option) any later version. | |
| 8 | + * | |
| 9 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 | + * Lesser General Public License for more details. | |
| 13 | + * | |
| 14 | + * You should have received a copy of the GNU Lesser General Public | |
| 15 | + * License along with FFmpeg; if not, write to the Free Software | |
| 16 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 17 | + */ | |
| 18 | + | |
| 19 | +#include "adts_header.h" | |
| 20 | +#include "avcodec.h" | |
| 21 | +#include "codec_internal.h" | |
| 22 | +#include "get_bits.h" | |
| 23 | +#include "decode.h" | |
| 24 | + | |
| 25 | +typedef struct FTRContext { | |
| 26 | + AVCodecContext *aac_avctx[64]; // wrapper context for AAC | |
| 27 | + int nb_context; | |
| 28 | + AVPacket *packet; | |
| 29 | + AVFrame *frame; | |
| 30 | +} FTRContext; | |
| 31 | + | |
| 32 | +static av_cold int ftr_init(AVCodecContext *avctx) | |
| 33 | +{ | |
| 34 | + FTRContext *s = avctx->priv_data; | |
| 35 | + const AVCodec *codec; | |
| 36 | + int ret; | |
| 37 | + | |
| 38 | + if (avctx->ch_layout.nb_channels > 64 || | |
| 39 | + avctx->ch_layout.nb_channels <= 0) | |
| 40 | + return AVERROR(ENOTSUP); | |
| 41 | + | |
| 42 | + s->packet = av_packet_alloc(); | |
| 43 | + if (!s->packet) | |
| 44 | + return AVERROR(ENOMEM); | |
| 45 | + | |
| 46 | + s->frame = av_frame_alloc(); | |
| 47 | + if (!s->frame) | |
| 48 | + return AVERROR(ENOMEM); | |
| 49 | + | |
| 50 | + s->nb_context = avctx->ch_layout.nb_channels; | |
| 51 | + | |
| 52 | + codec = avcodec_find_decoder(AV_CODEC_ID_AAC); | |
| 53 | + if (!codec) | |
| 54 | + return AVERROR_BUG; | |
| 55 | + | |
| 56 | + for (int i = 0; i < s->nb_context; i++) { | |
| 57 | + s->aac_avctx[i] = avcodec_alloc_context3(codec); | |
| 58 | + if (!s->aac_avctx[i]) | |
| 59 | + return AVERROR(ENOMEM); | |
| 60 | + ret = avcodec_open2(s->aac_avctx[i], codec, NULL); | |
| 61 | + if (ret < 0) | |
| 62 | + return ret; | |
| 63 | + } | |
| 64 | + | |
| 65 | + avctx->sample_fmt = s->aac_avctx[0]->sample_fmt; | |
| 66 | + if (!av_sample_fmt_is_planar(avctx->sample_fmt)) | |
| 67 | + return AVERROR(EINVAL); | |
| 68 | + | |
| 69 | + return 0; | |
| 70 | +} | |
| 71 | + | |
| 72 | +static int ftr_decode_frame(AVCodecContext *avctx, AVFrame *frame, | |
| 73 | + int *got_frame, AVPacket *avpkt) | |
| 74 | +{ | |
| 75 | + FTRContext *s = avctx->priv_data; | |
| 76 | + GetBitContext gb; | |
| 77 | + int ret, ch_offset = 0; | |
| 78 | + | |
| 79 | + ret = init_get_bits8(&gb, avpkt->data, avpkt->size); | |
| 80 | + if (ret < 0) | |
| 81 | + return ret; | |
| 82 | + | |
| 83 | + frame->nb_samples = 0; | |
| 84 | + | |
| 85 | + for (int i = 0; i < s->nb_context; i++) { | |
| 86 | + AVCodecContext *codec_avctx = s->aac_avctx[i]; | |
| 87 | + GetBitContext gb2 = gb; | |
| 88 | + AACADTSHeaderInfo hdr_info; | |
| 89 | + int size; | |
| 90 | + | |
| 91 | + if (get_bits_left(&gb) < 64) | |
| 92 | + return AVERROR_INVALIDDATA; | |
| 93 | + | |
| 94 | + memset(&hdr_info, 0, sizeof(hdr_info)); | |
| 95 | + | |
| 96 | + size = ff_adts_header_parse(&gb2, &hdr_info); | |
| 97 | + if (size <= 0 || size * 8 > get_bits_left(&gb)) | |
| 98 | + return AVERROR_INVALIDDATA; | |
| 99 | + | |
| 100 | + if (size > s->packet->size) { | |
| 101 | + ret = av_grow_packet(s->packet, size - s->packet->size); | |
| 102 | + if (ret < 0) | |
| 103 | + return ret; | |
| 104 | + } | |
| 105 | + | |
| 106 | + ret = av_packet_make_writable(s->packet); | |
| 107 | + if (ret < 0) | |
| 108 | + return ret; | |
| 109 | + | |
| 110 | + memcpy(s->packet->data, avpkt->data + (get_bits_count(&gb) >> 3), size); | |
| 111 | + s->packet->size = size; | |
| 112 | + | |
| 113 | + if (size > 12) { | |
| 114 | + uint8_t *buf = s->packet->data; | |
| 115 | + | |
| 116 | + if (buf[3] & 0x20) { | |
| 117 | + int tmp = buf[8]; | |
| 118 | + buf[ 9] = ~buf[9]; | |
| 119 | + buf[11] = ~buf[11]; | |
| 120 | + buf[12] = ~buf[12]; | |
| 121 | + buf[ 8] = ~buf[10]; | |
| 122 | + buf[10] = ~tmp; | |
| 123 | + } | |
| 124 | + } | |
| 125 | + | |
| 126 | + ret = avcodec_send_packet(codec_avctx, s->packet); | |
| 127 | + if (ret < 0) { | |
| 128 | + av_log(avctx, AV_LOG_ERROR, "Error submitting a packet for decoding\n"); | |
| 129 | + return ret; | |
| 130 | + } | |
| 131 | + | |
| 132 | + ret = avcodec_receive_frame(codec_avctx, s->frame); | |
| 133 | + if (ret < 0) | |
| 134 | + return ret; | |
| 135 | + | |
| 136 | + if (!avctx->sample_rate) { | |
| 137 | + avctx->sample_rate = codec_avctx->sample_rate; | |
| 138 | + } else { | |
| 139 | + if (avctx->sample_rate != codec_avctx->sample_rate) | |
| 140 | + return AVERROR_INVALIDDATA; | |
| 141 | + } | |
| 142 | + | |
| 143 | + if (!frame->nb_samples) { | |
| 144 | + frame->nb_samples = s->frame->nb_samples; | |
| 145 | + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) | |
| 146 | + return ret; | |
| 147 | + } else { | |
| 148 | + if (frame->nb_samples != s->frame->nb_samples) | |
| 149 | + return AVERROR_INVALIDDATA; | |
| 150 | + } | |
| 151 | + | |
| 152 | + skip_bits_long(&gb, size * 8); | |
| 153 | + | |
| 154 | + if (ch_offset + s->frame->ch_layout.nb_channels > avctx->ch_layout.nb_channels) | |
| 155 | + return AVERROR_INVALIDDATA; | |
| 156 | + | |
| 157 | + if (avctx->sample_fmt != codec_avctx->sample_fmt) | |
| 158 | + return AVERROR_INVALIDDATA; | |
| 159 | + | |
| 160 | + for (int ch = 0; ch < s->frame->ch_layout.nb_channels; ch++) | |
| 161 | + memcpy(frame->extended_data[ch_offset + ch], | |
| 162 | + s->frame->extended_data[ch], | |
| 163 | + av_get_bytes_per_sample(codec_avctx->sample_fmt) * s->frame->nb_samples); | |
| 164 | + | |
| 165 | + ch_offset += s->frame->ch_layout.nb_channels; | |
| 166 | + | |
| 167 | + if (ch_offset >= avctx->ch_layout.nb_channels) | |
| 168 | + break; | |
| 169 | + } | |
| 170 | + | |
| 171 | + *got_frame = 1; | |
| 172 | + | |
| 173 | + return get_bits_count(&gb) >> 3; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static void ftr_flush(AVCodecContext *avctx) | |
| 177 | +{ | |
| 178 | + FTRContext *s = avctx->priv_data; | |
| 179 | + | |
| 180 | + for (int i = 0; i < s->nb_context; i++) | |
| 181 | + avcodec_flush_buffers(s->aac_avctx[i]); | |
| 182 | +} | |
| 183 | + | |
| 184 | +static av_cold int ftr_close(AVCodecContext *avctx) | |
| 185 | +{ | |
| 186 | + FTRContext *s = avctx->priv_data; | |
| 187 | + | |
| 188 | + for (int i = 0; i < s->nb_context; i++) | |
| 189 | + avcodec_free_context(&s->aac_avctx[i]); | |
| 190 | + av_packet_free(&s->packet); | |
| 191 | + av_frame_free(&s->frame); | |
| 192 | + | |
| 193 | + return 0; | |
| 194 | +} | |
| 195 | + | |
| 196 | +const FFCodec ff_ftr_decoder = { | |
| 197 | + .p.name = "ftr", | |
| 198 | + .p.long_name = NULL_IF_CONFIG_SMALL("FTR Voice"), | |
| 199 | + .p.type = AVMEDIA_TYPE_AUDIO, | |
| 200 | + .p.id = AV_CODEC_ID_FTR, | |
| 201 | + .init = ftr_init, | |
| 202 | + FF_CODEC_DECODE_CB(ftr_decode_frame), | |
| 203 | + .close = ftr_close, | |
| 204 | + .flush = ftr_flush, | |
| 205 | + .priv_data_size = sizeof(FTRContext), | |
| 206 | + .p.capabilities = AV_CODEC_CAP_SUBFRAMES | AV_CODEC_CAP_DR1, | |
| 207 | + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | |
| 208 | +}; | |
| @@ -0,0 +1,107 @@ | ||
| 1 | +/* | |
| 2 | + * FTR parser | |
| 3 | + * Copyright (c) 2022 Paul B Mahol | |
| 4 | + * | |
| 5 | + * This file is part of FFmpeg. | |
| 6 | + * | |
| 7 | + * FFmpeg is free software; you can redistribute it and/or | |
| 8 | + * modify it under the terms of the GNU Lesser General Public | |
| 9 | + * License as published by the Free Software Foundation; either | |
| 10 | + * version 2.1 of the License, or (at your option) any later version. | |
| 11 | + * | |
| 12 | + * FFmpeg is distributed in the hope that it will be useful, | |
| 13 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 14 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 15 | + * Lesser General Public License for more details. | |
| 16 | + * | |
| 17 | + * You should have received a copy of the GNU Lesser General Public | |
| 18 | + * License along with FFmpeg; if not, write to the Free Software | |
| 19 | + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 | + */ | |
| 21 | + | |
| 22 | +/** | |
| 23 | + * @file | |
| 24 | + * FTR parser | |
| 25 | + */ | |
| 26 | + | |
| 27 | +#include "parser.h" | |
| 28 | +#include "get_bits.h" | |
| 29 | +#include "adts_header.h" | |
| 30 | +#include "adts_parser.h" | |
| 31 | +#include "mpeg4audio.h" | |
| 32 | + | |
| 33 | +typedef struct FTRParseContext { | |
| 34 | + ParseContext pc; | |
| 35 | + int skip; | |
| 36 | + int split; | |
| 37 | + int frame_index; | |
| 38 | +} FTRParseContext; | |
| 39 | + | |
| 40 | +static int ftr_parse(AVCodecParserContext *s, AVCodecContext *avctx, | |
| 41 | + const uint8_t **poutbuf, int *poutbuf_size, | |
| 42 | + const uint8_t *buf, int buf_size) | |
| 43 | +{ | |
| 44 | + uint8_t tmp[8 + AV_INPUT_BUFFER_PADDING_SIZE]; | |
| 45 | + FTRParseContext *ftr = s->priv_data; | |
| 46 | + uint64_t state = ftr->pc.state64; | |
| 47 | + int next = END_NOT_FOUND; | |
| 48 | + GetBitContext bits; | |
| 49 | + AACADTSHeaderInfo hdr; | |
| 50 | + int size; | |
| 51 | + | |
| 52 | + *poutbuf_size = 0; | |
| 53 | + *poutbuf = NULL; | |
| 54 | + | |
| 55 | + if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { | |
| 56 | + next = buf_size; | |
| 57 | + } else { | |
| 58 | + for (int i = 0; i < buf_size; i++) { | |
| 59 | + if (ftr->skip > 0) { | |
| 60 | + ftr->skip--; | |
| 61 | + if (ftr->skip == 0 && ftr->split) { | |
| 62 | + ftr->split = 0; | |
| 63 | + next = i; | |
| 64 | + s->duration = 1024; | |
| 65 | + s->key_frame = 1; | |
| 66 | + break; | |
| 67 | + } else if (ftr->skip > 0) { | |
| 68 | + continue; | |
| 69 | + } | |
| 70 | + } | |
| 71 | + | |
| 72 | + state = (state << 8) | buf[i]; | |
| 73 | + AV_WB64(tmp, state); | |
| 74 | + init_get_bits(&bits, tmp + 8 - AV_AAC_ADTS_HEADER_SIZE, | |
| 75 | + AV_AAC_ADTS_HEADER_SIZE * 8); | |
| 76 | + | |
| 77 | + if ((size = ff_adts_header_parse(&bits, &hdr)) > 0) { | |
| 78 | + ftr->skip = size - 6; | |
| 79 | + ftr->frame_index += ff_mpeg4audio_channels[hdr.chan_config]; | |
| 80 | + if (ftr->frame_index >= avctx->ch_layout.nb_channels) { | |
| 81 | + ftr->frame_index = 0; | |
| 82 | + ftr->split = 1; | |
| 83 | + } | |
| 84 | + } | |
| 85 | + } | |
| 86 | + | |
| 87 | + ftr->pc.state64 = state; | |
| 88 | + | |
| 89 | + if (ff_combine_frame(&ftr->pc, next, &buf, &buf_size) < 0) { | |
| 90 | + *poutbuf = NULL; | |
| 91 | + *poutbuf_size = 0; | |
| 92 | + return buf_size; | |
| 93 | + } | |
| 94 | + } | |
| 95 | + | |
| 96 | + *poutbuf = buf; | |
| 97 | + *poutbuf_size = buf_size; | |
| 98 | + | |
| 99 | + return next; | |
| 100 | +} | |
| 101 | + | |
| 102 | +const AVCodecParser ff_ftr_parser = { | |
| 103 | + .codec_ids = { AV_CODEC_ID_FTR }, | |
| 104 | + .priv_data_size = sizeof(FTRParseContext), | |
| 105 | + .parser_parse = ftr_parse, | |
| 106 | + .parser_close = ff_parse_close, | |
| 107 | +}; | |
| @@ -42,6 +42,7 @@ extern const AVCodecParser ff_dvbsub_parser; · 41 unmodified lines | ||
| 42 | 42 | extern const AVCodecParser ff_dvdsub_parser; |
| 43 | 43 | extern const AVCodecParser ff_dvd_nav_parser; |
| 44 | 44 | extern const AVCodecParser ff_flac_parser; |
| 45 | +extern const AVCodecParser ff_ftr_parser; | |
| 45 | 46 | extern const AVCodecParser ff_g723_1_parser; |
| 46 | 47 | extern const AVCodecParser ff_g729_parser; |
| 47 | 48 | extern const AVCodecParser ff_gif_parser; |
| @@ -639,6 +639,7 @@ static int get_audio_frame_duration(enum AVCodecID id, int sr, int ch, int ba, · 638 unmodified lines | ||
| 639 | 639 | case AV_CODEC_ID_MP2: |
| 640 | 640 | case AV_CODEC_ID_MUSEPACK7: return 1152; |
| 641 | 641 | case AV_CODEC_ID_AC3: return 1536; |
| 642 | + case AV_CODEC_ID_FTR: return 1024; | |
| 642 | 643 | } |
| 643 | 644 | |
| 644 | 645 | if (sr > 0) { |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | |
| 30 | 30 | #include "version_major.h" |
| 31 | 31 | |
| 32 | −#define LIBAVCODEC_VERSION_MINOR 45 | |
| 32 | +#define LIBAVCODEC_VERSION_MINOR 46 | |
| 33 | 33 | #define LIBAVCODEC_VERSION_MICRO 100 |
| 34 | 34 | |
| 35 | 35 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |
| @@ -923,6 +923,7 @@ static int avi_read_header(AVFormatContext *s) · 922 unmodified lines | ||
| 923 | 923 | ast->dshow_block_align = 0; |
| 924 | 924 | } |
| 925 | 925 | if ((st->codecpar->codec_id == AV_CODEC_ID_AAC || |
| 926 | + st->codecpar->codec_id == AV_CODEC_ID_FTR || | |
| 926 | 927 | st->codecpar->codec_id == AV_CODEC_ID_FLAC || |
| 927 | 928 | st->codecpar->codec_id == AV_CODEC_ID_MP2 ) && ast->dshow_block_align <= 4 && ast->dshow_block_align) { |
| 928 | 929 | av_log(s, AV_LOG_DEBUG, "overriding invalid dshow_block_align of %d\n", ast->dshow_block_align); |
| @@ -558,6 +558,7 @@ const AVCodecTag ff_codec_wav_tags[] = { · 557 unmodified lines | ||
| 558 | 558 | { AV_CODEC_ID_WMALOSSLESS, 0x0163 }, |
| 559 | 559 | { AV_CODEC_ID_XMA1, 0x0165 }, |
| 560 | 560 | { AV_CODEC_ID_XMA2, 0x0166 }, |
| 561 | + { AV_CODEC_ID_FTR, 0x0180 }, | |
| 561 | 562 | { AV_CODEC_ID_ADPCM_CT, 0x0200 }, |
| 562 | 563 | { AV_CODEC_ID_DVAUDIO, 0x0215 }, |
| 563 | 564 | { AV_CODEC_ID_DVAUDIO, 0x0216 }, |
| @@ -584,8 +585,10 @@ const AVCodecTag ff_codec_wav_tags[] = { · 20 unmodified lines | ||
| 584 | 585 | { AV_CODEC_ID_PCM_MULAW, 0x6c75 }, |
| 585 | 586 | { AV_CODEC_ID_AAC, 0x706d }, |
| 586 | 587 | { AV_CODEC_ID_AAC, 0x4143 }, |
| 588 | + { AV_CODEC_ID_FTR, 0x4180 }, | |
| 587 | 589 | { AV_CODEC_ID_XAN_DPCM, 0x594a }, |
| 588 | 590 | { AV_CODEC_ID_G729, 0x729A }, |
| 591 | + { AV_CODEC_ID_FTR, 0x8180 }, | |
| 589 | 592 | { AV_CODEC_ID_G723_1, 0xA100 }, /* Comverse Infosys Ltd. G723 1 */ |
| 590 | 593 | { AV_CODEC_ID_AAC, 0xA106 }, |
| 591 | 594 | { AV_CODEC_ID_SPEEX, 0xA109 }, |