-
-
Save roxlu/6d8765f290a4e8ef6cbe01020b1d129e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <AudioConverterFfmpeg.h> | |
namespace poly { | |
/* -------------------------------------------------------- */ | |
static AVSampleFormat audiobitsize_to_avsampleformat(AudioBitSize bs, bool isInterleaved); | |
static uint64_t audiomode_to_avchannellayout(AudioMode mode); | |
static int audiomode_to_numchannels(AudioMode mode); | |
/* -------------------------------------------------------- */ | |
AudioConverterFfmpeg::AudioConverterFfmpeg() | |
:listener(NULL) | |
,ctx(NULL) | |
,src_rate(-1) | |
,dst_rate(-1) | |
,dst_chanlayout(0) | |
,dst_format(AV_SAMPLE_FMT_NONE) | |
,dst_nchannels(-1) | |
,dst_nbytes_allocated(0) | |
,dst_linesize(-1) | |
,dst_max_samples(-1) | |
,dst_data(NULL) | |
{ | |
} | |
AudioConverterFfmpeg::~AudioConverterFfmpeg() { | |
} | |
int AudioConverterFfmpeg::init(AudioSettings from, AudioSettings to, AudioConverterListener* lis) { | |
int r = 0; | |
if (NULL == lis) { | |
SX_ERROR("Listener is NULL."); | |
r = -1; | |
goto error; | |
} | |
convert_from = from; | |
convert_to = to; | |
listener = lis; | |
src_rate = audio_samplerate_get_int(from.samplerate); | |
dst_chanlayout = audiomode_to_avchannellayout(to.mode); | |
dst_rate = audio_samplerate_get_int(to.samplerate); | |
dst_format = audiobitsize_to_avsampleformat(to.bitsize, to.is_interleaved); | |
dst_nchannels = av_get_channel_layout_nb_channels(audiomode_to_avchannellayout(to.mode)); | |
ctx = swr_alloc(); | |
if (NULL == ctx) { | |
SX_ERROR("Failed to allocate the resample context."); | |
r = -2; | |
goto error; | |
} | |
av_opt_set_int(ctx, "in_channel_layout", audiomode_to_avchannellayout(from.mode), 0); | |
av_opt_set_int(ctx, "in_sample_rate", src_rate, 0); | |
av_opt_set_sample_fmt(ctx, "in_sample_fmt", audiobitsize_to_avsampleformat(from.bitsize, from.is_interleaved), 0); | |
av_opt_set_int(ctx, "out_channel_layout", dst_chanlayout, 0); | |
av_opt_set_int(ctx, "out_sample_rate", dst_rate, 0); | |
av_opt_set_sample_fmt(ctx, "out_sample_fmt", dst_format, 0); | |
if ( (r = swr_init(ctx)) < 0) { | |
SX_ERROR("Failed to initialize the resample context."); | |
r = -3; | |
goto error; | |
} | |
error: | |
if (r < 0) { | |
shutdown(); | |
} | |
return r; | |
} | |
int AudioConverterFfmpeg::shutdown() { | |
int r = 0; | |
if (NULL != ctx) { | |
swr_free(&ctx); | |
ctx = NULL; | |
} | |
if (NULL != dst_data) { | |
free(dst_data); | |
dst_data = NULL; | |
} | |
src_rate = -1; | |
dst_rate = -1; | |
dst_format = AV_SAMPLE_FMT_NONE; | |
dst_nchannels = -1; | |
dst_nbytes_allocated = -1; | |
dst_linesize = -1; | |
dst_max_samples = -1; | |
return r; | |
} | |
int AudioConverterFfmpeg::convert(void* data, size_t nbytes, size_t nframes) { | |
if (NULL == data) { | |
SX_ERROR("data is NULL."); | |
return -1; | |
} | |
if (0 == nbytes) { | |
SX_ERROR("nbytes is 0."); | |
return -2; | |
} | |
if (0 == nframes) { | |
SX_ERROR("nframes is 0."); | |
return -3; | |
} | |
if (NULL == ctx) { | |
SX_ERROR("ctx is NULL."); | |
return -4; | |
} | |
int r = 0; | |
int delayed_samples = swr_get_delay(ctx, src_rate); | |
int num_dst_samples = av_rescale_rnd(delayed_samples + nframes, dst_rate, src_rate, AV_ROUND_UP); | |
int nbytes_needed = av_samples_get_buffer_size(NULL, dst_nchannels, nframes, dst_format, 1); | |
/* Allocate or reallocate the destination buffer. */ | |
if (nbytes_needed > dst_nbytes_allocated) { | |
if (NULL == dst_data) { | |
dst_data = (uint8_t*)malloc(nbytes_needed); | |
if (NULL == dst_data) { | |
SX_ERROR("Failed to allocate the destination buffer of %d bytes.", nbytes_needed); | |
return -1; | |
} | |
} | |
else { | |
dst_data = (uint8_t*)realloc(dst_data, nbytes_needed); | |
if (NULL == dst_data) { | |
SX_ERROR("Failed to reallocate the destination buffer of %d bytes.", nbytes_needed); | |
return -2; | |
} | |
} | |
dst_nbytes_allocated = nbytes_needed; | |
} | |
r = swr_convert(ctx, | |
&dst_data, | |
num_dst_samples, | |
(const uint8_t**)data, | |
nframes | |
); | |
return r; | |
} | |
/* -------------------------------------------------------- */ | |
static AVSampleFormat audiobitsize_to_avsampleformat(AudioBitSize bs, bool isInterleaved) { | |
if (false == isInterleaved) { | |
/* Planar */ | |
switch (bs) { | |
case AUDIO_BITSIZE_S16: { return AV_SAMPLE_FMT_S16P; } | |
case AUDIO_BITSIZE_S32: { return AV_SAMPLE_FMT_S32P; } | |
case AUDIO_BITSIZE_F32: { return AV_SAMPLE_FMT_FLTP; } | |
default: { | |
SX_ERROR("Unhandled AudioBitSize; cannot convert to AVSampleFormat. (exiting)."); | |
exit(EXIT_FAILURE); | |
} | |
}; | |
} | |
else { | |
/* Non-Planar */ | |
switch (bs) { | |
case AUDIO_BITSIZE_S16: { return AV_SAMPLE_FMT_S16; } | |
case AUDIO_BITSIZE_S32: { return AV_SAMPLE_FMT_S32; } | |
case AUDIO_BITSIZE_F32: { return AV_SAMPLE_FMT_FLT; } | |
default: { | |
SX_ERROR("Unhandled AudioBitSize; cannot convert to AVSampleFormat. (exiting)."); | |
exit(EXIT_FAILURE); | |
} | |
} | |
} | |
} | |
static uint64_t audiomode_to_avchannellayout(AudioMode mode) { | |
if (AUDIO_MODE_STEREO == mode) { | |
return AV_CH_LAYOUT_STEREO; | |
} | |
else if (AUDIO_MODE_MONO == mode) { | |
return AV_CH_LAYOUT_MONO; | |
} | |
else { | |
SX_ERROR("Unhandled AudioMode; cannot convert to avchannellayout. (exiting)."); | |
exit(EXIT_FAILURE); | |
} | |
} | |
static int audiomode_to_numchannels(AudioMode mode) { | |
if (AUDIO_MODE_STEREO == mode) { | |
return 2; | |
} | |
else if (AUDIO_MODE_MONO == mode) { | |
return 1; | |
} | |
else { | |
SX_ERROR("Unhandled AudioMode; cannot convert to number of channels.. (exiting)."); | |
exit(EXIT_FAILURE); | |
} | |
} | |
/* -------------------------------------------------------- */ | |
} /* namespace poly */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef POLY_AUDIO_CONVERTER_FFMPEG_H | |
#define POLY_AUDIO_CONVERTER_FFMPEG_H | |
#include <poly/AudioTypes.h> | |
#include <poly/AudioSettings.h> | |
#include <poly/AudioConverterListener.h> | |
extern "C" { | |
# include <libavutil/opt.h> | |
# include <libavutil/channel_layout.h> | |
# include <libswresample/swresample.h> | |
//#include <libavutil/samplefmt.h> | |
} | |
namespace poly { | |
class AudioConverterFfmpeg { | |
public: | |
AudioConverterFfmpeg(); | |
~AudioConverterFfmpeg(); | |
int init(AudioSettings convertFrom, AudioSettings convertTo, AudioConverterListener* lis); | |
int shutdown(); | |
int convert(void* data, size_t nbytes, size_t nframes); | |
private: | |
AudioConverterListener* listener; | |
AudioSettings convert_from; | |
AudioSettings convert_to; | |
SwrContext* ctx; | |
int src_rate; | |
int dst_rate; | |
int64_t dst_chanlayout; | |
AVSampleFormat dst_format; | |
int dst_nchannels; | |
int dst_nbytes_allocated; | |
int dst_linesize; | |
uint8_t* dst_data; | |
int dst_max_samples; | |
}; | |
} /* namespace poly */ | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Process 15070 stopped | |
* thread #8: tid = 0x563156, 0x000000010008b7dc test_ffmpeg_audio_converter_debug`___lldb_unnamed_function39$$test_ffmpeg_audio_converter_debug, name = 'com.apple.audio.IOThread.client', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) | |
frame #0: 0x000000010008b7dc test_ffmpeg_audio_converter_debug`___lldb_unnamed_function39$$test_ffmpeg_audio_converter_debug | |
test_ffmpeg_audio_converter_debug`___lldb_unnamed_function39$$test_ffmpeg_audio_converter_debug: | |
-> 0x10008b7dc <+0>: movdqa xmm0, xmmword ptr [rsi + 8*rdx] | |
0x10008b7e1 <+5>: movdqa xmm2, xmmword ptr [rsi + 8*rdx + 0x10] | |
0x10008b7e7 <+11>: movdqa xmm1, xmm0 | |
0x10008b7eb <+15>: shufps xmm0, xmm2, 0x88 ; xmm0 = xmm0[0,2],xmm2[0,2] | |
(lldb) bt | |
* thread #8: tid = 0x563156, 0x000000010008b7dc test_ffmpeg_audio_converter_debug`___lldb_unnamed_function39$$test_ffmpeg_audio_converter_debug, name = 'com.apple.audio.IOThread.client', stop reason = EXC_BAD_ACCESS (code=1, address=0x0) | |
* frame #0: 0x000000010008b7dc test_ffmpeg_audio_converter_debug`___lldb_unnamed_function39$$test_ffmpeg_audio_converter_debug | |
frame #1: 0x000000010007bda0 test_ffmpeg_audio_converter_debug`swri_audio_convert(ctx=0x0000607000006980, out=0x000062f0000033d0, in=0x000062f0000031b0, len=<unavailable>) + 576 at audioconvert.c:229 | |
frame #2: 0x00000001000891b7 test_ffmpeg_audio_converter_debug`swr_convert_internal(s=0x000062f000000400, out=<unavailable>, out_count=558, in=0x000062f0000031b0, in_count=512) + 455 at swresample.c:634 | |
frame #3: 0x00000001000889fd test_ffmpeg_audio_converter_debug`swr_convert(s=0x000062f000000400, out_arg=<unavailable>, out_count=558, in_arg=<unavailable>, in_count=0) + 941 at swresample.c:759 | |
frame #4: 0x000000010005e5d3 test_ffmpeg_audio_converter_debug`poly::AudioConverterFfmpeg::convert(this=0x00000001000bf060, data=0x0000621000076d00, nbytes=4096, nframes=512) + 2419 at AudioConverterFfmpeg.cpp:151 | |
frame #5: 0x0000000100007237 test_ffmpeg_audio_converter_debug`on_audio(data=0x0000621000076d00, nbytes=4096, nframes=512, user=0x0000000000000000) + 167 at test_ffmpeg_audio_converter.cpp:140 | |
frame #6: 0x000000010001d1bd test_ffmpeg_audio_converter_debug`poly::read_callback(instream=0x000061700000f580, frameCountMin=512, frameCountMax=512) + 3805 at AudioCaptureSoundIo.cpp:521 | |
frame #7: 0x0000000100069a01 test_ffmpeg_audio_converter_debug`read_callback_ca(userdata=0x000061700000f580, io_action_flags=0x0000700000322c54, in_time_stamp=0x00000001067280a0, in_bus_number=1, in_number_frames=512, io_data=0x0000000000000000) + 865 at coreaudio.c:1151 | |
frame #8: 0x000000010647e799 CoreAudio`AUHAL::AUIOProc(unsigned int, AudioTimeStamp const*, AudioBufferList const*, AudioTimeStamp const*, AudioBufferList*, AudioTimeStamp const*, void*) + 2221 | |
frame #9: 0x00007fff8c423ea3 CoreAudio`HALC_ProxyIOContext::IOWorkLoop() + 2535 | |
frame #10: 0x00007fff8c4233ee CoreAudio`HALC_ProxyIOContext::IOThreadEntry(void*) + 88 | |
frame #11: 0x00007fff8c4232c3 CoreAudio`HALB_IOThread::Entry(void*) + 75 | |
frame #12: 0x00007fff8e010c13 libsystem_pthread.dylib`_pthread_body + 131 | |
frame #13: 0x00007fff8e010b90 libsystem_pthread.dylib`_pthread_start + 168 | |
frame #14: 0x00007fff8e00e375 libsystem_pthread.dylib`thread_start + 13 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment