2 * codec2 encoder/decoder using libcodec2
3 * Copyright (c) 2017 Tomas Härdin
5 * This file is part of FFmpeg.
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.
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.
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
22 #include <codec2/codec2.h>
23 #include "libavutil/channel_layout.h"
24 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "codec_internal.h"
30 #include "codec2utils.h"
38 static const AVOption options
[] = {
39 //not AV_OPT_FLAG_DECODING_PARAM since mode should come from the demuxer
40 //1300 (aka FreeDV 1600) is the most common mode on-the-air, default to it here as well
41 CODEC2_AVOPTIONS("codec2 mode", LibCodec2Context
, 0, 4 /*CODEC2_MODE_1300*/, AV_OPT_FLAG_AUDIO_PARAM
|AV_OPT_FLAG_ENCODING_PARAM
),
45 static const AVClass libcodec2_enc_class
= {
46 .class_name
= "libcodec2 encoder",
47 .item_name
= av_default_item_name
,
49 .version
= LIBAVUTIL_VERSION_INT
,
52 static av_cold
int libcodec2_init_common(AVCodecContext
*avctx
, int mode
)
54 LibCodec2Context
*c2
= avctx
->priv_data
;
55 //Grab mode name from options, unless it's some weird number.
56 const char *modename
= mode
>= 0 && mode
<= CODEC2_MODE_MAX
? options
[mode
+1].name
: "?";
58 c2
->codec
= codec2_create(mode
);
60 //Out of memory or unsupported mode. The latter seems most likely,
61 //but we can't tell for sure with the current API.
62 goto libcodec2_init_common_error
;
65 avctx
->frame_size
= codec2_samples_per_frame(c2
->codec
);
66 avctx
->block_align
= (codec2_bits_per_frame(c2
->codec
) + 7) / 8;
68 if (avctx
->frame_size
<= 0 || avctx
->block_align
<= 0) {
69 //codec2_create() may succeed for some modes but still fail at codec2_samples_per_frame()
70 //example is -mode 700C on libcodec2 0.4
71 codec2_destroy(c2
->codec
);
73 goto libcodec2_init_common_error
;
76 codec2_set_natural_or_gray(c2
->codec
, 1);
80 libcodec2_init_common_error
:
81 av_log(avctx
, AV_LOG_ERROR
,
82 "Mode %i (%s) not supported with the linked version of libcodec2\n",
84 return AVERROR(EINVAL
);
87 static av_cold
int libcodec2_init_decoder(AVCodecContext
*avctx
)
89 avctx
->sample_rate
= 8000;
90 avctx
->sample_fmt
= AV_SAMPLE_FMT_S16
;
91 av_channel_layout_uninit(&avctx
->ch_layout
);
92 avctx
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
94 if (avctx
->extradata_size
!= CODEC2_EXTRADATA_SIZE
) {
95 av_log(avctx
, AV_LOG_ERROR
, "must have exactly %i bytes of extradata (got %i)\n",
96 CODEC2_EXTRADATA_SIZE
, avctx
->extradata_size
);
97 return AVERROR_INVALIDDATA
;
100 return libcodec2_init_common(avctx
, codec2_mode_from_extradata(avctx
->extradata
));
103 static av_cold
int libcodec2_init_encoder(AVCodecContext
*avctx
)
105 LibCodec2Context
*c2
= avctx
->priv_data
;
107 //will need to be smarter once we get wideband support
108 if (avctx
->sample_rate
!= 8000 ||
109 avctx
->sample_fmt
!= AV_SAMPLE_FMT_S16
) {
110 av_log(avctx
, AV_LOG_ERROR
, "only 8 kHz 16-bit mono allowed\n");
111 return AVERROR(EINVAL
);
114 avctx
->extradata
= av_mallocz(CODEC2_EXTRADATA_SIZE
+ AV_INPUT_BUFFER_PADDING_SIZE
);
115 if (!avctx
->extradata
) {
116 return AVERROR(ENOMEM
);
119 avctx
->extradata_size
= CODEC2_EXTRADATA_SIZE
;
120 codec2_make_extradata(avctx
->extradata
, c2
->mode
);
122 return libcodec2_init_common(avctx
, c2
->mode
);
125 static av_cold
int libcodec2_close(AVCodecContext
*avctx
)
127 LibCodec2Context
*c2
= avctx
->priv_data
;
129 codec2_destroy(c2
->codec
);
133 static int libcodec2_decode(AVCodecContext
*avctx
, AVFrame
*frame
,
134 int *got_frame_ptr
, AVPacket
*pkt
)
136 LibCodec2Context
*c2
= avctx
->priv_data
;
138 const uint8_t *input
;
141 nframes
= pkt
->size
/ avctx
->block_align
;
142 frame
->nb_samples
= avctx
->frame_size
* nframes
;
144 ret
= ff_get_buffer(avctx
, frame
, 0);
150 output
= (int16_t *)frame
->data
[0];
152 for (i
= 0; i
< nframes
; i
++) {
153 codec2_decode(c2
->codec
, output
, input
);
154 input
+= avctx
->block_align
;
155 output
+= avctx
->frame_size
;
158 *got_frame_ptr
= nframes
> 0;
159 return nframes
* avctx
->block_align
;
162 static int libcodec2_encode(AVCodecContext
*avctx
, AVPacket
*avpkt
,
163 const AVFrame
*frame
, int *got_packet_ptr
)
165 LibCodec2Context
*c2
= avctx
->priv_data
;
166 int16_t *samples
= (int16_t *)frame
->data
[0];
168 int ret
= ff_get_encode_buffer(avctx
, avpkt
, avctx
->block_align
, 0);
173 codec2_encode(c2
->codec
, avpkt
->data
, samples
);
179 const FFCodec ff_libcodec2_decoder
= {
180 .p
.name
= "libcodec2",
181 CODEC_LONG_NAME("codec2 decoder using libcodec2"),
182 .p
.type
= AVMEDIA_TYPE_AUDIO
,
183 .p
.id
= AV_CODEC_ID_CODEC2
,
184 .p
.capabilities
= AV_CODEC_CAP_CHANNEL_CONF
,
185 CODEC_SAMPLERATES(8000),
186 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16
),
187 CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO
),
188 .caps_internal
= FF_CODEC_CAP_NOT_INIT_THREADSAFE
,
189 .priv_data_size
= sizeof(LibCodec2Context
),
190 .init
= libcodec2_init_decoder
,
191 .close
= libcodec2_close
,
192 FF_CODEC_DECODE_CB(libcodec2_decode
),
195 const FFCodec ff_libcodec2_encoder
= {
196 .p
.name
= "libcodec2",
197 CODEC_LONG_NAME("codec2 encoder using libcodec2"),
198 .p
.type
= AVMEDIA_TYPE_AUDIO
,
199 .p
.id
= AV_CODEC_ID_CODEC2
,
200 .p
.capabilities
= AV_CODEC_CAP_DR1
|
201 AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
,
202 CODEC_SAMPLERATES(8000),
203 CODEC_SAMPLEFMTS(AV_SAMPLE_FMT_S16
),
204 CODEC_CH_LAYOUTS(AV_CHANNEL_LAYOUT_MONO
),
205 .p
.priv_class
= &libcodec2_enc_class
,
206 .caps_internal
= FF_CODEC_CAP_NOT_INIT_THREADSAFE
,
207 .priv_data_size
= sizeof(LibCodec2Context
),
208 .init
= libcodec2_init_encoder
,
209 .close
= libcodec2_close
,
210 FF_CODEC_ENCODE_CB(libcodec2_encode
),