1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
index c0e16d6a887..3257daab442 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGReader.cpp
@@ -31,6 +31,10 @@ AUD_NAMESPACE_BEGIN
#define FFMPEG_OLD_CODE
#endif
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+#define HAVE_CH_LAYOUT
+#endif
+
SampleFormat FFMPEGReader::convertSampleFormat(AVSampleFormat format)
{
switch(av_get_packed_sample_fmt(format))
@@ -104,15 +108,22 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
packet.size = orig_size;
#else
avcodec_send_packet(m_codecCtx, &packet);
+
while(true)
{
auto ret = avcodec_receive_frame(m_codecCtx, m_frame);
+#ifdef HAVE_CH_LAYOUT
+ int nb_channels = m_codecCtx->ch_layout.nb_channels;
+#else
+ int nb_channels = m_codecCtx->channels;
+#endif
+
if(ret != 0)
break;
- int data_size = av_samples_get_buffer_size(nullptr, m_codecCtx->channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1);
+ int data_size = av_samples_get_buffer_size(nullptr, nb_channels, m_frame->nb_samples, m_codecCtx->sample_fmt, 1);
if(buf_size - buf_pos < data_size)
{
@@ -122,12 +133,12 @@ int FFMPEGReader::decode(AVPacket& packet, Buffer& buffer)
if(m_tointerleave)
{
- int single_size = data_size / m_codecCtx->channels / m_frame->nb_samples;
- for(int channel = 0; channel < m_codecCtx->channels; channel++)
+ int single_size = data_size / nb_channels / m_frame->nb_samples;
+ for(int channel = 0; channel < nb_channels; channel++)
{
for(int i = 0; i < m_frame->nb_samples; i++)
{
- std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((m_codecCtx->channels * i) + channel) * single_size,
+ std::memcpy(((data_t*)buffer.getBuffer()) + buf_pos + ((nb_channels * i) + channel) * single_size,
m_frame->data[channel] + i * single_size, single_size);
}
}
@@ -207,7 +218,11 @@ void FFMPEGReader::init(int stream)
if(avcodec_open2(m_codecCtx, aCodec, nullptr) < 0)
AUD_THROW(FileException, "File couldn't be read, ffmpeg codec couldn't be opened.");
+#ifdef HAVE_CH_LAYOUT
+ m_specs.channels = (Channels) m_codecCtx->ch_layout.nb_channels;
+#else
m_specs.channels = (Channels) m_codecCtx->channels;
+#endif
m_tointerleave = av_sample_fmt_is_planar(m_codecCtx->sample_fmt);
switch(av_get_packed_sample_fmt(m_codecCtx->sample_fmt))
@@ -344,8 +359,12 @@ std::vector<StreamInfo> FFMPEGReader::queryStreams()
info.specs.channels = Channels(m_formatCtx->streams[i]->codec->channels);
info.specs.rate = m_formatCtx->streams[i]->codec->sample_rate;
info.specs.format = convertSampleFormat(m_formatCtx->streams[i]->codec->sample_fmt);
+#else
+#ifdef HAVE_CH_LAYOUT
+ info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->ch_layout.nb_channels);
#else
info.specs.channels = Channels(m_formatCtx->streams[i]->codecpar->channels);
+#endif
info.specs.rate = m_formatCtx->streams[i]->codecpar->sample_rate;
info.specs.format = convertSampleFormat(AVSampleFormat(m_formatCtx->streams[i]->codecpar->format));
#endif
diff --git a/extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp b/extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
index 9cadfe9c092..2f435c14b56 100644
--- a/extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
+++ b/extern/audaspace/plugins/ffmpeg/FFMPEGWriter.cpp
@@ -34,6 +34,10 @@ AUD_NAMESPACE_BEGIN
#define FFMPEG_OLD_CODE
#endif
+#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 28, 100)
+#define HAVE_CH_LAYOUT
+#endif
+
void FFMPEGWriter::encode()
{
sample_t* data = m_input_buffer.getBuffer();
@@ -77,8 +81,12 @@ void FFMPEGWriter::encode()
m_frame->nb_samples = m_input_samples;
m_frame->format = m_codecCtx->sample_fmt;
+#ifdef HAVE_CH_LAYOUT
+ av_channel_layout_copy(&m_frame->ch_layout, &m_codecCtx->ch_layout);
+#else
m_frame->channel_layout = m_codecCtx->channel_layout;
m_frame->channels = m_specs.channels;
+#endif
if(avcodec_fill_audio_frame(m_frame, m_specs.channels, m_codecCtx->sample_fmt, reinterpret_cast<data_t*>(data), m_input_buffer.getSize(), 0) < 0)
AUD_THROW(FileException, "File couldn't be written, filling the audio frame failed with ffmpeg.");
@@ -237,6 +245,39 @@ FFMPEGWriter::FFMPEGWriter(const std::string &filename, DeviceSpecs specs, Conta
break;
}
+#ifdef HAVE_CH_LAYOUT
+ AVChannelLayout channel_layout{};
+
+ switch(m_specs.channels)
+ {
+ case CHANNELS_MONO:
+ channel_layout = AV_CHANNEL_LAYOUT_MONO;
+ break;
+ case CHANNELS_STEREO:
+ channel_layout = AV_CHANNEL_LAYOUT_STEREO;
+ break;
+ case CHANNELS_STEREO_LFE:
+ channel_layout = AV_CHANNEL_LAYOUT_2POINT1;
+ break;
+ case CHANNELS_SURROUND4:
+ channel_layout = AV_CHANNEL_LAYOUT_QUAD;
+ break;
+ case CHANNELS_SURROUND5:
+ channel_layout = AV_CHANNEL_LAYOUT_5POINT0_BACK;
+ break;
+ case CHANNELS_SURROUND51:
+ channel_layout = AV_CHANNEL_LAYOUT_5POINT1_BACK;
+ break;
+ case CHANNELS_SURROUND61:
+ channel_layout = AV_CHANNEL_LAYOUT_6POINT1_BACK;
+ break;
+ case CHANNELS_SURROUND71:
+ channel_layout = AV_CHANNEL_LAYOUT_7POINT1;
+ break;
+ default:
+ AUD_THROW(FileException, "File couldn't be written, channel layout not supported.");
+ }
+#else
uint64_t channel_layout = 0;
switch(m_specs.channels)
@@ -268,6 +309,7 @@ FFMPEGWriter::FFMPEGWriter(const std::string &filename, DeviceSpecs specs, Conta
default:
AUD_THROW(FileException, "File couldn't be written, channel layout not supported.");
}
+#endif
try
{
@@ -405,8 +447,12 @@ FFMPEGWriter::FFMPEGWriter(const std::string &filename, DeviceSpecs specs, Conta
m_codecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
m_codecCtx->bit_rate = bitrate;
+#ifdef HAVE_CH_LAYOUT
+ av_channel_layout_copy(&m_codecCtx->ch_layout, &channel_layout);
+#else
m_codecCtx->channel_layout = channel_layout;
m_codecCtx->channels = m_specs.channels;
+#endif
m_stream->time_base.num = m_codecCtx->time_base.num = 1;
m_stream->time_base.den = m_codecCtx->time_base.den = m_codecCtx->sample_rate;
|