QAudioInput::byteReady() and QIODevice::read() giving different number of bytes - qt

I am having a doubt with the following code snippet…
const qint64 bytesReady = m_audioInput->bytesReady();
const qint64 bytesSpace = m_buffer.size() - m_dataLength;
const qint64 bytesToRead = qMin(bytesReady, bytesSpace);
const qint64 bytesRead = m_audioInputIODevice->read(m_buffer.data() + m_dataLength, bytesToRead);
bytesReady() method is giving me a particular number of bytes and am passing these number of bytes to the read() of QIODevice which will return me the number of bytes read.
The problem is that bytesRead is not equal to bytesToRead.
And am getting fixed number of bytes from read method i.e 320, 640, 960, 1280, etc. and this depends on byteToRead.

There is no direct relation between the QAudioInput::bytesReady() and the QIODevice on which it is writing its samples.
QAudioInput maintains internally a IO device (system dependent) to the audio system, which is analog to a read-only QIODevice.
When you call bytesReady, it returns the number of bytes available to be read, analog to QIODevice::bytesAvailable(). Those have not yet been written to the output QIODevice, so when you do the m_audioInputIODevice->read just after it, without processing events, you're actually getting the samples which have been written earlier, not the ones still in the audio buffer.
This, plus the buffering of the IODevice, explains why the numbers might be different, and I don't see a way to synchronize them together.
Actually, you should do:
const qint64 bytesRead = m_audioInputIODevice->read(m_buffer.data() + m_dataLength, bytesSpace);
to get whatever is available from the IODevice, up to your available buffer space.

Better yet:
Use ->readAll() which returns a QByteArray "qba"
...then use sz=qba.size() which will tell you what you GOT (may be zero)
...then do something with it using sz and qba.data();
...seems to be without bugs unlike much of QAudioInput, which is incredibly broken, for instance, arbitrary sample rate limit of 48000 under Windows but not OSX, pull mode uses foreground thread so will break up constantly in any real situation, bytesReady() is meaningless... Worst. Qt. Routine. Evar!

Related

How to use OpenCL to write directly to linux framebuffer with zero-copy?

I am using OpenCL to do some image processing and want to use it to write RGBA image directly to framebuffer. Workflow is shown below:
1) map framebuffer to user space.
2) create OpenCL buffer using clCreateBuffer with flags of "CL_MEM_ALLOC_HOST_PTR"
3) use clEnqueueMapBuffer to map the results to framebuffer.
However, it doesn't work. Nothing on the screen. Then I found that the mapped virtual address from framebuffer are not same as the virtual address mapped OpenCL. Has any body done a zero-copy move of data from GPU to framebuffer?Any help on what approach should I use for this?
Some key codes:
if ((fd_fb = open("/dev/fb0", O_RDWR, 0)) < 0) {
printf("Unable to open /dev/fb0\n");
return -1;
}
fb0 = (unsigned char *)mmap(0, fb0_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
...
cmDevSrc4 = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(cl_uchar) * imagesize * 4, NULL, &status);
...
fb0 = (unsigned char*)clEnqueueMapBuffer(cqCommandQueue, cmDevSrc4, CL_TRUE, CL_MAP_READ, 0, sizeof(cl_uchar) * imagesize * 4, 0, NULL, NULL, &ciErr);
For zero-copy with an existing buffer you need to use CL_MEM_USE_HOST_PTR flag in the clCreateBuffer() function call. In addition you need give the pointer to the existing buffer as second to last argument.
I don't know how linux framebuffer internally works but it is possible that even with the zero-copy from device to host it leads to extra copying the data to GPU for rendering. So you might want to render the OpenCL buffer directly with OpenGL. Check out cl_khr_gl_sharing extension for OpenCL.
I don't know OpenCL yet, I was just doing a search to find out about writing to the framebuffer from it and hit your post. Opening it and mmapping it like in your code looks good.
I've done that with the CPU: https://sourceforge.net/projects/fbgrad/
That doesn't always work, it depends on the computer. I'm on an old Dell Latitude D530 and not only can't I write to the framebuffer but there's no GPU, so no advantage to using OpenCL over using the CPU. If you have a /dev/fb0 and you can get something on the screen with
cat /dev/random > /dev/fb0
Then you might have a chance from OpenCL. With a Mali at least there's a way to pass a pointer from the CPU to the GPU. You may need to add some offset (true on a Raspberry Pi I think). And it could be double-buffered by Xorg, there are lots of reasons why it might not work.

Run arduino sketch from an sd card

