react-native-audio-api 0.9.0-nightly-7ecb495-20251008 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/cpp/audioapi/android/core/{utils/AudioDecoder.cpp → AudioDecoder.cpp} +75 -79
- package/android/src/main/jniLibs/arm64-v8a/libavcodec.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libavformat.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libavutil.so +0 -0
- package/android/src/main/jniLibs/arm64-v8a/libswresample.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libavcodec.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libavformat.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libavutil.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libswresample.so +0 -0
- package/android/src/main/jniLibs/x86/libavcodec.so +0 -0
- package/android/src/main/jniLibs/x86/libavformat.so +0 -0
- package/android/src/main/jniLibs/x86/libavutil.so +0 -0
- package/android/src/main/jniLibs/x86/libswresample.so +0 -0
- package/android/src/main/jniLibs/x86_64/libavcodec.so +0 -0
- package/android/src/main/jniLibs/x86_64/libavformat.so +0 -0
- package/android/src/main/jniLibs/x86_64/libavutil.so +0 -0
- package/android/src/main/jniLibs/x86_64/libswresample.so +0 -0
- package/common/cpp/audioapi/AudioAPIModuleInstaller.h +43 -124
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.cpp +101 -1
- package/common/cpp/audioapi/HostObjects/BaseAudioContextHostObject.h +3 -0
- package/common/cpp/audioapi/HostObjects/sources/AudioBufferHostObject.cpp +3 -8
- package/common/cpp/audioapi/core/AudioContext.cpp +2 -0
- package/common/cpp/audioapi/core/BaseAudioContext.cpp +35 -0
- package/common/cpp/audioapi/core/BaseAudioContext.h +12 -4
- package/common/cpp/audioapi/core/OfflineAudioContext.cpp +2 -0
- package/common/cpp/audioapi/core/effects/WorkletNode.cpp +16 -28
- package/common/cpp/audioapi/core/effects/WorkletNode.h +2 -3
- package/common/cpp/audioapi/core/effects/WorkletProcessingNode.cpp +5 -6
- package/common/cpp/audioapi/core/sources/AudioBuffer.h +1 -0
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.cpp +0 -4
- package/common/cpp/audioapi/core/sources/AudioBufferBaseSourceNode.h +0 -1
- package/common/cpp/audioapi/core/sources/AudioBufferSourceNode.cpp +0 -2
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.cpp +0 -4
- package/common/cpp/audioapi/core/sources/AudioScheduledSourceNode.h +0 -1
- package/common/cpp/audioapi/core/sources/StreamerNode.cpp +16 -6
- package/common/cpp/audioapi/core/sources/StreamerNode.h +3 -1
- package/common/cpp/audioapi/core/sources/WorkletSourceNode.cpp +2 -3
- package/common/cpp/audioapi/core/utils/AudioDecoder.h +91 -36
- package/common/cpp/audioapi/core/utils/Constants.h +0 -4
- package/common/cpp/audioapi/events/AudioEventHandlerRegistry.cpp +5 -1
- package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64/libavcodec.framework/libavcodec +0 -0
- package/common/cpp/audioapi/external/libavcodec.xcframework/ios-arm64_x86_64-simulator/libavcodec.framework/libavcodec +0 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/Info.plist +5 -5
- package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64/libavformat.framework/libavformat +0 -0
- package/common/cpp/audioapi/external/libavformat.xcframework/ios-arm64_x86_64-simulator/libavformat.framework/libavformat +0 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64/libavutil.framework/libavutil +0 -0
- package/common/cpp/audioapi/external/libavutil.xcframework/ios-arm64_x86_64-simulator/libavutil.framework/libavutil +0 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/Info.plist +5 -5
- package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64/libswresample.framework/libswresample +0 -0
- package/common/cpp/audioapi/external/libswresample.xcframework/ios-arm64_x86_64-simulator/libswresample.framework/libswresample +0 -0
- package/common/cpp/audioapi/jsi/AudioArrayBuffer.cpp +2 -2
- package/common/cpp/audioapi/jsi/AudioArrayBuffer.h +10 -11
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.cpp +282 -241
- package/common/cpp/audioapi/libs/ffmpeg/FFmpegDecoding.h +19 -57
- package/common/cpp/audioapi/libs/ffmpeg/ffmpeg_setup.sh +1 -1
- package/common/cpp/audioapi/utils/AudioBus.cpp +4 -0
- package/common/cpp/audioapi/utils/AudioBus.h +1 -0
- package/common/cpp/test/CMakeLists.txt +8 -5
- package/common/cpp/test/RunTests.sh +2 -2
- package/common/cpp/test/{AudioParamTest.cpp → src/AudioParamTest.cpp} +1 -1
- package/common/cpp/test/src/ConstantSourceTest.cpp +64 -0
- package/common/cpp/test/{GainTest.cpp → src/GainTest.cpp} +11 -10
- package/common/cpp/test/{MockAudioEventHandlerRegistry.h → src/MockAudioEventHandlerRegistry.h} +4 -2
- package/common/cpp/test/{OscillatorTest.cpp → src/OscillatorTest.cpp} +6 -4
- package/common/cpp/test/{StereoPannerTest.cpp → src/StereoPannerTest.cpp} +1 -1
- package/ios/audioapi/ios/core/AudioDecoder.mm +156 -0
- package/lib/commonjs/api.js +1 -21
- package/lib/commonjs/api.js.map +1 -1
- package/lib/commonjs/core/BaseAudioContext.js +18 -11
- package/lib/commonjs/core/BaseAudioContext.js.map +1 -1
- package/lib/module/api.js +1 -3
- package/lib/module/api.js.map +1 -1
- package/lib/module/core/BaseAudioContext.js +18 -11
- package/lib/module/core/BaseAudioContext.js.map +1 -1
- package/lib/typescript/api.d.ts +1 -5
- package/lib/typescript/api.d.ts.map +1 -1
- package/lib/typescript/core/BaseAudioContext.d.ts +6 -3
- package/lib/typescript/core/BaseAudioContext.d.ts.map +1 -1
- package/lib/typescript/interfaces.d.ts +3 -10
- package/lib/typescript/interfaces.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/api.ts +0 -10
- package/src/core/BaseAudioContext.ts +29 -26
- package/src/interfaces.ts +6 -26
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.cpp +0 -133
- package/common/cpp/audioapi/HostObjects/utils/AudioDecoderHostObject.h +0 -28
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.cpp +0 -58
- package/common/cpp/audioapi/HostObjects/utils/AudioStretcherHostObject.h +0 -26
- package/common/cpp/audioapi/core/types/AudioFormat.h +0 -16
- package/common/cpp/audioapi/core/utils/AudioStretcher.cpp +0 -75
- package/common/cpp/audioapi/core/utils/AudioStretcher.h +0 -30
- package/ios/audioapi/ios/core/utils/AudioDecoder.mm +0 -160
- package/lib/commonjs/core/AudioDecoder.js +0 -48
- package/lib/commonjs/core/AudioDecoder.js.map +0 -1
- package/lib/commonjs/core/AudioStretcher.js +0 -31
- package/lib/commonjs/core/AudioStretcher.js.map +0 -1
- package/lib/module/core/AudioDecoder.js +0 -42
- package/lib/module/core/AudioDecoder.js.map +0 -1
- package/lib/module/core/AudioStretcher.js +0 -26
- package/lib/module/core/AudioStretcher.js.map +0 -1
- package/lib/typescript/core/AudioDecoder.d.ts +0 -4
- package/lib/typescript/core/AudioDecoder.d.ts.map +0 -1
- package/lib/typescript/core/AudioStretcher.d.ts +0 -3
- package/lib/typescript/core/AudioStretcher.d.ts.map +0 -1
- package/src/core/AudioDecoder.ts +0 -78
- package/src/core/AudioStretcher.ts +0 -43
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* This file dynamically links to the FFmpeg library, which is licensed under
|
|
3
|
-
*
|
|
2
|
+
* This file dynamically links to the FFmpeg library, which is licensed under the
|
|
3
|
+
* GNU Lesser General Public License (LGPL) version 2.1 or later.
|
|
4
4
|
*
|
|
5
|
-
* Our own code in this file is licensed under the MIT License and dynamic
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* Our own code in this file is licensed under the MIT License and dynamic linking
|
|
6
|
+
* allows you to use this code without your entire project being subject to the
|
|
7
|
+
* terms of the LGPL. However, note that if you link statically to FFmpeg, you must
|
|
8
|
+
* comply with the terms of the LGPL for FFmpeg itself.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
#include
|
|
12
|
-
#include <audioapi/libs/ffmpeg/FFmpegDecoding.h>
|
|
13
|
-
#include <audioapi/utils/AudioArray.h>
|
|
14
|
-
#include <audioapi/utils/AudioBus.h>
|
|
15
|
-
#include <functional>
|
|
11
|
+
#include "FFmpegDecoding.h"
|
|
16
12
|
|
|
17
|
-
namespace audioapi::
|
|
13
|
+
namespace audioapi::ffmpegdecoding {
|
|
18
14
|
|
|
19
15
|
int read_packet(void *opaque, uint8_t *buf, int buf_size) {
|
|
20
16
|
MemoryIOContext *ctx = static_cast<MemoryIOContext *>(opaque);
|
|
@@ -55,87 +51,42 @@ int64_t seek_packet(void *opaque, int64_t offset, int whence) {
|
|
|
55
51
|
return ctx->pos;
|
|
56
52
|
}
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
SwrContext *swr,
|
|
60
|
-
AVFrame *frame,
|
|
61
|
-
int output_channel_count,
|
|
62
|
-
std::vector<float> &buffer,
|
|
63
|
-
size_t &framesRead,
|
|
64
|
-
uint8_t **&resampled_data,
|
|
65
|
-
int &max_resampled_samples) {
|
|
66
|
-
const int out_samples = swr_get_out_samples(swr, frame->nb_samples);
|
|
67
|
-
if (out_samples > max_resampled_samples) {
|
|
68
|
-
av_freep(&resampled_data[0]);
|
|
69
|
-
av_freep(&resampled_data);
|
|
70
|
-
max_resampled_samples = out_samples;
|
|
71
|
-
|
|
72
|
-
if (av_samples_alloc_array_and_samples(
|
|
73
|
-
&resampled_data,
|
|
74
|
-
nullptr,
|
|
75
|
-
output_channel_count,
|
|
76
|
-
max_resampled_samples,
|
|
77
|
-
AV_SAMPLE_FMT_FLT,
|
|
78
|
-
0) < 0) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
int converted_samples = swr_convert(
|
|
84
|
-
swr,
|
|
85
|
-
resampled_data,
|
|
86
|
-
max_resampled_samples,
|
|
87
|
-
const_cast<const uint8_t **>(frame->data),
|
|
88
|
-
frame->nb_samples);
|
|
89
|
-
|
|
90
|
-
if (converted_samples > 0) {
|
|
91
|
-
const size_t current_size = buffer.size();
|
|
92
|
-
const size_t new_samples =
|
|
93
|
-
static_cast<size_t>(converted_samples) * output_channel_count;
|
|
94
|
-
buffer.resize(current_size + new_samples);
|
|
95
|
-
memcpy(
|
|
96
|
-
buffer.data() + current_size,
|
|
97
|
-
resampled_data[0],
|
|
98
|
-
new_samples * sizeof(float));
|
|
99
|
-
framesRead += converted_samples;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
std::vector<float> readAllPcmFrames(
|
|
54
|
+
std::vector<int16_t> readAllPcmFrames(
|
|
104
55
|
AVFormatContext *fmt_ctx,
|
|
105
56
|
AVCodecContext *codec_ctx,
|
|
106
57
|
int out_sample_rate,
|
|
107
|
-
int output_channel_count,
|
|
108
58
|
int audio_stream_index,
|
|
59
|
+
int channels,
|
|
109
60
|
size_t &framesRead) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
swr_alloc(), [](SwrContext *ctx) { swr_free(&ctx); });
|
|
114
|
-
|
|
115
|
-
if (swr == nullptr)
|
|
61
|
+
std::vector<int16_t> buffer;
|
|
62
|
+
SwrContext *swr_ctx = swr_alloc();
|
|
63
|
+
if (swr_ctx == nullptr) {
|
|
116
64
|
return buffer;
|
|
65
|
+
}
|
|
117
66
|
|
|
118
|
-
av_opt_set_chlayout(
|
|
119
|
-
av_opt_set_int(
|
|
120
|
-
av_opt_set_sample_fmt(
|
|
67
|
+
av_opt_set_chlayout(swr_ctx, "in_chlayout", &codec_ctx->ch_layout, 0);
|
|
68
|
+
av_opt_set_int(swr_ctx, "in_sample_rate", codec_ctx->sample_rate, 0);
|
|
69
|
+
av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", codec_ctx->sample_fmt, 0);
|
|
121
70
|
|
|
122
71
|
AVChannelLayout out_ch_layout;
|
|
123
|
-
av_channel_layout_default(&out_ch_layout,
|
|
124
|
-
av_opt_set_chlayout(
|
|
125
|
-
av_opt_set_int(
|
|
126
|
-
av_opt_set_sample_fmt(
|
|
72
|
+
av_channel_layout_default(&out_ch_layout, channels);
|
|
73
|
+
av_opt_set_chlayout(swr_ctx, "out_chlayout", &out_ch_layout, 0);
|
|
74
|
+
av_opt_set_int(swr_ctx, "out_sample_rate", out_sample_rate, 0);
|
|
75
|
+
av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
|
127
76
|
|
|
128
|
-
if (swr_init(
|
|
77
|
+
if (swr_init(swr_ctx) < 0) {
|
|
78
|
+
swr_free(&swr_ctx);
|
|
129
79
|
av_channel_layout_uninit(&out_ch_layout);
|
|
130
80
|
return buffer;
|
|
131
81
|
}
|
|
132
82
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
av_frame_alloc(), [](AVFrame *p) { av_frame_free(&p); });
|
|
137
|
-
|
|
83
|
+
AVPacket *packet = av_packet_alloc();
|
|
84
|
+
AVFrame *frame = av_frame_alloc();
|
|
85
|
+
|
|
138
86
|
if (packet == nullptr || frame == nullptr) {
|
|
87
|
+
if (packet != nullptr) av_packet_free(&packet);
|
|
88
|
+
if (frame != nullptr) av_frame_free(&frame);
|
|
89
|
+
swr_free(&swr_ctx);
|
|
139
90
|
av_channel_layout_uninit(&out_ch_layout);
|
|
140
91
|
return buffer;
|
|
141
92
|
}
|
|
@@ -143,222 +94,312 @@ std::vector<float> readAllPcmFrames(
|
|
|
143
94
|
// Allocate buffer for resampled data
|
|
144
95
|
uint8_t **resampled_data = nullptr;
|
|
145
96
|
int max_resampled_samples = 4096; // Initial size
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
97
|
+
int ret = av_samples_alloc_array_and_samples(
|
|
98
|
+
&resampled_data,
|
|
99
|
+
nullptr,
|
|
100
|
+
channels,
|
|
101
|
+
max_resampled_samples,
|
|
102
|
+
AV_SAMPLE_FMT_S16,
|
|
103
|
+
0);
|
|
104
|
+
|
|
105
|
+
if (ret < 0) {
|
|
106
|
+
av_frame_free(&frame);
|
|
107
|
+
av_packet_free(&packet);
|
|
108
|
+
swr_free(&swr_ctx);
|
|
153
109
|
av_channel_layout_uninit(&out_ch_layout);
|
|
154
110
|
return buffer;
|
|
155
111
|
}
|
|
156
112
|
|
|
157
|
-
|
|
113
|
+
framesRead = 0;
|
|
114
|
+
|
|
115
|
+
while (av_read_frame(fmt_ctx, packet) >= 0) {
|
|
158
116
|
if (packet->stream_index == audio_stream_index) {
|
|
159
|
-
if (avcodec_send_packet(codec_ctx, packet
|
|
160
|
-
while (avcodec_receive_frame(codec_ctx, frame
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
117
|
+
if (avcodec_send_packet(codec_ctx, packet) == 0) {
|
|
118
|
+
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
|
|
119
|
+
// Check if we need more buffer space
|
|
120
|
+
int out_samples = swr_get_out_samples(swr_ctx, frame->nb_samples);
|
|
121
|
+
if (out_samples > max_resampled_samples) {
|
|
122
|
+
if (resampled_data != nullptr) {
|
|
123
|
+
av_freep(&resampled_data[0]);
|
|
124
|
+
av_freep(&resampled_data);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
max_resampled_samples = out_samples;
|
|
128
|
+
ret = av_samples_alloc_array_and_samples(
|
|
129
|
+
&resampled_data,
|
|
130
|
+
nullptr,
|
|
131
|
+
channels,
|
|
132
|
+
max_resampled_samples,
|
|
133
|
+
AV_SAMPLE_FMT_S16,
|
|
134
|
+
0);
|
|
135
|
+
|
|
136
|
+
if (ret < 0) {
|
|
137
|
+
break; // Exit on allocation failure
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
int converted_samples = swr_convert(
|
|
142
|
+
swr_ctx,
|
|
167
143
|
resampled_data,
|
|
168
|
-
max_resampled_samples
|
|
144
|
+
max_resampled_samples,
|
|
145
|
+
(const uint8_t **)frame->data,
|
|
146
|
+
frame->nb_samples);
|
|
147
|
+
|
|
148
|
+
if (converted_samples > 0) {
|
|
149
|
+
size_t current_size = buffer.size();
|
|
150
|
+
size_t new_samples = converted_samples * channels;
|
|
151
|
+
buffer.resize(current_size + new_samples);
|
|
152
|
+
memcpy(
|
|
153
|
+
buffer.data() + current_size,
|
|
154
|
+
resampled_data[0],
|
|
155
|
+
new_samples * sizeof(int16_t));
|
|
156
|
+
|
|
157
|
+
framesRead += converted_samples;
|
|
158
|
+
}
|
|
169
159
|
}
|
|
170
160
|
}
|
|
171
161
|
}
|
|
172
|
-
av_packet_unref(packet
|
|
162
|
+
av_packet_unref(packet);
|
|
173
163
|
}
|
|
174
164
|
|
|
175
165
|
// Flush decoder
|
|
176
166
|
avcodec_send_packet(codec_ctx, nullptr);
|
|
177
|
-
while (avcodec_receive_frame(codec_ctx, frame
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
167
|
+
while (avcodec_receive_frame(codec_ctx, frame) == 0) {
|
|
168
|
+
int out_samples = swr_get_out_samples(swr_ctx, frame->nb_samples);
|
|
169
|
+
if (out_samples > max_resampled_samples) {
|
|
170
|
+
if (resampled_data != nullptr) {
|
|
171
|
+
av_freep(&resampled_data[0]);
|
|
172
|
+
av_freep(&resampled_data);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
max_resampled_samples = out_samples;
|
|
176
|
+
ret = av_samples_alloc_array_and_samples(
|
|
177
|
+
&resampled_data,
|
|
178
|
+
nullptr,
|
|
179
|
+
channels,
|
|
180
|
+
max_resampled_samples,
|
|
181
|
+
AV_SAMPLE_FMT_S16,
|
|
182
|
+
0);
|
|
183
|
+
|
|
184
|
+
if (ret < 0) {
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
int converted_samples = swr_convert(
|
|
190
|
+
swr_ctx,
|
|
184
191
|
resampled_data,
|
|
185
|
-
max_resampled_samples
|
|
192
|
+
max_resampled_samples,
|
|
193
|
+
(const uint8_t **)frame->data,
|
|
194
|
+
frame->nb_samples);
|
|
195
|
+
|
|
196
|
+
if (converted_samples > 0) {
|
|
197
|
+
size_t current_size = buffer.size();
|
|
198
|
+
size_t new_samples = converted_samples * channels;
|
|
199
|
+
buffer.resize(current_size + new_samples);
|
|
200
|
+
memcpy(
|
|
201
|
+
buffer.data() + current_size,
|
|
202
|
+
resampled_data[0],
|
|
203
|
+
new_samples * sizeof(int16_t));
|
|
204
|
+
|
|
205
|
+
framesRead += converted_samples;
|
|
206
|
+
}
|
|
186
207
|
}
|
|
187
208
|
|
|
188
|
-
|
|
189
|
-
|
|
209
|
+
if (resampled_data != nullptr) {
|
|
210
|
+
av_freep(&resampled_data[0]);
|
|
211
|
+
av_freep(&resampled_data);
|
|
212
|
+
}
|
|
213
|
+
swr_free(&swr_ctx);
|
|
190
214
|
av_channel_layout_uninit(&out_ch_layout);
|
|
215
|
+
av_frame_free(&frame);
|
|
216
|
+
av_packet_free(&packet);
|
|
191
217
|
|
|
192
218
|
return buffer;
|
|
193
219
|
}
|
|
194
220
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
return i;
|
|
221
|
+
std::vector<int16_t> decodeWithMemoryBlock(const void *data, size_t size, const int channel_count, int sample_rate) {
|
|
222
|
+
if (data == nullptr || size == 0) {
|
|
223
|
+
return {};
|
|
199
224
|
}
|
|
200
|
-
}
|
|
201
|
-
return -1;
|
|
202
|
-
}
|
|
203
225
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
&codec_ctx) {
|
|
209
|
-
audio_stream_index = findAudioStreamIndex(fmt_ctx);
|
|
210
|
-
if (audio_stream_index == -1) {
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
226
|
+
MemoryIOContext io_ctx;
|
|
227
|
+
io_ctx.data = static_cast<const uint8_t *>(data);
|
|
228
|
+
io_ctx.size = size;
|
|
229
|
+
io_ctx.pos = 0;
|
|
213
230
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
231
|
+
constexpr size_t buffer_size = 4096;
|
|
232
|
+
uint8_t *io_buffer = static_cast<uint8_t *>(av_malloc(buffer_size));
|
|
233
|
+
if (io_buffer == nullptr) {
|
|
234
|
+
return {};
|
|
235
|
+
}
|
|
219
236
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
237
|
+
AVIOContext *avio_ctx = avio_alloc_context(
|
|
238
|
+
io_buffer, buffer_size, 0, &io_ctx, read_packet, nullptr, seek_packet);
|
|
224
239
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (avcodec_open2(codec_ctx.get(), codec, nullptr) < 0) {
|
|
230
|
-
return false;
|
|
231
|
-
}
|
|
240
|
+
if (avio_ctx == nullptr) {
|
|
241
|
+
av_free(io_buffer);
|
|
242
|
+
return {};
|
|
243
|
+
}
|
|
232
244
|
|
|
233
|
-
|
|
234
|
-
|
|
245
|
+
// Create format context and set custom IO
|
|
246
|
+
AVFormatContext *fmt_ctx = avformat_alloc_context();
|
|
247
|
+
if (fmt_ctx == nullptr) {
|
|
248
|
+
avio_context_free(&avio_ctx);
|
|
249
|
+
return {};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
fmt_ctx->pb = avio_ctx;
|
|
253
|
+
|
|
254
|
+
// Open input from memory
|
|
255
|
+
if (avformat_open_input(&fmt_ctx, nullptr, nullptr, nullptr) < 0) {
|
|
256
|
+
avformat_free_context(fmt_ctx);
|
|
257
|
+
avio_context_free(&avio_ctx);
|
|
258
|
+
return {};
|
|
259
|
+
}
|
|
235
260
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
int output_sample_rate =
|
|
243
|
-
(sample_rate > 0) ? sample_rate : codec_ctx->sample_rate;
|
|
244
|
-
int output_channel_count = codec_ctx->ch_layout.nb_channels;
|
|
245
|
-
|
|
246
|
-
std::vector<float> decoded_buffer = readAllPcmFrames(
|
|
247
|
-
fmt_ctx,
|
|
248
|
-
codec_ctx,
|
|
249
|
-
output_sample_rate,
|
|
250
|
-
output_channel_count,
|
|
251
|
-
audio_stream_index,
|
|
252
|
-
framesRead);
|
|
261
|
+
// Find stream info
|
|
262
|
+
if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
|
|
263
|
+
avformat_close_input(&fmt_ctx);
|
|
264
|
+
avio_context_free(&avio_ctx);
|
|
265
|
+
return {};
|
|
266
|
+
}
|
|
253
267
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
268
|
+
int audio_stream_index = -1;
|
|
269
|
+
for (int i = 0; i < fmt_ctx->nb_streams; i++) {
|
|
270
|
+
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
|
271
|
+
audio_stream_index = i;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (audio_stream_index == -1) {
|
|
277
|
+
avformat_close_input(&fmt_ctx);
|
|
278
|
+
avio_context_free(&avio_ctx);
|
|
279
|
+
return {};
|
|
280
|
+
}
|
|
257
281
|
|
|
258
|
-
|
|
259
|
-
auto audioBus = std::make_shared<AudioBus>(
|
|
260
|
-
outputFrames, output_channel_count, output_sample_rate);
|
|
282
|
+
AVCodecParameters *codecpar = fmt_ctx->streams[audio_stream_index]->codecpar;
|
|
261
283
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
284
|
+
// Find decoder
|
|
285
|
+
const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
|
|
286
|
+
if (codec == nullptr) {
|
|
287
|
+
avformat_close_input(&fmt_ctx);
|
|
288
|
+
avio_context_free(&avio_ctx);
|
|
289
|
+
return {};
|
|
266
290
|
}
|
|
267
|
-
}
|
|
268
|
-
return std::make_shared<AudioBuffer>(audioBus);
|
|
269
|
-
}
|
|
270
291
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
292
|
+
// Allocate and setup codec context
|
|
293
|
+
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
|
|
294
|
+
if (codec_ctx == nullptr) {
|
|
295
|
+
avformat_close_input(&fmt_ctx);
|
|
296
|
+
avio_context_free(&avio_ctx);
|
|
297
|
+
return {};
|
|
298
|
+
}
|
|
276
299
|
|
|
277
|
-
|
|
300
|
+
if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
|
|
301
|
+
avcodec_free_context(&codec_ctx);
|
|
302
|
+
avformat_close_input(&fmt_ctx);
|
|
303
|
+
avio_context_free(&avio_ctx);
|
|
304
|
+
return {};
|
|
305
|
+
}
|
|
278
306
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
307
|
+
if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
|
|
308
|
+
avcodec_free_context(&codec_ctx);
|
|
309
|
+
avformat_close_input(&fmt_ctx);
|
|
310
|
+
avio_context_free(&avio_ctx);
|
|
311
|
+
return {};
|
|
312
|
+
}
|
|
285
313
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
avio_alloc_context(
|
|
289
|
-
io_buffer.get(),
|
|
290
|
-
buffer_size,
|
|
291
|
-
0,
|
|
292
|
-
&io_ctx,
|
|
293
|
-
read_packet,
|
|
294
|
-
nullptr,
|
|
295
|
-
seek_packet),
|
|
296
|
-
[](AVIOContext *ctx) { avio_context_free(&ctx); });
|
|
297
|
-
if (avio_ctx == nullptr) {
|
|
298
|
-
return nullptr;
|
|
299
|
-
}
|
|
314
|
+
// Get actual channel count from the decoded stream
|
|
315
|
+
int actual_channels = codec_ctx->ch_layout.nb_channels;
|
|
300
316
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
317
|
+
// Validate channel count
|
|
318
|
+
if (actual_channels <= 0 || actual_channels > 8) {
|
|
319
|
+
avcodec_free_context(&codec_ctx);
|
|
320
|
+
avformat_close_input(&fmt_ctx);
|
|
321
|
+
avio_context_free(&avio_ctx);
|
|
322
|
+
return {};
|
|
323
|
+
}
|
|
306
324
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
325
|
+
// Decode all frames
|
|
326
|
+
size_t framesRead = 0;
|
|
327
|
+
std::vector<int16_t> decoded_buffer = readAllPcmFrames(
|
|
328
|
+
fmt_ctx, codec_ctx, sample_rate, audio_stream_index, channel_count, framesRead);
|
|
311
329
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
330
|
+
// Cleanup - Note: avio_context_free will free the io_buffer
|
|
331
|
+
avcodec_free_context(&codec_ctx);
|
|
332
|
+
avformat_close_input(&fmt_ctx);
|
|
333
|
+
avio_context_free(&avio_ctx);
|
|
315
334
|
|
|
316
|
-
|
|
317
|
-
|
|
335
|
+
if (framesRead == 0 || decoded_buffer.empty()) {
|
|
336
|
+
return {};
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
return decoded_buffer;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
std::vector<int16_t> decodeWithFilePath(const std::string &path, const int channel_count, int sample_rate) {
|
|
343
|
+
if (path.empty()) {
|
|
344
|
+
return {};
|
|
318
345
|
}
|
|
319
346
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
347
|
+
AVFormatContext *fmt_ctx = nullptr;
|
|
348
|
+
if (avformat_open_input(&fmt_ctx, path.c_str(), nullptr, nullptr) < 0) {
|
|
349
|
+
return {};
|
|
350
|
+
}
|
|
351
|
+
if (avformat_find_stream_info(fmt_ctx, nullptr) < 0) {
|
|
352
|
+
avformat_close_input(&fmt_ctx);
|
|
353
|
+
return {};
|
|
354
|
+
}
|
|
323
355
|
int audio_stream_index = -1;
|
|
324
|
-
|
|
325
|
-
|
|
356
|
+
for (int i = 0; i < fmt_ctx->nb_streams; i++) {
|
|
357
|
+
if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
|
|
358
|
+
audio_stream_index = i;
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (audio_stream_index == -1) {
|
|
363
|
+
avformat_close_input(&fmt_ctx);
|
|
364
|
+
return {};
|
|
326
365
|
}
|
|
327
366
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
367
|
+
AVCodecParameters *codecpar = fmt_ctx->streams[audio_stream_index]->codecpar;
|
|
368
|
+
const AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
|
|
369
|
+
if (codec == nullptr) {
|
|
370
|
+
avformat_close_input(&fmt_ctx);
|
|
371
|
+
return {};
|
|
372
|
+
}
|
|
373
|
+
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
|
|
374
|
+
if (codec_ctx == nullptr) {
|
|
375
|
+
avformat_close_input(&fmt_ctx);
|
|
376
|
+
return {};
|
|
377
|
+
}
|
|
331
378
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
return nullptr;
|
|
379
|
+
if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
|
|
380
|
+
avcodec_free_context(&codec_ctx);
|
|
381
|
+
avformat_close_input(&fmt_ctx);
|
|
382
|
+
return {};
|
|
337
383
|
}
|
|
338
384
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
385
|
+
if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
|
|
386
|
+
avcodec_free_context(&codec_ctx);
|
|
387
|
+
avformat_close_input(&fmt_ctx);
|
|
388
|
+
return {};
|
|
389
|
+
}
|
|
342
390
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
[](AVFormatContext *ctx) { avformat_close_input(&ctx); });
|
|
391
|
+
size_t framesRead = 0;
|
|
392
|
+
std::vector<int16_t> decoded_buffer = readAllPcmFrames(
|
|
393
|
+
fmt_ctx, codec_ctx, sample_rate, audio_stream_index, channel_count, framesRead);
|
|
347
394
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}
|
|
395
|
+
avcodec_free_context(&codec_ctx);
|
|
396
|
+
avformat_close_input(&fmt_ctx);
|
|
351
397
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
nullptr, [](AVCodecContext *ctx) { avcodec_free_context(&ctx); });
|
|
355
|
-
int audio_stream_index = -1;
|
|
356
|
-
if (!setupDecoderContext(fmt_ctx.get(), audio_stream_index, codec_ctx)) {
|
|
357
|
-
return nullptr;
|
|
398
|
+
if (framesRead == 0 || decoded_buffer.empty()) {
|
|
399
|
+
return {};
|
|
358
400
|
}
|
|
359
401
|
|
|
360
|
-
return
|
|
361
|
-
fmt_ctx.get(), codec_ctx.get(), audio_stream_index, sample_rate);
|
|
402
|
+
return decoded_buffer;
|
|
362
403
|
}
|
|
363
404
|
|
|
364
405
|
} // namespace audioapi::ffmpegdecoder
|