I have the following code in a loop (it gets called every 1/4 second).
(I have removed the rest of the code to narrow the problem down to the following).
dispatch_async(self.audioQueue, ^{
AudioBufferList *aacBufferList;
aacBufferList = malloc(sizeof(AudioBufferList));
aacBufferList->mNumberBuffers = 1;
aacBufferList->mBuffers[0].mNumberChannels = aacStreamFormat.mChannelsPerFrame;
aacBufferList->mBuffers[0].mDataByteSize = maxOutputPacketSize;
aacBufferList->mBuffers[0].mData = (void *)(calloc(maxOutputPacketSize, 1));
// Other code was here. As stated above, I have removed it to isolate the problem to the allocating and freeing of memory for the AudioBufferList
freeABL(aacBufferList);
}
And the freeABL function:
void freeABL(AudioBufferList *abl)
{
for (int i = 0; i < abl->mNumberBuffers; i++)
{
free(abl->mBuffers[i].mData);
abl->mBuffers[i].mData = NULL;
}
free(abl);
abl = NULL;
}
The problem I have, is every time this loops the memory consumption of my app increased, until I receive a memory warning.
Related
I am working on a project in which I have to store the datas of an ADC Stream on a µSD card. However even if I use a 16 bits buffer, I lose data from the ADC stream. My ADC is used with DMA and I use FATFS (WITHOUT DMA) and the SDMMC1 peripheral to fill a .bin file with the datas.
Do you have an idea to avoid this loss ?
Here is my project : https://github.com/mathieuchene/STM32H743ZI
I use a nucleo-h743zi2 Board, CubeIDE, and CubeMx in their last version.
EDIT 1
I tried to implement Colin's solution, it's better but I have a strange things in the middle of my acquisition. However when I increase the maximal count value or try to debug, the HardFault_Handler appears. I modified main.c file by creating 2 blocks (uint16_t blockX[BUFFERLENGTH/2]) and 2 flags for when adcBuffer is half filled or completely filled.
I also changed the while(1) part in main function like this
if (flagHlfCplt){
//flagCplt=0;
res = f_write(&SDFile, block1, strlen((char*)block1), (void *)&byteswritten);
memcpy(block2, adcBuffer, BUFFERLENGTH/2);
flagHlfCplt = 0;
count++;
}
if (flagCplt){
//flagHlfCplt=0;
res = f_write(&SDFile, block2, strlen((char*)block2), (void *)&byteswritten);
memcpy(block1, adcBuffer[(BUFFERLENGTH/2)-1], BUFFERLENGTH/2);
flagCplt = 0;
count++;
}
if (count == 10){
f_close(&SDFile);
HAL_ADC_Stop_DMA(&hadc1);
while(1){
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
HAL_Delay(1000);
}
}
}
EDIT 2
I modified my program. I set block 1 and block 2 with the length of BUFFERLENGTH and I added a pointer (*idx) to change the buffer which is filled. I don't have HardFault_Handler anymore but I still loose some datas from my adc's stream.
Here are the modification I made:
// my pointer and buffers
uint16_t block1[BUFFERLENGTH], block2[BUFFERLENGTH], *idx;
// init of pointer and adc start
idx=block1;
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)idx, BUFFERLENGTH);
// while(1) part
while (1)
{
if (flagCplt){
if (flagToChangeBuffer) {
idx=block1;
res = f_write(&SDFile, block2, strlen((char*)block2), (void *)&byteswritten);
flagCplt = 0;
flagToChangeBuffer=0;
count++;
}
else {
idx=block2;
res = f_write(&SDFile, block1, strlen((char*)block1), (void *)&byteswritten);
flagCplt = 0;
flagToChangeBuffer=1;
count++;
}
}
if (count == 150){
f_close(&SDFile);
HAL_ADC_Stop_DMA(&hadc1);
while(1){
HAL_GPIO_TogglePin(LD1_GPIO_Port, LD1_Pin);
HAL_Delay(1000);
}
}
}
Does someone know how to solve my matter with these loss?
Best Regards
Mathieu
I'm facing some problem with gpu resize using opencv.
Here is my code:
#define MX 500
#define ASYNC 0
class job {
public:
cv::cuda::GpuMat gpuImage;
cv::cuda::Stream stream;
cv::Mat cpuImage;
~job() {
printf("job deleted\n");
}
};
void onComplete(int status, void* uData) {
job* _job = (job*) uData;
delete _job;
}
void resize(job* _job, vector<uchar> buffer) {
_job->cpuImage = cv::imdecode(buffer, cv::IMREAD_COLOR);
if (ASYNC) {
_job->gpuImage.upload(_job->cpuImage, _job->stream);
cv::cuda::resize(_job->gpuImage, _job->gpuImage, cv::Size(100, 100), 0, 0, cv::INTER_NEAREST, _job->stream);
_job->gpuImage.download(_job->cpuImage, _job->stream);
_job->stream.enqueueHostCallback(onComplete, _job);
// _job->stream.waitForCompletion();
} else {
_job->gpuImage.upload(_job->cpuImage);
cv::cuda::resize(_job->gpuImage, _job->gpuImage, cv::Size(100, 100), 0, 0, cv::INTER_NEAREST);
_job->gpuImage.download(_job->cpuImage);
delete _job;
}
}
vector<uchar> readFile(string filename) {
std::ifstream input(filename, std::ios::binary);
std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input),{});
return buffer;
}
int main() {
for (int i = 0; i < MX; i++) {
vector<uchar> buf = readFile("input.jpg");
job* _job = new job();
resize(_job, buf);
printFreeGPUMemory();
}
while (true) {
// wait
}
return 0;
}
When I run resize synchronously (ASYNC = 0), the code works perfectly fine. But when I run it asynchronously (ASYNC = 1), it seems that some gpu memory is lost somewhere despite the fact that I have deleted all created GpuMats and Streams. The more loop I run, the less free memory I have. is there a bug or part of my code is wrong?
problem solved.
here is the note of the callback from OpenCV docs:
Callbacks must not make any CUDA API calls. Callbacks must not perform
any synchronization that may depend on outstanding device work or
other callbacks that are not mandated to run earlier. Callbacks
without a mandated order (in independent streams) execute in undefined
order and may be serialized.
I had read the note but didn't actually notice that even deleting a cv::cuda::* still causes problems. So the solution is to avoid "touching" any cv::cuda::* in the callback, even deleting or releasing.
I'm using STM32F407VG Discovery Board and I've issue with DMA memory to memory transfer. I want to copy 32 bytes of data from one place in memory to other using DMA by writing copy_dma() function. In while loop i'm checking Transfer Complete flag but DMA never returns it. I want to ask where i'm making mistake? Maybe something in configuration is wrong. I'm using Standart Peripheral Libraries. Here's my code.
#include "stm32f4xx.h"
#define BUFFER_SIZE 32
uint8_t src_buffer[BUFFER_SIZE];
uint8_t dst_buffer[BUFFER_SIZE];
void copy_dma(void);
int main(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
int i;
DMA_InitTypeDef dma;
DMA_DeInit(DMA1_Stream4);
DMA_StructInit(&dma);
dma.DMA_Channel = DMA_Channel_1;
dma.DMA_PeripheralBaseAddr = (uint32_t)src_buffer;
dma.DMA_PeripheralInc = DMA_PeripheralInc_Enable;
dma.DMA_Memory0BaseAddr = (uint32_t)dst_buffer;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
dma.DMA_BufferSize = BUFFER_SIZE;
dma.DMA_DIR = DMA_DIR_MemoryToMemory;
dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
dma.DMA_Mode = DMA_Mode_Normal;
dma.DMA_Priority = DMA_Priority_High;
DMA_Init(DMA1_Stream4, &dma);
for (i = 0; i < BUFFER_SIZE; i++) {
src_buffer[i] = 100 + i;
}
copy_dma();
while(1) {
}
}
void copy_dma(void) {
DMA_Cmd(DMA1_Stream4, ENABLE);
while (DMA_GetFlagStatus(DMA1_Stream4, DMA_FLAG_TCIF4) == RESET);
}
In app note "Using the STM32F2 and STM32F4 DMA controller"(http://stm32.eefocus.com/download/index.php?act=down&id=6312)
is mentioned:
"Memory to memory (only DMA2 is able to do such transfer, in this mode, the circular and direct modes are not allowed.)"
So, try to use DMA2.
In addition to Mariusz Górka's awnser:
When using the DMA you need to know which memory region you are using. The stm32f4 has a memory section called Core Coupled Memory (CCM). The DMA does not have access to this region.
Check your map file and make sure your buffers are not in the region 0x10000000 - 0x1000FFFF.
I am using EZAudio and trying to write some samples generated by my softaware to an AudioBuffer provided by this library https://github.com/syedhali/EZAudio as seen in the example "Playback By Manual Override".
My code looks like this...
// Completely override the output callback function
- (void)
output:(EZOutput *)output
callbackWithActionFlags:(AudioUnitRenderActionFlags *)ioActionFlags
inTimeStamp:(const AudioTimeStamp *)inTimeStamp
inBusNumber:(UInt32)inBusNumber
inNumberFrames:(UInt32)inNumberFrames
ioData:(AudioBufferList *)ioData {
//grab latest sample from sample queue
if (currentAudioPiece == nil || currentAudioPiece.duration >= currentAudioPieceIndex) {
self.currentAudioPiece = sampleQueue.dequeue;
}
AudioBuffer audioBuffer = ioData->mBuffers[0];
if (true) {
for (int i = 0; i < audioBuffer.mDataByteSize; i++) {
uint8_t rofl[2048];
arc4random_buf(&rofl, 2048);
audioBuffer.mData = rofl;
}
return;
}
//... more code that I'll debug later...'
Essentially I am unable to get a sanity check that a random bunch of memory playing back should make some noise. I think the problem is with "audioBuffer.mData = rofl;". I'm rather confused about working with memory at void*.
jn_pdx is correct, you need to copy/fill mData instead of reassigning it.
- (void)
output:(EZOutput *)output
callbackWithActionFlags:(AudioUnitRenderActionFlags *)ioActionFlags
inTimeStamp:(const AudioTimeStamp *)inTimeStamp
inBusNumber:(UInt32)inBusNumber
inNumberFrames:(UInt32)inNumberFrames
ioData:(AudioBufferList *)ioData {
//grab latest sample from sample queue
if (currentAudioPiece == nil || currentAudioPiece.duration >= currentAudioPieceIndex) {
self.currentAudioPiece = sampleQueue.dequeue;
}
AudioBuffer audioBuffer = ioData->mBuffers[0];
if (true) {
arc4random_buf(audioBuffer.mData, audioBuffer.mDataByteSize);
return;
}
I've seen it said multiple times that there is no way to limit a Lua script's memory usage, including people jumping through hoops to prevent Lua scripts from creating functions and tables. But given that lua_newstate allows you to pass a custom allocator, couldn't one just use that to limit memory consumption? At worst, one could use an arena-based allocator and put a hard limit even on the amount of memory that could be used by fragmentation.
Am I missing something here?
static void *l_alloc_restricted (void *ud, void *ptr, size_t osize, size_t nsize)
{
const int MAX_SIZE = 1024; /* set limit here */
int *used = (int *)ud;
if(ptr == NULL) {
/*
* <http://www.lua.org/manual/5.2/manual.html#lua_Alloc>:
* When ptr is NULL, osize encodes the kind of object that Lua is
* allocating.
*
* Since we don’t care about that, just mark it as 0.
*/
osize = 0;
}
if (nsize == 0)
{
free(ptr);
*used -= osize; /* substract old size from used memory */
return NULL;
}
else
{
if (*used + (nsize - osize) > MAX_SIZE) /* too much memory in use */
return NULL;
ptr = realloc(ptr, nsize);
if (ptr) /* reallocation successful? */
*used += (nsize - osize);
return ptr;
}
}
To make Lua use your allocator, you can use
int *ud = malloc(sizeof(int)); *ud = 0;
lua_State *L = lua_State *lua_newstate (l_alloc_restricted, ud);
Note: I haven't tested the source, but it should work.