Is it possible to put a sketch (.HEX file) to an SD card and run it from there?
My objective is to utilize SD storage instead of flash memory for a program.
If yes, are there any libraries doing exactly this?
All i found was "flashing arduino from sd card", which is not what i need.
UPDATE:
the sketch's loop calling is implemented in the bootloader.
so i assume there is something like this in the bootloader:
while(true)
{
call_sketch_loop();
}
can it be changed to this? :
//signature changed from void loop() to int loop()
while(true)
{
int retval = call_sketch_loop(); //get loop call's return value
if( 0 == retval )
continue; // if 0, iterate the loop as usual
else
{
//copy 1.HEX from sd to flash and reboot
copy_hex_from_sd_to_flash( retval + ".HEX" );
reboot();
}
}
change loop singature to int loop()
put {int}.HEX files to an SD card - 1.HEX , 2.HEX , 3.HEX
the loop() call returns 0
continue with next iteration as usual
the loop() call returns 2
copy file 2.HEX from SD card into program flash memory
reboot device
with this approach, we can run flash-capacity-exceeding programs if we split them up to smaller subprograms.
The technical term you are looking for is "SD card bootloader".
Have you looked into this: "https://github.com/thseiler/embedded/tree/master/avr/2boots"?
As far as I understand, 2boot will first load the hex into the flash and then execute it from there. This is not exactly what you are looking for (you want to load it directly to RAM, right?).
The problem with what you are looking for is that arduino's RAM is really small. And there is liittle advantage in loading directly to RAM. Therfore such library might not exist at all.
I can sugget a poor-mans approach for doing this. First write a sketch that contains a function that have an infinite loop inside it and inside this loop, put the code of your desired "loop". In the setup of the sketch take the pointer to this function and write sufficient ammount of bytes into a binary file on the SD card.
Then upload another sketch wich has an empty buffer. This sketch will load the binary file into it and refernce to it's beginning as a pointer to a function. Viola, you can now execute your "loop".
This is ugly and unless you have very specific and isoteric need for loading directly into RAM, I suggest to try the 2boot library.

How to measure the amount of memory or RAM consumed by a code on Arduino Mega or Due

