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"
25 #include "libavutil/opt.h"
26 #include "codec_internal.h"
29 #include "codec2utils.h"
37 static const AVOption options
[] = {
38 //not AV_OPT_FLAG_DECODING_PARAM since mode should come from the demuxer
39 //1300 (aka FreeDV 1600) is the most common mode on-the-air, default to it here as well
40 CODEC2_AVOPTIONS("codec2 mode", LibCodec2Context
, 0, 4 /*CODEC2_MODE_1300*/, AV_OPT_FLAG_AUDIO_PARAM
|AV_OPT_FLAG_ENCODING_PARAM
),
44 static const AVClass libcodec2_enc_class
= {
45 .class_name
= "libcodec2 encoder",
46 .item_name
= av_default_item_name
,
48 .version
= LIBAVUTIL_VERSION_INT
,
51 static av_cold
int libcodec2_init_common(AVCodecContext
*avctx
, int mode
)
53 LibCodec2Context
*c2
= avctx
->priv_data
;
54 //Grab mode name from options, unless it's some weird number.
55 const char *modename
= mode
>= 0 && mode
<= CODEC2_MODE_MAX
? options
[mode
+1].name
: "?";
57 c2
->codec
= codec2_create(mode
);
59 //Out of memory or unsupported mode. The latter seems most likely,
60 //but we can't tell for sure with the current API.
61 goto libcodec2_init_common_error
;
64 avctx
->frame_size
= codec2_samples_per_frame(c2
->codec
);
65 avctx
->block_align
= (codec2_bits_per_frame(c2
->codec
) + 7) / 8;
67 if (avctx
->frame_size
<= 0 || avctx
->block_align
<= 0) {
68 //codec2_create() may succeed for some modes but still fail at codec2_samples_per_frame()
69 //example is -mode 700C on libcodec2 0.4
70 codec2_destroy(c2
->codec
);
72 goto libcodec2_init_common_error
;
75 codec2_set_natural_or_gray(c2
->codec
, 1);
79 libcodec2_init_common_error
:
80 av_log(avctx
, AV_LOG_ERROR
,
81 "Mode %i (%s) not supported with the linked version of libcodec2\n",
83 return AVERROR(EINVAL
);
86 static av_cold
int libcodec2_init_decoder(AVCodecContext
*avctx
)
88 avctx
->sample_rate
= 8000;
89 avctx
->sample_fmt
= AV_SAMPLE_FMT_S16
;
90 av_channel_layout_uninit(&avctx
->ch_layout
);
91 avctx
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
93 if (avctx
->extradata_size
!= CODEC2_EXTRADATA_SIZE
) {
94 av_log(avctx
, AV_LOG_ERROR
, "must have exactly %i bytes of extradata (got %i)\n",
95 CODEC2_EXTRADATA_SIZE
, avctx
->extradata_size
);
96 return AVERROR_INVALIDDATA
;
99 return libcodec2_init_common(avctx
, codec2_mode_from_extradata(avctx
->extradata
));
102 static av_cold
int libcodec2_init_encoder(AVCodecContext
*avctx
)
104 LibCodec2Context
*c2
= avctx
->priv_data
;
106 //will need to be smarter once we get wideband support
107 if (avctx
->sample_rate
!= 8000 ||
108 avctx
->ch_layout
.nb_channels
!= 1 ||
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 .p
.long_name
= NULL_IF_CONFIG_SMALL("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 .p
.supported_samplerates
= (const int[]){ 8000, 0 },
186 .p
.sample_fmts
= (const enum AVSampleFormat
[]) { AV_SAMPLE_FMT_S16
, AV_SAMPLE_FMT_NONE
},
187 .p
.ch_layouts
= (const AVChannelLayout
[]) { AV_CHANNEL_LAYOUT_MONO
, { 0 } },
188 .priv_data_size
= sizeof(LibCodec2Context
),
189 .init
= libcodec2_init_decoder
,
190 .close
= libcodec2_close
,
191 FF_CODEC_DECODE_CB(libcodec2_decode
),
192 #if FF_API_OLD_CHANNEL_LAYOUT
193 .p
.channel_layouts
= (const uint64_t[]) { AV_CH_LAYOUT_MONO
, 0 },
197 const FFCodec ff_libcodec2_encoder
= {
198 .p
.name
= "libcodec2",
199 .p
.long_name
= NULL_IF_CONFIG_SMALL("codec2 encoder using libcodec2"),
200 .p
.type
= AVMEDIA_TYPE_AUDIO
,
201 .p
.id
= AV_CODEC_ID_CODEC2
,
202 .p
.capabilities
= AV_CODEC_CAP_DR1
,
203 .p
.supported_samplerates
= (const int[]){ 8000, 0 },
204 .p
.sample_fmts
= (const enum AVSampleFormat
[]) { AV_SAMPLE_FMT_S16
, AV_SAMPLE_FMT_NONE
},
205 .p
.ch_layouts
= (const AVChannelLayout
[]) { AV_CHANNEL_LAYOUT_MONO
, { 0 } },
206 .p
.priv_class
= &libcodec2_enc_class
,
207 .priv_data_size
= sizeof(LibCodec2Context
),
208 .init
= libcodec2_init_encoder
,
209 .close
= libcodec2_close
,
210 FF_CODEC_ENCODE_CB(libcodec2_encode
),
211 #if FF_API_OLD_CHANNEL_LAYOUT
212 .p
.channel_layouts
= (const uint64_t[]) { AV_CH_LAYOUT_MONO
, 0 },