vdr-plugin-softhddevice-drm-gles 1.6.4-d0291bb
codec_audio.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: AGPL-3.0-or-later
2
17#include <cstdint>
18#include <mutex>
19#include <unistd.h>
20
21extern "C" {
22#include <libavcodec/avcodec.h>
23}
24
25#include "audio.h"
26#include "codec_audio.h"
27#include "logger.h"
28#include "misc.h"
29
36 : m_pAudio(audio),
37 m_passthroughMask(m_pAudio->GetPassthrough() & (CODEC_AC3 | CODEC_EAC3 | CODEC_DTS))
38{
39 if (!(m_pFrame = av_frame_alloc()))
40 LOGFATAL("audiocodec: %s: can't allocate audio decoder frame buffer", __FUNCTION__);
41
42 LOGDEBUG2(L_CODEC, "audiocodec: %s: Set passthrough mask %d", __FUNCTION__, m_passthroughMask);
43}
44
51
62{
63 std::lock_guard<std::mutex> lock(m_mutex);
64
65 const AVCodec *codec;
66
67 m_codecId = codecId;
68
69 switch (codecId) {
70 case AV_CODEC_ID_AC3:
71 if (!(codec = avcodec_find_decoder_by_name("ac3_fixed")))
72 LOGFATAL("audiocodec: %s: codec ac3_fixed ID %#06x not found", __FUNCTION__, codecId);
73 break;
74 case AV_CODEC_ID_AAC:
75 if (!(codec = avcodec_find_decoder_by_name("aac_fixed")))
76 LOGFATAL("audiocodec: %s: codec aac_fixed ID %#06x not found", __FUNCTION__, codecId);
77 break;
78 default:
79 if (!(codec = avcodec_find_decoder(codecId))) {
80 LOGFATAL("audiocodec: %s: codec %s ID %#06x not found", __FUNCTION__,
81 avcodec_get_name(codecId), codecId);
82 }
83 break;
84 }
85
87 LOGFATAL("audiocodec: %s: can't allocate audio codec context", __FUNCTION__);
88
89 m_pAudioCtx->pkt_timebase = timebase;
90
92 LOGERROR("audiocodec: %s: insert parameters to context failed!", __FUNCTION__);
93
94 if (avcodec_open2(m_pAudioCtx, m_pAudioCtx->codec, NULL) < 0)
95 LOGFATAL("audiocodec: %s: can't open audio codec", __FUNCTION__);
96
97 LOGDEBUG2(L_CODEC, "audiocodec: %s: Codec %s found, passthrough mask %d", __FUNCTION__, m_pAudioCtx->codec->long_name, m_passthroughMask);
98
104}
105
110{
111 std::lock_guard<std::mutex> lock(m_mutex);
112
113 if (!m_pAudioCtx)
114 return;
115
116 LOGDEBUG2(L_CODEC, "audiocodec: %s", __FUNCTION__);
117
119
122}
123
140{
141 m_pAudio->SetTimebase(&m_pAudioCtx->pkt_timebase);
142
143 // AC3 passthrough
146 int spdifSize = AC3_FRAME_SIZE * 4; // frames * channels * (samplesize / 8)
147
148 if (spdifSize < avpkt->size + 8) {
149 LOGERROR("audiocodec: %s: too much data for spdif buffer!", __FUNCTION__);
150 return -1;
151 }
152
153 if (avpkt->size < 6)
154 return -1;
155
156 // build SPDIF header and append AC3 audio data to it
157 int bitstreamMode = avpkt->data[5] & 0x07;
161 spdif[3] = htole16(avpkt->size * 8);
162 swab(avpkt->data, spdif + 4, avpkt->size);
163 memset((uint8_t *)(spdif + 4) + avpkt->size, 0, spdifSize - 8 - avpkt->size);
164
166 return 1;
167 }
168
169 // EAC3 passthrough
172 int spdifSize = EAC3_FRAME_SIZE * 4; // frames * channels * (samplesize / 8)
173 int repeat = 1;
174
175 // spdifSize is smaller, if we don't have 192000
176 if (m_currentHwSampleRate == 48000) {
177 spdifSize /= 4;
178 }
179
181 LOGERROR("audiocodec: %s: too much data for spdif buffer!", __FUNCTION__);
182 ResetSpdif();
183 return -1;
184 }
185
186 if (avpkt->size < 5) {
187 LOGERROR("audiocodec: %s: avpkt size too small!", __FUNCTION__);
188 ResetSpdif();
189 return -1;
190 }
191
192 // check if we need to pack multiple packets
193 int fscod = (avpkt->data[4] >> 6) & 0x3;
194 int numblkscod = 6;
195 if (fscod != 0x3) {
196 numblkscod = (avpkt->data[4] >> 4) & 0x3;
197 static const uint8_t eac3_repeat[4] = { 6, 3, 2, 1 };
199 }
200
201 if (repeat * avpkt->size > spdifSize - 8) {
202 LOGERROR("audiocodec: %s: spdif size too small!", __FUNCTION__);
203 ResetSpdif();
204 return -1;
205 }
206
207 // pack upto repeat EAC-3 pakets into one IEC 61937 burst
208 swab(avpkt->data, (uint8_t *)(spdif + 4) + m_spdifIndex, avpkt->size);
209 m_spdifIndex += avpkt->size;
210
211// LOGDEBUG2(L_CODEC, "audiocodec: %s: E-AC3: set repeat to %d (fscod = %d, numblkscode = %d) avpkt->size %d (spdifSize %d) (repeatCount gets %d) (m_spdifIndex = %d)",
212// __FUNCTION__, repeat, fscod, numblkscod, avpkt->size, spdifSize, m_spdifRepeatCount + 1, m_spdifIndex);
213
215 return 1;
216
217 if (m_spdifRepeatCount > 6) {
218 ResetSpdif();
219 return -1;
220 }
221
222 // build SPDIF header and append E-AC3 audio data to it
226 spdif[3] = htole16(m_spdifIndex * 8);
227 int pad = spdifSize - 8 - m_spdifIndex;
228 if (pad > 0)
229 memset((uint8_t *)(spdif + 4) + m_spdifIndex, 0, pad);
230
232 ResetSpdif();
233 return 1;
234 }
235
236 // DTS passthrough
239
240 uint8_t nbs;
241 int bsid;
242 int burstSz;
243
244 if (avpkt->size < 6) {
245 LOGERROR("audiocodec: %s: avpkt size too small!", __FUNCTION__);
246 return -1;
247 }
248
249 nbs = (uint8_t)((avpkt->data[4] & 0x01) << 6) |
250 ((avpkt->data[5] >> 2) & 0x3f);
251 switch(nbs) {
252 case 0x07:
253 bsid = 0x0a; // MPEG-2 layer 3 is used when?
254 burstSz = 1024;
255 break;
256 case 0x0f:
258 burstSz = DTS1_FRAME_SIZE * 4; // frames * channels * (samplesize / 8)
259 break;
260 case 0x1f:
262 burstSz = DTS2_FRAME_SIZE * 4; // frames * channels * (samplesize / 8)
263 break;
264 case 0x3f:
266 burstSz = DTS3_FRAME_SIZE * 4; // frames * channels * (samplesize / 8)
267 break;
268 default:
270 if (nbs < 5)
271 nbs = 127;
272 burstSz = (nbs + 1) * 32 * 2 + 2;
273 break;
274 }
275
276 // build SPDIF header and append DTS audio data to it
277 if (burstSz < avpkt->size + 8) {
278 LOGERROR("audiocodec: %s: too much data for spdif buffer!", __FUNCTION__);
279 return -1;
280 }
283 spdif[2] = htole16(bsid);
284 spdif[3] = htole16(avpkt->size * 8);
287 swab(avpkt->data, spdif + 6, avpkt->size);
288 memset((uint8_t *)(spdif + 6) + avpkt->size, 0, burstSz - 12 - avpkt->size);
289
291 return 1;
292 }
293
294 return 0;
295}
296
306{
307 int isPassthrough = 0;
308 int err = 0;
309
310 m_currentSampleRate = m_pAudioCtx->sample_rate;
311 m_currentHwSampleRate = m_pAudioCtx->sample_rate;
312 m_currentNumChannels = m_pAudioCtx->ch_layout.nb_channels;
313 m_currentHwNumChannels = m_pAudioCtx->ch_layout.nb_channels;
315
319
320 // E-AC3 over HDMI: some receivers need HBR
321 if (m_pAudioCtx->codec_id == AV_CODEC_ID_EAC3)
323
325 m_spdifIndex = 0;
327 isPassthrough = 1;
328 }
329
331 // E-AC3 over HDMI: try without HBR
333
334 if (m_pAudioCtx->codec_id != AV_CODEC_ID_EAC3 ||
336 LOGERROR("audiocodec: %s: format change update error", __FUNCTION__);
339 return err;
340 }
341 }
342
343 if (!err) {
344 LOGDEBUG2(L_SOUND, "audiocodec: %s: format change %s %dHz *%d channels%s%s%s%s%d", __FUNCTION__,
345 av_get_sample_fmt_name(m_pAudioCtx->sample_fmt), m_pAudioCtx->sample_rate, m_pAudioCtx->ch_layout.nb_channels,
346 m_passthroughMask & CODEC_AC3 ? " AC3" : "",
347 m_passthroughMask & CODEC_EAC3 ? " EAC3" : "",
348 m_passthroughMask & CODEC_DTS ? " DTS" : "",
349 m_passthroughMask ? " passthrough mask " : "",
351 }
352
353 return err;
354}
355
364{
365 std::lock_guard<std::mutex> lock(m_mutex);
366
367 int retSend, retRec;
368 AVFrame *frame;
369
370 // decoded frame is also needed for passthrough to set the PTS
371 frame = m_pFrame;
372 av_frame_unref(frame);
373
374 do {
376 if (retSend < 0 && retSend != AVERROR(EAGAIN))
377 LOGERROR("audiocodec: %s: avcodec_send_packet error: %s", __FUNCTION__, av_err2str(retSend));
378
379 do {
381
382 if (retRec < 0) {
383 if (retRec != AVERROR(EAGAIN))
384 LOGERROR("audiocodec: %s: avcodec_receive_frame error: %s", __FUNCTION__, av_err2str(retRec));
385 continue;
386 }
387
388 if (m_lastPts == AV_NOPTS_VALUE && avpkt->pts == AV_NOPTS_VALUE) {
389 // the first AVPacket has no valid PTS, if its PES packet has been truncated while searching for the sync word
390 av_frame_unref(frame);
391 continue;
392 }
393
394 // update audio clock and remeber last PTS or guess the next PTS
395 if (frame->pts != AV_NOPTS_VALUE) {
396 m_lastPts = frame->pts;
397 } else if (m_lastPts != AV_NOPTS_VALUE) {
398 frame->pts = m_lastPts +
399 av_rescale_q(frame->nb_samples, (AVRational){1, frame->sample_rate}, m_pAudioCtx->pkt_timebase);
400 m_lastPts = frame->pts;
401 }
402
404 m_currentNumChannels != m_pAudioCtx->ch_layout.nb_channels ||
405 m_currentSampleRate != m_pAudioCtx->sample_rate) {
406 UpdateFormat();
407 }
408
410 LOGERROR("audiocodec: %s: unsupported format!", __FUNCTION__);
411 av_frame_unref(frame);
412 return;
413 }
414
415 if (DecodePassthrough(avpkt, frame)) {
416 av_frame_unref(frame);
417 } else
418 m_pAudio->Filter(frame, m_pAudioCtx);
419 } while (retRec == 0);
420 } while (retSend == AVERROR(EAGAIN));
421}
422
429{
430 std::lock_guard<std::mutex> lock(m_mutex);
431
432 LOGDEBUG2(L_CODEC, "audiocodec: %s", __FUNCTION__);
433 if (m_pAudioCtx)
435
438
439 ResetSpdif();
440}
441
446{
447 m_spdifIndex = 0;
449}
450
Audio and Alsa Interface Header File.
int DecodePassthrough(const AVPacket *, AVFrame *)
Passthrough audio data.
int UpdateFormat(void)
Handle audio format changes.
AVCodecContext * m_pAudioCtx
ffmpeg audio codec context
int m_currentHwSampleRate
current hw sample rate
void FlushBuffers(void)
Flush the audio decoder buffers.
int m_currentHwNumChannels
current number of hw channels
void Decode(const AVPacket *)
Decode an audio packet.
AVFrame * m_pFrame
decoded ffmpeg audio frame
int m_spdifIndex
index into SPDIF output buffer
int m_currentPassthroughMask
current passthrough mask
int m_passthroughMask
passthrough mask to be set
AVCodecID m_codecId
current codec id
cAudioDecoder(cSoftHdAudio *)
Create a new audio decoder for the given audio context.
void SetPassthroughMask(int)
Set audio pass-through mask.
int m_spdifRepeatCount
SPDIF repeat counter.
uint16_t m_spdifOutput[(MAX_FRAME_SIZE *4+16)/2]
SPDIF output buffer.
std::mutex m_mutex
decoder mutex
int64_t m_lastPts
last seen PTS
int m_currentSampleRate
current sample rate
void ResetSpdif(void)
Rest the internal SPDIF burst buffer.
cSoftHdAudio * m_pAudio
audio module
int m_currentNumChannels
current number of channels
void Open(AVCodecID, AVCodecParameters *=nullptr, AVRational={ .num=1,.den=90000 })
Open and initiate the audio decoder.
void Close(void)
Close the audio decoder.
Audio Interface.
Definition audio.h:50
void Filter(AVFrame *, AVCodecContext *)
Send audio frame to filter and enqueue it.
Definition audio.cpp:938
int Setup(AVCodecContext *, int, int, int)
Alsa setup wrapper.
Definition audio.cpp:849
void EnqueueSpdif(uint16_t *, int, AVFrame *)
Enqueue prepared spdif bursts in audio output queue.
Definition audio.cpp:775
void SetTimebase(AVRational *timebase)
Definition audio.h:83
Audio Decoder Header File.
@ EAC3_FRAME_SIZE
Definition codec_audio.h:81
@ AC3_FRAME_SIZE
Definition codec_audio.h:80
@ DTS3_FRAME_SIZE
Definition codec_audio.h:79
@ DTS2_FRAME_SIZE
Definition codec_audio.h:78
@ DTS1_FRAME_SIZE
Definition codec_audio.h:77
@ IEC61937_DTS3
DTS type III (2048 samples)
Definition codec_audio.h:54
@ IEC61937_DTS2
DTS type II (1024 samples)
Definition codec_audio.h:53
@ IEC61937_AC3
AC-3 data.
Definition codec_audio.h:50
@ IEC61937_NULL
no data
Definition codec_audio.h:49
@ IEC61937_EAC3
E-AC-3 data.
Definition codec_audio.h:51
@ IEC61937_DTS1
DTS type I (512 samples)
Definition codec_audio.h:52
@ IEC61937_PREAMBLE1
Definition codec_audio.h:65
@ DTS_PREAMBLE_16BE_2
Definition codec_audio.h:68
@ DTS_PREAMBLE_16BE_1
Definition codec_audio.h:67
@ IEC61937_PREAMBLE2
Definition codec_audio.h:66
@ CODEC_EAC3
E-AC-3 bit mask.
Definition codec_audio.h:39
@ CODEC_AC3
AC-3 bit mask.
Definition codec_audio.h:38
@ CODEC_DTS
DTS bit mask.
Definition codec_audio.h:40
#define LOGDEBUG2
log to LOG_DEBUG and add a prefix
Definition logger.h:47
#define LOGERROR
log to LOG_ERR
Definition logger.h:39
#define AV_NOPTS_VALUE
Definition misc.h:74
#define LOGFATAL
log to LOG_ERR and abort
Definition logger.h:37
#define av_err2str(err)
Definition misc.h:112
@ L_CODEC
codec logs
Definition logger.h:61
@ L_SOUND
sound logs
Definition logger.h:58
Logger Header File.
Misc Functions.