2 * LC3 muxer and demuxer
3 * Copyright (C) 2024 Antoine Soulier <asoulier@google.com>
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
24 * Based on the file format specified by :
26 * - Bluetooth SIG - Low Complexity Communication Codec Test Suite
27 * https://www.bluetooth.org/docman/handlers/downloaddoc.ashx?doc_id=502301
28 * 3.2.8.2 Reference LC3 Codec Bitstream Format
30 * - ETSI TI 103 634 V1.4.1 - Low Complexity Communication Codec plus
31 * https://www.etsi.org/deliver/etsi_ts/103600_103699/103634/01.04.01_60/ts_103634v010401p.pdf
32 * LC3plus conformance script package
35 #include "config_components.h"
37 #include "libavcodec/packet.h"
38 #include "libavutil/intreadwrite.h"
46 static int check_frame_length(void *avcl
, int srate_hz
, int frame_us
)
48 if (srate_hz
!= 8000 && srate_hz
!= 16000 && srate_hz
!= 24000 &&
49 srate_hz
!= 32000 && srate_hz
!= 48000 && srate_hz
!= 96000) {
51 av_log(avcl
, AV_LOG_ERROR
,
52 "Invalid LC3 sample rate: %d Hz.\n", srate_hz
);
56 if (frame_us
!= 2500 && frame_us
!= 5000 &&
57 frame_us
!= 7500 && frame_us
!= 10000) {
59 av_log(avcl
, AV_LOG_ERROR
,
60 "Invalid LC3 frame duration: %.1f ms.\n", frame_us
/ 1000.f
);
67 #if CONFIG_LC3_DEMUXER
69 typedef struct LC3DemuxContext
{
74 static int lc3_read_probe(const AVProbeData
*p
)
76 int frame_us
, srate_hz
;
81 if (AV_RB16(p
->buf
+ 0) != 0x1ccc ||
82 AV_RL16(p
->buf
+ 2) < 9 * sizeof(uint16_t))
85 srate_hz
= AV_RL16(p
->buf
+ 4) * 100;
86 frame_us
= AV_RL16(p
->buf
+ 10) * 10;
87 if (check_frame_length(NULL
, srate_hz
, frame_us
) < 0)
90 return AVPROBE_SCORE_MAX
;
93 static int lc3_read_header(AVFormatContext
*s
)
95 LC3DemuxContext
*lc3
= s
->priv_data
;
97 uint16_t tag
, hdr_size
;
99 int srate_hz
, frame_us
, channels
, bit_rate
;
100 int ep_mode
, hr_mode
;
101 int num_extra_params
;
104 tag
= avio_rb16(s
->pb
);
105 hdr_size
= avio_rl16(s
->pb
);
107 if (tag
!= 0x1ccc || hdr_size
< 9 * sizeof(uint16_t))
108 return AVERROR_INVALIDDATA
;
110 num_extra_params
= hdr_size
/ sizeof(uint16_t) - 9;
112 srate_hz
= avio_rl16(s
->pb
) * 100;
113 bit_rate
= avio_rl16(s
->pb
) * 100;
114 channels
= avio_rl16(s
->pb
);
115 frame_us
= avio_rl16(s
->pb
) * 10;
116 ep_mode
= avio_rl16(s
->pb
) != 0;
117 length
= avio_rl32(s
->pb
);
118 hr_mode
= num_extra_params
>= 1 && avio_rl16(s
->pb
);
120 if (check_frame_length(s
, srate_hz
, frame_us
) < 0)
121 return AVERROR_INVALIDDATA
;
123 st
= avformat_new_stream(s
, NULL
);
125 return AVERROR(ENOMEM
);
127 avpriv_set_pts_info(st
, 64, 1, srate_hz
);
128 avpriv_update_cur_dts(s
, st
, 0);
129 st
->duration
= length
;
131 st
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
132 st
->codecpar
->codec_id
= AV_CODEC_ID_LC3
;
133 st
->codecpar
->sample_rate
= srate_hz
;
134 st
->codecpar
->bit_rate
= bit_rate
;
135 st
->codecpar
->ch_layout
.nb_channels
= channels
;
137 if ((ret
= ff_alloc_extradata(st
->codecpar
, 6)) < 0)
140 AV_WL16(st
->codecpar
->extradata
+ 0, frame_us
/ 10);
141 AV_WL16(st
->codecpar
->extradata
+ 2, ep_mode
);
142 AV_WL16(st
->codecpar
->extradata
+ 4, hr_mode
);
144 lc3
->frame_samples
= av_rescale(frame_us
, srate_hz
, 1000*1000);
146 delay
= av_rescale(frame_us
== 7500 ? 4000 : 2500, srate_hz
, 1000*1000);
147 lc3
->end_dts
= length
? length
+ delay
: -1;
152 static int lc3_read_packet(AVFormatContext
*s
, AVPacket
*pkt
)
154 LC3DemuxContext
*lc3
= s
->priv_data
;
155 AVStream
*st
= s
->streams
[0];
156 AVIOContext
*pb
= s
->pb
;
157 int64_t pos
= avio_tell(pb
);
158 int64_t remaining_samples
;
161 ret
= av_get_packet(s
->pb
, pkt
, avio_rl16(pb
));
167 remaining_samples
= lc3
->end_dts
< 0 ? lc3
->frame_samples
:
168 FFMAX(lc3
->end_dts
- ffstream(st
)->cur_dts
, 0);
169 pkt
->duration
= FFMIN(lc3
->frame_samples
, remaining_samples
);
174 const FFInputFormat ff_lc3_demuxer
= {
176 .p
.long_name
= NULL_IF_CONFIG_SMALL("LC3 (Low Complexity Communication Codec)"),
177 .p
.extensions
= "lc3",
178 .p
.flags
= AVFMT_GENERIC_INDEX
,
179 .priv_data_size
= sizeof(LC3DemuxContext
),
180 .read_probe
= lc3_read_probe
,
181 .read_header
= lc3_read_header
,
182 .read_packet
= lc3_read_packet
,
185 #endif /* CONFIG_LC3_DEMUXER */
189 static int lc3_write_header(AVFormatContext
*s
)
191 AVStream
*st
= s
->streams
[0];
192 int channels
= st
->codecpar
->ch_layout
.nb_channels
;
193 int srate_hz
= st
->codecpar
->sample_rate
;
194 int bit_rate
= st
->codecpar
->bit_rate
;
195 int frame_us
, ep_mode
, hr_mode
;
196 uint32_t nb_samples
= av_rescale_q(
197 st
->duration
, st
->time_base
, (AVRational
){ 1, srate_hz
});
199 if (st
->codecpar
->extradata_size
< 6)
200 return AVERROR_INVALIDDATA
;
202 frame_us
= AV_RL16(st
->codecpar
->extradata
+ 0) * 10;
203 ep_mode
= AV_RL16(st
->codecpar
->extradata
+ 2) != 0;
204 hr_mode
= AV_RL16(st
->codecpar
->extradata
+ 4) != 0;
206 if (check_frame_length(s
, srate_hz
, frame_us
) < 0)
207 return AVERROR_INVALIDDATA
;
209 avio_wb16(s
->pb
, 0x1ccc);
210 avio_wl16(s
->pb
, (9 + hr_mode
) * sizeof(uint16_t));
211 avio_wl16(s
->pb
, srate_hz
/ 100);
212 avio_wl16(s
->pb
, bit_rate
/ 100);
213 avio_wl16(s
->pb
, channels
);
214 avio_wl16(s
->pb
, frame_us
/ 10);
215 avio_wl16(s
->pb
, ep_mode
);
216 avio_wl32(s
->pb
, nb_samples
);
218 avio_wl16(s
->pb
, hr_mode
);
223 static int lc3_write_packet(AVFormatContext
*s
, AVPacket
*pkt
)
225 avio_wl16(s
->pb
, pkt
->size
);
226 avio_write(s
->pb
, pkt
->data
, pkt
->size
);
230 const FFOutputFormat ff_lc3_muxer
= {
232 .p
.long_name
= NULL_IF_CONFIG_SMALL("LC3 (Low Complexity Communication Codec)"),
233 .p
.extensions
= "lc3",
234 .p
.audio_codec
= AV_CODEC_ID_LC3
,
235 .p
.video_codec
= AV_CODEC_ID_NONE
,
236 .p
.subtitle_codec
= AV_CODEC_ID_NONE
,
237 .p
.flags
= AVFMT_NOTIMESTAMPS
,
238 .flags_internal
= FF_OFMT_FLAG_MAX_ONE_OF_EACH
|
239 FF_OFMT_FLAG_ONLY_DEFAULT_CODECS
,
240 .write_header
= lc3_write_header
,
241 .write_packet
= lc3_write_packet
,
244 #endif /* CONFIG_LC3_MUXER */