FFmpeg
Loading...
Searching...
No Matches
liblc3enc.c
Go to the documentation of this file.
1/*
2 * LC3 encoder wrapper
3 * Copyright (C) 2024 Antoine Soulier <asoulier@google.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <lc3.h>
21
23#include "libavutil/opt.h"
24#include "libavutil/mem.h"
25
26#include "avcodec.h"
27#include "codec.h"
28#include "codec_internal.h"
29#include "encode.h"
30
31#define ENCODER_MAX_CHANNELS 2
32
33typedef struct LibLC3EncOpts {
37
47
49{
50 LibLC3EncContext *liblc3 = avctx->priv_data;
51 bool hr_mode = liblc3->opts.hr_mode;
52 int frame_us = liblc3->opts.frame_duration * 1000;
53 int srate_hz = avctx->sample_rate;
54 int channels = avctx->ch_layout.nb_channels;
55 int effective_bit_rate;
56 unsigned encoder_size;
57
58 if (frame_us != 2500 && frame_us != 5000 &&
59 frame_us != 7500 && frame_us != 10000 ) {
60 av_log(avctx, AV_LOG_ERROR,
61 "Unsupported frame duration %.1f ms.\n", frame_us / 1000.f);
62 return AVERROR(EINVAL);
63 }
65 av_log(avctx, AV_LOG_ERROR,
66 "Invalid number of channels %d. Max %d channels are accepted\n",
68 return AVERROR(EINVAL);
69 }
70
71 hr_mode |= srate_hz > 48000;
72 hr_mode &= srate_hz >= 48000;
73
74 if (frame_us == 7500 && hr_mode) {
75 av_log(avctx, AV_LOG_ERROR,
76 "High-resolution mode is not supported with 7.5 ms frames.\n");
77 return AVERROR(EINVAL);
78 }
79
80 av_log(avctx, AV_LOG_INFO, "Encoding %.1f ms frames.\n", frame_us / 1000.f);
81 if (hr_mode)
82 av_log(avctx, AV_LOG_INFO, "High-resolution mode is enabled.\n");
83
84 liblc3->block_bytes = lc3_hr_frame_block_bytes(
85 hr_mode, frame_us, srate_hz, channels, avctx->bit_rate);
86
87 effective_bit_rate = lc3_hr_resolve_bitrate(
88 hr_mode, frame_us, srate_hz, liblc3->block_bytes);
89
90 if (avctx->bit_rate != effective_bit_rate)
92 "Bitrate changed to %d bps.\n", effective_bit_rate);
93 avctx->bit_rate = effective_bit_rate;
94
95 encoder_size = lc3_hr_encoder_size(hr_mode, frame_us, srate_hz);
96 if (!encoder_size)
97 return AVERROR(EINVAL);
98
99 liblc3->encoder_mem = av_malloc_array(channels, encoder_size);
100 if (!liblc3->encoder_mem)
101 return AVERROR(ENOMEM);
102
103 for (int ch = 0; ch < channels; ch++) {
104 liblc3->encoder[ch] = lc3_hr_setup_encoder(
105 hr_mode, frame_us, srate_hz, 0,
106 (char *)liblc3->encoder_mem + ch * encoder_size);
107 }
108
110 if (!avctx->extradata)
111 return AVERROR(ENOMEM);
112
113 AV_WL16(avctx->extradata + 0, frame_us / 10);
114 AV_WL16(avctx->extradata + 2, 0);
115 AV_WL16(avctx->extradata + 4, hr_mode);
116 avctx->extradata_size = 6;
117
118 avctx->frame_size = av_rescale(frame_us, srate_hz, 1000*1000);
119 liblc3->delay_samples = lc3_hr_delay_samples(hr_mode, frame_us, srate_hz);
120 liblc3->remaining_samples = 0;
121
122 return 0;
123}
124
126{
127 LibLC3EncContext *liblc3 = avctx->priv_data;
128
129 av_freep(&liblc3->encoder_mem);
130
131 return 0;
132}
133
135 const AVFrame *frame, int *got_packet_ptr)
136{
137 LibLC3EncContext *liblc3 = avctx->priv_data;
138 int block_bytes = liblc3->block_bytes;
139 int channels = avctx->ch_layout.nb_channels;
140 uint8_t *data_ptr;
141 int ret;
142
143 if ((ret = ff_get_encode_buffer(avctx, pkt, block_bytes, 0)) < 0)
144 return ret;
145
146 if (frame) {
147 int padding = frame->nb_samples - frame->duration;
148 liblc3->remaining_samples = FFMAX(liblc3->delay_samples - padding, 0);
149 } else {
150 if (!liblc3->remaining_samples)
151 return 0;
152
153 liblc3->remaining_samples = 0;
154 }
155
156 int is_planar = avctx->sample_fmt == AV_SAMPLE_FMT_FLTP;
157
158 data_ptr = pkt->data;
159 for (int ch = 0; ch < channels; ch++) {
160 int nbytes = block_bytes / channels + (ch < block_bytes % channels);
161
162 const float *pcm = frame ?
163 (is_planar ? (const float*)frame->data[ch] :
164 (const float*)frame->data[0] + ch) :
165 (const float[]){ 0 };
166
167 int stride = frame ? (is_planar ? 1 : channels) : 0;
168
169 lc3_encode(liblc3->encoder[ch],
170 LC3_PCM_FORMAT_FLOAT, pcm, stride, nbytes, data_ptr);
171
172 data_ptr += nbytes;
173 }
174
175 *got_packet_ptr = 1;
176
177 return 0;
178}
179
180#define OFFSET(x) offsetof(LibLC3EncContext, opts.x)
181#define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
182static const AVOption options[] = {
183 { "frame_duration", "Duration of a frame in milliseconds",
184 OFFSET(frame_duration), AV_OPT_TYPE_FLOAT,
185 { .dbl = 10.0 }, 2.5, 10.0, FLAGS },
186 { "high_resolution", "Enable High-Resolution mode (48 KHz or 96 KHz)",
187 OFFSET(hr_mode), AV_OPT_TYPE_BOOL,
188 { .i64 = 0 }, 0, 1, FLAGS },
189 { NULL }
190};
191
192static const AVClass class = {
193 .class_name = "liblc3 encoder",
195 .option = options,
197};
198
200 .p.name = "liblc3",
201 CODEC_LONG_NAME("LC3 (Low Complexity Communication Codec)"),
202 .p.type = AVMEDIA_TYPE_AUDIO,
203 .p.id = AV_CODEC_ID_LC3,
204 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
205 .p.priv_class = &class,
206 .p.wrapper_name = "liblc3",
207 CODEC_SAMPLERATES(96000, 48000, 32000, 24000, 16000, 8000),
209 .priv_data_size = sizeof(LibLC3EncContext),
213};
const FFCodec ff_liblc3_encoder
Definition liblc3enc.c:199
channels
Definition aptx.h:31
static av_cold void close(AVCodecParserContext *s)
Definition apv_parser.c:197
Libavcodec external API header.
#define FLAGS
Definition cmdutils.c:598
#define CODEC_SAMPLERATES(...)
#define FF_CODEC_ENCODE_CB(func)
#define CODEC_LONG_NAME(str)
#define CODEC_SAMPLEFMTS(...)
#define NULL
Definition coverity.c:32
static AVPacket * pkt
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition encode.c:106
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition opt.h:326
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_LC3
Definition codec_id.h:559
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding.
Definition defs.h:40
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:241
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition samplefmt.h:66
@ AV_SAMPLE_FMT_FLT
float
Definition samplefmt.h:60
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define AV_WL16(p, v)
#define av_cold
Definition attributes.h:117
#define ENCODER_MAX_CHANNELS
Definition liblc3enc.c:31
static av_cold int liblc3_encode_close(AVCodecContext *avctx)
Definition liblc3enc.c:125
static int liblc3_encode(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr)
Definition liblc3enc.c:134
#define OFFSET(x)
Definition liblc3enc.c:180
static av_cold int liblc3_encode_init(AVCodecContext *avctx)
Definition liblc3enc.c:48
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
AVOptions.
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
Definition log.h:76
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition log.h:81
main external API structure.
Definition avcodec.h:443
AVChannelLayout ch_layout
Audio channel layout.
Definition avcodec.h:1055
enum AVSampleFormat sample_fmt
audio sample format
Definition avcodec.h:1047
int64_t bit_rate
the average bitrate
Definition avcodec.h:493
int sample_rate
samples per second
Definition avcodec.h:1040
uint8_t * extradata
Out-of-band global headers that may be used by some codecs.
Definition avcodec.h:526
int extradata_size
Definition avcodec.h:527
int frame_size
Number of samples per channel in an audio frame.
Definition avcodec.h:1068
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
This structure stores compressed data.
Definition packet.h:580
lc3_encoder_t encoder[ENCODER_MAX_CHANNELS]
Definition liblc3enc.c:43
LibLC3EncOpts opts
Definition liblc3enc.c:40
void * encoder_mem
Definition liblc3enc.c:42
const AVClass * av_class
Definition liblc3enc.c:39
float frame_duration
Definition liblc3enc.c:34
#define stride
#define av_malloc_array(a, b)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)