I am getting audio from a microphone with PortAudio (PA). I need to then resample this audio to 44,100KHz. I'm attempting to do this with FFmpeg. Currently, the mic I'm testing with has a sample rate of 48,000KHz, but this won't always be the case when the application is used. Anyway, whenever I attempt to resample with swr_convert
, I get a segmentation fault. I am initializing the SwrContext
with
this->swr_ctx = swr_alloc_set_opts(
nullptr, // No current context
num_channels, // The number of channls I'm getting from PA
AV_SAMPLE_FMT_S16, // 16 bit Signed, should correspond to paInt16
FINAL_SAMPLE_RATE, // 44100
num_channels, // The number of channls I'm getting from PA
AV_SAMPLE_FMT_S16, // 16 bit Signed, should correspond to paInt16
this->source_sample_rate, // Mic I'm testing with currently is 44800, but depends on source
0, // Logging offset (0 is what examples use, so I did too)
nullptr // "parent logging context, can be NULL"
);
I know PA is working right, as the project works if I hard-code the sample rate in other aspects of this project. The callback looks like this
auto paCallback( const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ) -> int {
// Calls class's callback handler
return ((Audio*)userData)->classPaCallback((const uint8_t **)inputBuffer);
}
// Class callback handler
auto Audio::classPaCallback(const uint8_t **inputBuffer) -> int {
// This line throws SIGSEGV
int out_count = swr_convert(swr_ctx, this->resample_buffer, BUFFER_CHUNK_SIZE, inputBuffer, this->source_buffer_size);
if (out_count < 0)
throw std::runtime_error("Error resampling audio");
}
// Add data to buffers to handle outside of callback context (This is a special context according to PA docs)
return 0;
}
Playing around with the swr_convert
line, I changed the out_count
and in_count
parameters (BUFFER_CHUNK_SIZE
and this->source_buffer_size
) to 0 to make sure that the code would at least run, that worked. I then changed one of them to 1, and left the other at 0, to test which buffer access was throwing the SIGSEGV, and it was thrown when the in_count
(buffer from PA) was not 0. What am I doing wrong when passing the audio from PA to FFMpeg?
I do know that the PA audio is "interleaved" (I.E. input[0] is the first sample from channel 0, input[1] is the first sample from channel 1, ect.). Is this also the format that FFMpeg uses, or should I create a different SwrContext
for each channel?
In case this is helpful, this->resample_buffer
is successfully initialized with
av_samples_alloc_array_and_samples(
&this->resample_buffer, // Buffer
nullptr, // "linesize", not used from what I could tell
this->num_channels, // number of channels expected
BUFFER_CHUNK_SIZE, // Number of frames to be stored per channel
AV_SAMPLE_FMT_S16, // 16 bit Signed, should correspond to paInt16
0 // For alignment, not needed here
);