Can anybody tell me how to measure the consumed RAM for a particular code running on Arduino Mega or Due.
There is two kinds of numbers to this question:
Global static usage and current run time.
The static estimated usage can be determined by adding the following line to (if it does not already exist)
.\arduino-1.5.5\hardware\arduino\avr\boards.txt
uno.upload.maximum_ram_size=2048
This then allows the compiler to output the additional 2nd line in the following example in the IDE's result window
Binary sketch size: 25,880 bytes (of a 32,256 byte maximum)
Estimated used SRAM memory: 990 bytes (of a 2048 byte maximum)
To see the amount of memory used at any given point. Including memory space currently in use, that exists while only in functions and members. This includes the HEAP and such. I use the following MemoryFree library at specific points in the code to reveal the high-water. The readme explains how to save unnecessarily/unintentionally used RAM by prints.
Note: That while the original Arduino IDE 1.0.5's boards.txt files does contain these ram_sizes, it does not actually use display usage. Where the original Arduino IDE 1.5.5 does, along with Arduino ERW 1.0.5 does (an non-supported fork).
In my Arduino IDE 2.1.0
I edit the file: /usr/share/arduino/hardware/arduino/boards.txt
but the second line don't appear
After read:
check-ram-memory-usage-arduino-optimization
measuring-free-memory
I tried:
Show vervose output during compilation
and use avr-size /tmp/build4042914391435450796.tmp/XXXXXXX.cpp.elf
then i get my memory used
Best Regards!
int freeRam () {
extern int __heap_start, *__brkval;
int v;
int fr = (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
Serial.print("Free ram: ");
Serial.println(fr);
}

Qt QSharedMemory Segmentation Faults after Several Successful Writes

I'm using QSharedMemory to store some data and want to subsequently append data to what is contained there. So I call the following code several times with new data. The "audioBuffer" is new data given to this function. I can call this function about 4-7 times ( and it varies ) before it seg faults on the memcpy operation. The size of the QSharedMemory location is huge so in the few calls that I do before seg faulting, there is no issue of memcpy copying data beyond it's boundaries. Also, m_SharedAudioBuffer.errorString() gives no errors up to the memcpy operation. Currently, I only have one process using this QSharedMemory segment. I also tried to write continually without appending each time and that works fine, so something is happening when I try to append more data to the shared memory segment. Any ideas? Thanks!
// Get the buffer size for the current audio buffer in shared memory
int bufferAudioDataSizeBytes = readFromSharedAudioBufferSizeMemory(); // This in number of bytes
// Create a bytearray with our data currently in the shared buffer
char* bufferAudioData = readFromSharedAudioBufferMemory();
QByteArray currentAudioStream = QByteArray::fromRawData(bufferAudioData,bufferAudioDataSizeBytes);
QByteArray currentAudioStreamDeepCopy(currentAudioStream);
currentAudioStreamDeepCopy.append(audioBuffer);
dataSize = currentAudioStreamDeepCopy.size();
//#if DEBUG
qDebug() << "Inserting audio buffer, new size is: " << dataSize;
//#endif
writeToSharedAudioBufferSizeMemory( dataSize ); // Just the size of what we received
// Write into the shared memory
m_SharedAudioBuffer.lock();
// Clear the buffer and define the copy locations
memset(m_SharedAudioBuffer.data(), '\0', m_SharedAudioBuffer.size());
char *to = (char*)m_SharedAudioBuffer.data();
char *from = (char*)audioBuffer.data();
// Now perform the actual copy operation to store the buffer
memcpy( to, from, dataSize );
// Release the lock
m_SharedAudioBuffer.unlock();
EDIT: Perhaps, this is due to my target embedded device which is very small. The available RAM is large when I am trying to write to shared memory, but I notice that in the /tmp directory ( which is only given 4Mb ) I have the following entries - the size is not nearly consumed in /tmp though so I'm not sure why I couldn't allocate more memory, also the QSharedMemory::create method never fails for my maximum size of 960000:
# cd /tmp/
# ls
QtSettings
lib
qipc_sharedmemory_AudioBufferData2a7d5f1a29e3d27dac65b4f350d76a0dfd442222
qipc_sharedmemory_AudioBufferSizeData6b7acc119f94322a6794cbca37ed63df07b733ab
qipc_systemsem_AudioBufferData2a7d5f1a29e3d27dac65b4f350d76a0dfd442222
qipc_systemsem_AudioBufferSizeData6b7acc119f94322a6794cbca37ed63df07b733ab
qtembedded-0
run
The problem seemed to be that I was using QByteArray's ::fromRawData on the pointer returned by the shared memory segment. When I copied that data explicitly using memcpy on this pointer, and then constructed my QByteArray using the copied data, then the seg faults stopped.

Constructing QImage from unsigned char* data

I encountered a problem with passing Image object (captured with Point Grej FlyCapture2 SDK) to QImage object. I am getting a pointer associated with Image data by function:
virtual unsigned char* FlyCapture2::GetData ( )
and then loading the data by:
QImage::QImage ( uchar * data, int width, int height, int bytesPerLine, Format format )
Formats of data of both Image objects are 8-bit monocolor. BytesPerLine parameter should be equal to width of the Image (I've already checked it by saving FlyCapture2::Image to .bmp and then loading it to QImage).
Do you thing the problem is casting from unsigned char* to uchar*?
Do you have any other ideas? Copying image pixel by pixel is much too slow.
EDIT: I am converting Image captured by FlyCapture into the FlyCapture2::PIXEL_FORMAT_RGB8 , for which: R = G = B = 8 bits, within PGR::SnapShot() function. SnapShot() returns unsigned char* const.
and here is a part of my Qt display function:
unsigned char *const img = PGRSystem->SnapShot();
QImage Img(img, 1024, 768, QImage::Format_RGB888);
QGraphicsScene *Scene = new QGraphicsScene();
Scene->addPixmap(QPixmap::fromImage(Img));
ui.ImageView->setScene(Scene);
ui.ImageView->fitInView(ui.ImageView->itemAt(100,100));
delete [] Scene;
I also tried to save Img to file, but got unhandled exception then. I tried other pixel format pairs (FlyCapture2::PIXEL_FORMAT_RGB - 24 bit RGB with QImage::RGB888 and FlyCapture2::PIXEL_FORMAT_RGBU32 with QImage::RGB32)
It is also worth to mention that QImage constuctor, which I am using, does not set the colorTable (I am getting exception when checking if QImage is in grayScale).
I need a little more help I guess.
First thing - QImage doesn't support a native greyscale image, which is what it sounds as if you're getting as output - so I would be curious what Format argument you're using. Probably the easiest solution, though memory-inefficent, will be to expand your greyscale image to RGB by copying each value three times (into a new QByteArray).
An additional concern is that the particular QImage constructor you're using, does not copy the underlying data, so you need be sure the pointer returned from GetData() outlives the QImage - or force the QImage to make a copy internally, using, say, QImage::copy.
Seeing more code would help, as other respondents noted above.
Thanks a lot for your help, you were right about the Image formats. Unfortunatelly the main problem was associated with passing the pointer between functions. In PGR::SnapShot() I was creating FlyCapture2::Image and then I was getting the pointer to data. FlyCapture2::Image was detructed when exit the function so returned pointer was BadPtr.

Resources