FFmpeg
Loading...
Searching...
No Matches
libmpeghdec.c
Go to the documentation of this file.
1/*
2 * MPEG-H 3D Audio Decoder Wrapper
3 * Copyright (C) 2025 Fraunhofer Institute for Integrated Circuits IIS
4 *
5 * This file is part of FFmpeg.
6 *
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.
11 *
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.
16 *
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
20 */
21
22/*
23 * Please note that this FFmpeg Software is licensed under the LGPL-2.1
24 * but is combined with software that is licensed under different terms, namely
25 * the "Software License for The Fraunhofer FDK MPEG-H Software". Fraunhofer
26 * as the initial licensor does not interpret the LGPL-2.1 as requiring
27 * distribution of the MPEG-H Software under the LGPL-2.1 if being distributed
28 * together with this FFmpeg Software. Therefore, downstream distribution of
29 * FFmpeg Software does not imply any right to redistribute the MPEG-H Software
30 * under the LGPL-2.1.
31 */
32#include <string.h>
33#include <mpeghdec/mpeghdecoder.h>
34
36#include "libavutil/frame.h"
37#include "libavutil/mem.h"
38
39#include "codec_internal.h"
40#include "decode.h"
41
42#define MAX_LOST_FRAMES 2
43// max framesize * (max delay frames + 1)
44#define PER_CHANNEL_OUTBUF_SIZE (3072 * (MAX_LOST_FRAMES + 1))
45
46typedef struct MPEGH3DADecContext {
47 // pointer to the decoder
48 HANDLE_MPEGH_DECODER_CONTEXT decoder;
49
50 // Internal values
52 int decoder_buffer_size; ///< in samples
54
56{
58
59 if (s->decoder)
60 mpeghdecoder_destroy(s->decoder);
61 s->decoder = NULL;
62 av_freep(&s->decoder_buffer);
63
64 return 0;
65}
66
67// Lookup CICP for FFmpeg channel layout, see:
68// https://github.com/Fraunhofer-IIS/mpeghdec/wiki/MPEG-H-decoder-target-layouts
70{
71// different from AV_CH_LAYOUT_7POINT2POINT3
72#define CH_LAYOUT_7POINT2POINT3 AV_CH_LAYOUT_5POINT1POINT2 | AV_CH_SIDE_SURROUND_LEFT | \
73 AV_CH_SIDE_SURROUND_RIGHT | AV_CH_TOP_BACK_CENTER | \
74 AV_CH_LOW_FREQUENCY_2
75#define CH_LAYOUT_5POINT1POINT6 AV_CH_LAYOUT_5POINT1POINT4_BACK | \
76 AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_CENTER
77#define CH_LAYOUT_7POINT1POINT6 AV_CH_LAYOUT_7POINT1POINT4_BACK | \
78 AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_CENTER
79 static const uint64_t channel_layout_masks[] = {
80 0,
91 };
92 for (size_t i = 0; i < FF_ARRAY_ELEMS(channel_layout_masks); ++i) {
93 if (channel_layout_masks[i]) {
94 AVChannelLayout ch_layout;
95 av_channel_layout_from_mask(&ch_layout, channel_layout_masks[i]);
96 if (!av_channel_layout_compare(layout, &ch_layout))
97 return i;
98 }
99 }
100
101 return 0;
102}
103
105{
106 int cicp;
107
109
110 if (avctx->ch_layout.nb_channels == 0) {
111 av_log(avctx, AV_LOG_ERROR, "Channel layout needs to be specified\n");
112 return AVERROR(EINVAL);
113 } else if ((cicp = channel_layout_to_cicp(&avctx->ch_layout)) <= 0) {
114 av_log(avctx, AV_LOG_ERROR, "Unsupported channel layout\n");
115 return AVERROR(EINVAL);
116 }
117
118 s->decoder = NULL;
119
120 avctx->delay = 0;
122 avctx->sample_rate = 48000;
123
124 s->decoder_buffer_size = PER_CHANNEL_OUTBUF_SIZE * avctx->ch_layout.nb_channels;
125 s->decoder_buffer = av_malloc_array(s->decoder_buffer_size, sizeof(*s->decoder_buffer));
126 if (!s->decoder_buffer)
127 return AVERROR(ENOMEM);
128
129 // initialize the decoder
130 s->decoder = mpeghdecoder_init(cicp);
131 if (s->decoder == NULL) {
132 av_log(avctx, AV_LOG_ERROR, "MPEG-H decoder library init failed.\n");
133 return AVERROR_EXTERNAL;
134 }
135
136 if (avctx->extradata_size) {
137 if (mpeghdecoder_setMhaConfig(s->decoder, avctx->extradata,
138 avctx->extradata_size)) {
139 av_log(avctx, AV_LOG_ERROR, "Unable to set MHA configuration\n");
140 return AVERROR_INVALIDDATA;
141 }
142 }
143
144 return 0;
145}
146
148 int *got_frame_ptr, AVPacket *avpkt)
149{
151 int ret;
152 MPEGH_DECODER_ERROR err;
153 MPEGH_DECODER_OUTPUT_INFO out_info;
154
155 if (!avctx->sample_rate) {
156 av_log(avctx, AV_LOG_ERROR, "Audio sample rate is not set");
157 return AVERROR_INVALIDDATA;
158 }
159
160 if (avpkt->data != NULL && avpkt->size > 0) {
161 if ((err = mpeghdecoder_processTimescale(s->decoder, avpkt->data,
162 avpkt->size, avpkt->pts,
163 avctx->sample_rate))) {
164 av_log(avctx, AV_LOG_ERROR, "mpeghdecoder_process() failed: %x\n",
165 err);
166 return AVERROR_INVALIDDATA;
167 }
168 } else {
169 // we are flushing
170 err = mpeghdecoder_flushAndGet(s->decoder);
171
172 if (err != MPEGH_DEC_OK && err != MPEGH_DEC_FEED_DATA)
173 av_log(avctx, AV_LOG_WARNING,
174 "mpeghdecoder_flushAndGet() failed: %d\n", err);
175 }
176
177 err = mpeghdecoder_getSamples(s->decoder, s->decoder_buffer,
178 s->decoder_buffer_size,
179 &out_info);
180 if (err == MPEGH_DEC_FEED_DATA) {
181 // no frames to produce at the moment
182 return avpkt->size;
183 } else if (err) {
184 av_log(avctx, AV_LOG_ERROR, "mpeghdecoder_getSamples() failed: %x\n",
185 err);
186 return AVERROR_UNKNOWN;
187 }
188
189 frame->nb_samples = out_info.numSamplesPerChannel;
190 frame->sample_rate = avctx->sample_rate = out_info.sampleRate;
191 frame->pts = out_info.ticks;
192 frame->time_base.num = 1;
193 frame->time_base.den = out_info.sampleRate;
194
195 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
196 return ret;
197
198 memcpy(frame->extended_data[0], s->decoder_buffer,
199 avctx->ch_layout.nb_channels * frame->nb_samples *
200 sizeof(*s->decoder_buffer) /* only AV_SAMPLE_FMT_S32 is supported */);
201
202 *got_frame_ptr = 1;
203 return ret = avpkt->size;
204}
205
207{
208 MPEGH_DECODER_ERROR err;
210
211 err = mpeghdecoder_flush(s->decoder);
212
213 if (err != MPEGH_DEC_OK && err != MPEGH_DEC_FEED_DATA)
214 av_log(avctx, AV_LOG_WARNING, "mpeghdecoder_flush failed: %d\n", err);
215}
216
218 .p.name = "libmpeghdec",
219 CODEC_LONG_NAME("libmpeghdec (MPEG-H 3D Audio)"),
220 .p.type = AVMEDIA_TYPE_AUDIO,
222 .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
224 .caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
225 .priv_data_size = sizeof(MPEGH3DADecContext),
228 .flush = mpegh3dadec_flush,
229 .close = mpegh3dadec_close,
230 .p.wrapper_name = "libmpeghdec",
231};
const FFCodec ff_libmpeghdec_decoder
int32_t
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
Public libavutil channel layout APIs header.
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
#define NULL
Definition coverity.c:32
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
reference-counted frame API
#define AV_CH_LAYOUT_6POINT1
#define AV_CH_LAYOUT_4POINT0
#define AV_CH_LAYOUT_5POINT0
#define AV_CH_LAYOUT_7POINT1
#define AV_CH_LAYOUT_7POINT1POINT4_BACK
#define AV_CH_LAYOUT_MONO
#define AV_CH_LAYOUT_2_2
#define AV_CH_LAYOUT_SURROUND
#define AV_CH_LAYOUT_7POINT1_WIDE
#define AV_CH_LAYOUT_5POINT1POINT2
#define AV_CH_LAYOUT_STEREO
#define AV_CH_LAYOUT_22POINT2
#define AV_CH_LAYOUT_5POINT1
#define AV_CH_LAYOUT_2_1
#define AV_CH_LAYOUT_5POINT1POINT4_BACK
#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
#define AV_CODEC_CAP_CHANNEL_CONF
Codec should fill in channel configuration and samplerate instead of container.
Definition codec.h:94
@ AV_CODEC_ID_MPEGH_3D_AUDIO
Definition codec_id.h:544
int av_channel_layout_compare(const AVChannelLayout *chl, const AVChannelLayout *chl1)
Check whether two channel layouts are semantically the same, i.e.
int av_channel_layout_from_mask(AVChannelLayout *channel_layout, uint64_t mask)
Initialize a native channel layout from a bitmask indicating which channels are present.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition error.h:59
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AV_SAMPLE_FMT_S32
signed 32 bits
Definition samplefmt.h:59
#define av_cold
Definition attributes.h:117
#define CH_LAYOUT_7POINT2POINT3
static av_cold int mpegh3dadec_init(AVCodecContext *avctx)
static int mpegh3dadec_decode_frame(AVCodecContext *avctx, AVFrame *frame, int *got_frame_ptr, AVPacket *avpkt)
#define PER_CHANNEL_OUTBUF_SIZE
Definition libmpeghdec.c:44
#define CH_LAYOUT_5POINT1POINT6
#define CH_LAYOUT_7POINT1POINT6
static av_cold int channel_layout_to_cicp(const AVChannelLayout *layout)
Definition libmpeghdec.c:69
static av_cold void mpegh3dadec_flush(AVCodecContext *avctx)
static av_cold int mpegh3dadec_close(AVCodecContext *avctx)
Definition libmpeghdec.c:55
uint64_t layout
Memory handling functions.
#define FF_ARRAY_ELEMS(a)
An AVChannelLayout holds information about the channel layout of audio data.
int nb_channels
Number of channels in this layout.
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
int sample_rate
samples per second
Definition avcodec.h:1040
int delay
Codec delay.
Definition avcodec.h:587
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
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition packet.h:596
uint8_t * data
Definition packet.h:603
HANDLE_MPEGH_DECODER_CONTEXT decoder
Definition libmpeghdec.c:48
int decoder_buffer_size
in samples
Definition libmpeghdec.c:52
int32_t * decoder_buffer
Definition libmpeghdec.c:51
#define av_malloc_array(a, b)
#define av_freep(p)
#define av_log(a,...)