FFmpeg
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 
22 #include "libavutil/intreadwrite.h"
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 
33 typedef struct LibLC3EncOpts {
35  int hr_mode;
37 
38 typedef struct LibLC3EncContext {
39  const AVClass *av_class;
42  void *encoder_mem;
43  lc3_encoder_t encoder[ENCODER_MAX_CHANNELS];
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)
91  av_log(avctx, AV_LOG_WARNING,
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  void *zero_frame = NULL;
141  uint8_t *data_ptr;
142  int ret;
143 
144  if ((ret = ff_get_encode_buffer(avctx, pkt, block_bytes, 0)) < 0)
145  return ret;
146 
147  if (frame) {
148  int padding = frame->nb_samples - frame->duration;
149  liblc3->remaining_samples = FFMAX(liblc3->delay_samples - padding, 0);
150  } else {
151  if (!liblc3->remaining_samples)
152  return 0;
153 
154  liblc3->remaining_samples = 0;
155  zero_frame = av_mallocz(avctx->frame_size * sizeof(float));
156  if (!zero_frame)
157  return AVERROR(ENOMEM);
158  }
159 
160  data_ptr = pkt->data;
161  for (int ch = 0; ch < channels; ch++) {
162  const float *pcm = zero_frame ? zero_frame : frame->data[ch];
163  int nbytes = block_bytes / channels + (ch < block_bytes % channels);
164 
165  lc3_encode(liblc3->encoder[ch],
166  LC3_PCM_FORMAT_FLOAT, pcm, 1, nbytes, data_ptr);
167 
168  data_ptr += nbytes;
169  }
170 
171  if (zero_frame)
172  av_free(zero_frame);
173 
174  *got_packet_ptr = 1;
175 
176  return 0;
177 }
178 
179 #define OFFSET(x) offsetof(LibLC3EncContext, opts.x)
180 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
181 static const AVOption options[] = {
182  { "frame_duration", "Duration of a frame in milliseconds",
183  OFFSET(frame_duration), AV_OPT_TYPE_FLOAT,
184  { .dbl = 10.0 }, 2.5, 10.0, FLAGS },
185  { "high_resolution", "Enable High-Resolution mode (48 KHz or 96 KHz)",
186  OFFSET(hr_mode), AV_OPT_TYPE_BOOL,
187  { .i64 = 0 }, 0, 1, FLAGS },
188  { NULL }
189 };
190 
191 static const AVClass class = {
192  .class_name = "liblc3 encoder",
193  .item_name = av_default_item_name,
194  .option = options,
196 };
197 
199  .p.name = "liblc3",
200  CODEC_LONG_NAME("LC3 (Low Complexity Communication Codec)"),
201  .p.type = AVMEDIA_TYPE_AUDIO,
202  .p.id = AV_CODEC_ID_LC3,
203  .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
204  .p.supported_samplerates = (const int [])
205  { 96000, 48000, 32000, 24000, 16000, 8000, 0 },
206  .p.sample_fmts = (const enum AVSampleFormat[])
208  .p.priv_class = &class,
209  .p.wrapper_name = "liblc3",
210  .priv_data_size = sizeof(LibLC3EncContext),
212  .close = liblc3_encode_close,
214 };
AVCodecContext::frame_size
int frame_size
Number of samples per channel in an audio frame.
Definition: avcodec.h:1077
AV_SAMPLE_FMT_FLTP
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition: samplefmt.h:66
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
AVCodecContext::sample_rate
int sample_rate
samples per second
Definition: avcodec.h:1050
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:374
AVPacket::data
uint8_t * data
Definition: packet.h:520
AVOption
AVOption.
Definition: opt.h:357
encode.h
LibLC3EncContext::encoder_mem
void * encoder_mem
Definition: liblc3enc.c:42
FFCodec
Definition: codec_internal.h:126
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
LibLC3EncContext
Definition: liblc3enc.c:38
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:321
LibLC3EncContext::opts
LibLC3EncOpts opts
Definition: liblc3enc.c:40
FFCodec::p
AVCodec p
The public AVCodec.
Definition: codec_internal.h:130
AVCodecContext::ch_layout
AVChannelLayout ch_layout
Audio channel layout.
Definition: avcodec.h:1065
LibLC3EncContext::encoder
lc3_encoder_t encoder[ENCODER_MAX_CHANNELS]
Definition: liblc3enc.c:43
options
static const AVOption options[]
Definition: liblc3enc.c:181
AV_CODEC_ID_LC3
@ AV_CODEC_ID_LC3
Definition: codec_id.h:546
FF_CODEC_ENCODE_CB
#define FF_CODEC_ENCODE_CB(func)
Definition: codec_internal.h:295
codec.h
LibLC3EncContext::remaining_samples
int remaining_samples
Definition: liblc3enc.c:45
FLAGS
#define FLAGS
Definition: liblc3enc.c:180
pkt
AVPacket * pkt
Definition: movenc.c:60
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
av_cold
#define av_cold
Definition: attributes.h:90
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:524
intreadwrite.h
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
liblc3_encode_init
static av_cold int liblc3_encode_init(AVCodecContext *avctx)
Definition: liblc3enc.c:48
channels
channels
Definition: aptx.h:31
ENCODER_MAX_CHANNELS
#define ENCODER_MAX_CHANNELS
Definition: liblc3enc.c:31
CODEC_LONG_NAME
#define CODEC_LONG_NAME(str)
Definition: codec_internal.h:271
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
liblc3_encode_close
static av_cold int liblc3_encode_close(AVCodecContext *avctx)
Definition: liblc3enc.c:125
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
NULL
#define NULL
Definition: coverity.c:32
AVCodecContext::bit_rate
int64_t bit_rate
the average bitrate
Definition: avcodec.h:495
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
LibLC3EncContext::av_class
const AVClass * av_class
Definition: liblc3enc.c:39
f
f
Definition: af_crystalizer.c:121
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:366
AV_CODEC_CAP_DR1
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition: codec.h:52
codec_internal.h
OFFSET
#define OFFSET(x)
Definition: liblc3enc.c:179
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
LibLC3EncOpts
Definition: liblc3enc.c:33
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Definition: opt.h:248
LibLC3EncContext::block_bytes
int block_bytes
Definition: liblc3enc.c:41
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:523
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
LibLC3EncOpts::frame_duration
float frame_duration
Definition: liblc3enc.c:34
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:194
av_rescale
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
avcodec.h
ret
ret
Definition: filter_design.txt:187
AVClass::class_name
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:71
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
AVCodecContext
main external API structure.
Definition: avcodec.h:445
ff_liblc3_encoder
const FFCodec ff_liblc3_encoder
Definition: liblc3enc.c:198
ff_get_encode_buffer
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_CODEC_CAP_DELAY
#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:76
mem.h
liblc3_encode
static int liblc3_encode(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet_ptr)
Definition: liblc3enc.c:134
LibLC3EncOpts::hr_mode
int hr_mode
Definition: liblc3enc.c:35
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AVPacket
This structure stores compressed data.
Definition: packet.h:497
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:472
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:261
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
LibLC3EncContext::delay_samples
int delay_samples
Definition: liblc3enc.c:44