How to check why QOpenGLVertexArrayObject::create fails - qt

I have got the following code for creating a VAO :
// VAO
mVAO = new QOpenGLVertexArrayObject();
if (!mVAO->create()) {
qDebug() << "ERROR: VAO creation failed";
}
mVAO->bind();
// VBO
mVBO = new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
if (!mVBO->create()) {
qDebug() << "ERROR: VBO creation failed";
}
mVBO->setUsagePattern( QOpenGLBuffer::StreamDraw );
mVBO->bind();
mVBO->allocate( mVertices.constData(), mVertices.count() * 3 * sizeof( float ) );
mProgram.enableAttributeArray(mVertexAttrLoc);
mProgram.setAttributeBuffer(mVertexAttrLoc, GL_FLOAT, 0, 3 ); // uses the currently bound VBO
// This is imp, we do not want any more state info recorded
mVAO->release();
mVAO->create() fails in the above code. But the VBO creation does not fail. I am not sure how to find out a more detailed reason as to why the VAO creation fails.
One other thing is I am using Qt 5.2 and a laptop with a dual video card and the nvidia optimus thingy. But I can see the program is executed by the nvidia card and not the onboard intel card. So it probably is not a hardware capabilities issue.
The OpenGL version reported by
qDebug() << "OpenGL version:" << QGLFormat::openGLVersionFlags();
is OpenGL version: QFlags(0x800) which is QGLFormat::OpenGL_ES_Version_2_0
Maybe the ES version is whats standard in laptops ?
I used this as a reference to write the code : http://www.kdab.com/opengl-in-qt-5-1-part-2/

Related

QMediaPlayer::metaData always returns QVariant(Invalid)

I used Qt on MAC OS and try to retrieve the metadata of media. So i took the Qt's Media Player Example (Qt 5.8.0) and modified a little bit:
Instead of:
connect(controls, SIGNAL(play()), player, SLOT(play()));
i used:
connect(controls, &PlayerControls::play, player,
[this]{
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Size);
player->play();
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Resolution);
});
The results are:
false
QVariant(Invalid)
false
QVariant(Invalid)
1st question: why is the metadata not available even after the media started playing?
2nd question: i added some codes in the destructor:
Player::~Player()
{
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Duration);
}
Now the metadata is available, but no data is returned:
true
QVariant(Invalid)
Can anyone help me please?
Update Question 1:
Instead of
connect(controls, SIGNAL(pause()), player, SLOT(pause()));
i used:
connect(controls, &PlayerControls::pause, player,
[this]{
qDebug() << player->isMetaDataAvailable();
qDebug() << player->metaData(QMediaMetaData::Resolution);
});
And after about 3-5 seconds of playing, the metadata is already available, but it also returns nothing:
true
QVariant(Invalid)
This is not the exact answer for your question but this may help you. You can check which metadata available with this code:
QMetaDataReaderControl *c = qobject_cast<QMetaDataReaderControl*>(player_->service()->requestControl(QMetaDataReaderControl_iid));
if(c) {
connect(c, &QMetaDataReaderControl::metaDataAvailableChanged, [c](bool) {
qDebug() << c->availableMetaData();
});
}
I', not sure, but I think that qDebug cannot handle QVariant, you should use for example:
qDebug() << (player->metaData(QMediaMetaData::Title)).toString();

QtCreator semantic issue warning code will never be executed

I have following chunk of Qt code:
if(this->ueCommunicationsSocket()->bind(QHostAddress(data[0].toString()),
static_cast<quint16>(data[1].toInt())),
QAbstractSocket::ShareAddress)
{
qDebug() << Q_FUNC_INFO
<< "TCP socket bind succesfull";
}
else
{
qDebug() << Q_FUNC_INFO
<< QString::number(this->ueCommunicationsSocket()->error())
<< this->ueCommunicationsSocket()->errorString(); // here i get semantic issue
} // if
and I am getting semantic issue warning code will never be executed. I am aware this is some dumb mistake and I am ready to get downvote(s), however, I cannot find mistake! Here is also a screenshot:
if(this->ueCommunicationsSocket()->bind(QHostAddress(data[0].toString()),
static_cast<quint16>(data[1].toInt())),
QAbstractSocket::ShareAddress)
is
if ( /*something */, QAbstractSocket::ShareAddress)
since AbstractSocket::SharedAddress is 0x1, this condition with a comma operator ! is always true, i.e. the else branch will never be executed.

OpenCL cannot find GPU device: NVIDIA GPU (Quadro K4000) + Visual Studio 2015

Just started to learn OpenCL and setup a Visual Studio project using VS2015. Somehow, the code can find only 1 platform (I guess it should be the CPU), and cannot find the GPU device. Can someone please help? The detailed information is as follows:
GPU: Nvidia Quadro K4000
CUDA Installation
CUDA is at: “C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5”
OpenCL related files are located at "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\CL" and "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\lib\Win32" (assuming 32bit system)
The installer created two environment variables “CUDA_PATH” and “CUDA_PATH_V7_5”. They both point to the above location.
In Visual Studio, the project is set up as
"Project Properties" -> "C/C++" -> "Additional Include Directories" -> "$(CUDA_PATH)\include"
"Project Properties" -> "Linker" -> "Additional Library Directories" -> "$(CUDA_PATH)\lib\Win32"
"Project Properties" -> "Linker" -> "Input" -> "Additional Dependencies" -> "OpenCL.lib"
The code is very simple:
#include "stdafx.h"
#include <iostream>
#include <CL/cl.h>
using namespace std;
int main()
{
cl_int err;
cl_uint numPlatforms;
err = clGetPlatformIDs(0, NULL, &numPlatforms);
if (CL_SUCCESS == err)
cout << "Detected OpenCL platforms: " << numPlatforms << endl;
else
cout << "Error calling clGetPlatformIDs. Error code:" << err << endl;
cl_device_id device = NULL;
err = clGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
if (err == CL_SUCCESS)
cout << device << endl;
return 0;
}
The code compiles and runs, but it cannot the GPU device. Specifically, the returned value of variable device is device = 0x00000000 <NULL>. What would be the problem? Thanks for the help.
This is not the way you use the OpenCL API.
You need to obtain a valid cl_platform_id object which it needs to be used to retrieve a cl_device_id. You are always passing NULL, this can't work.
The first time you invoke the clGetPlatformIds, you do it in order to obtain the number of platforms in the system. After than you need to invoke the method again in order to retrieve the actual cl_platform_ids:
size_t numPlatforms;
err = clGetPlatformIDs(0, NULL, &numPlatforms);
assert(numPlatforms > 0);
cl_platform_id platform_ids[numPlatforms];
err = clGetPlatformIDs(numPlatforms, platform_ids, NULL);
However, if you already know there is going to be only one platform in the system, then you can do speedup things as follows, but make sure to check for errors:
cl_platform_id platform_id;
err = clGetPlatformIDs(1, &platform_id, NULL);
assert(err == CL_SUCCESS);
After you have obtained a platform you need to follow the same procedure to first obtain the number of devices and then retrieve the list of OpenCL devices (which you then will need to build a cl_context, queues...):
// Note: this has to be done for each `cl_platform_id`
// until you find the device you were looking for
size_t numDevices;
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);
assert(numDevices > 0);
cl_device_id devices[numDevices];
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, numDevices, devices, NULL);
I guess you understand the procedure now. If like above, you already know that there is only 1 GPU device in the system, you can directly get its cl_device_id as follows:
cl_device_id device;
err = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
assert(err == CL_SUCCESS);

Files getting corrupted when being downloaded using QNetworkAcessManager

I'm developing a client app whose purpose is to download some files from a web server, temporarily store them in the Temp folder, check for file integrity, then send them to a FTP server in a Embedded Linux device.
Recently I got problems when doing the process in a preliminary development stage when I was trying to do the download from my local machine (see related question here). Now I'm able to download and upload without errors and with verification (I'm using QCryptographicHash + file size to check for any nonconformities) from my machine, but the same doesn't happen when I try downloading from the HTTP server.
There is a total of 8 files being downloaded: three .tar.gz, one simple text, two programs and two binaries. I'm able to successfully download all compressed files, the text file and one of the binaries, but the others, namely the two programs and one of the binaries (a Linux Kernel image) are always being incorrectly downloaded.
I check this by noticing not only that the hash returns error for them, but also for their sizes: their sizes are always wrong (and always the same erroneous value for any download attempt). And the files in the server are all correct.
My first suspicion was that I need to configure the HTTP download in a way that differs from the common FTP download from the local machine, but I'm unaware on how would that be. Moreover if this extra configuration was needed, then why some of the files always return correctly?
Here is the relevant code as for now:
void MainWindow::processNextDownload()
{
QUrl ulrTemp(updateData.at(transferStep).downloadUrl.arg(ui->leID->text())); //"//" +
if (updateData.at(transferStep).downloadUrl.contains("http"))
ulrTemp.setScheme("http");
else
ulrTemp.setScheme("file");
// ulrTemp.setUserName();
// ulrTemp.setPassword();
// ulrTemp.setPort();
qDebug() << "Downloading" << transferStep << "from" << ulrTemp;
#if 1
poReply = downloadNetworkManager->get(QNetworkRequest(ulrTemp));
#else
QNetworkRequest request;
request.setUrl(ulrTemp);
request.setRawHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");
poReply = downloadNetworkManager->get(request);
#endif
connect(poReply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(slotDownloadProgress(qint64,qint64)));
ui->statusBar->showMessage(tr("Downloading: %1").arg(updateData.at(transferStep).itemName));
}
void MainWindow::slotFileDownloaded(QNetworkReply* reply)
{
if (reply && (reply->error() != QNetworkReply::NoError))
{
ui->statusBar->clearMessage();
if (!isSingleFile)
{
const QString strTemp = tr("An error occurred while downloading \"%1\": %2 (error message: %3)")
.arg(updateData.at(transferStep).downloadName).arg(reply->error()).arg(reply->errorString());
QMessageBox::critical(this,tr("Error in download"),strTemp);
}
else
{
//irrelevant...
}
finished(false);
return;
}
qDebug() << "To write: " << reply->bytesAvailable();
QByteArray downloadedData = reply->readAll();
reply->deleteLater();
poReply->deleteLater();
//![]
static const QString tempFilePath = QDir::tempPath();
if (!isSingleFile)
{
QFile file(tempFilePath + "/" + updateData.at(transferStep).downloadName);
if (!file.open(QFile::WriteOnly | QFile::Truncate))
{
qDebug() << "Failure opening temp file to write: " << file.fileName();
QMessageBox::critical(this,
tr("Error"),
tr("An error occured while trying to open a temporary file to write the downloaded data (file: %1).").arg(file.fileName()));
transferStep = downloadStepCount;
slotFileUploaded(NULL);
return;
}
qint32 bytesWritten = file.write(downloadedData);
file.flush();
if (downloadedData.size() != bytesWritten)
qDebug() << "Write failed, wrote" << bytesWritten << "out of" << downloadedData.size() << "bytes.";
else
qDebug() << "Wrote " << bytesWritten << "bytes.";
file.close();
//![]
if (++transferStep >= downloadStepCount)
{
qDebug() << "Start hash check";
slotStartHashCheck();
return;
}
processNextDownload();
}
else
{
//irrelevant...
}
}
And this is why I get (the last number value after the "=" in the hash code is the file size):
So what am I missing?

Qt5.4 QAudioOutput on Raspberry Pi With PulseAudio on the 3.5mm Audio Jack Doesn't work but Qt 5.3 Does

Qt5.3 sees the default Raspberry Pi also_output.0.analog-mono device ( 3.5 mm headphone jack ) and QAudioOutput from 5.3 successfully writes audio to that device and I can hear the audio with my headphones. This all works with default Raspbian, with PulseAudio 2.0 from apt-get, and no extra configuration. PulseAudio is run as session process and not in the System Daemon mode. Qt 5.4 does not see the device with the exact same source code and Raspbian ( except cross-compiled with Qt 5.4.0 and not Qt 5.3.2 ) and also cannot write data to it.
It gives me this error ( Please note that I've manually assigned both sys default:CARD=ALSA and 'default' but they both return the same 'snd_pcm_hw_params' error ):
Output Device name: "sysdefault:CARD=ALSA"
Output Device name: "default"
Default device is "default"
Output device is: "default"
"QAudioOutput: snd_pcm_hw_params: err = -12"
Pactl sees it:
pactl list sinks
Sink #0
State: SUSPENDED
Name: alsa_output.0.analog-mono
Description: bcm2835 ALSA Analog Mono
Driver: module-alsa-card.c
Sample Specification: u8 1ch 8000Hz
I've tried to modify /etc/pulse/default.pa with this at the bottom to force the output device:
load-module module-alsa-sink sink_name=alsa_output.0.analog-mono device=hw:0
set-default-sink alsa_output.0.analog-mono
Here is my setup code that gives the error:
// Coordinator receives Audio data
m_Format.setSampleRate(8000);
m_Format.setChannelCount(1);
m_Format.setSampleSize(8);
m_Format.setCodec("audio/pcm");
m_Format.setByteOrder(QAudioFormat::BigEndian);
m_Format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo infoOut(QAudioDeviceInfo::defaultOutputDevice());
foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) {
qDebug() << "Output Device name: " << deviceInfo.deviceName();
}
qDebug() << "Default device is" << infoOut.deviceName();
if (!infoOut.isFormatSupported(m_Format))
{
qDebug()<< "Default format not supported - trying to use nearest";
m_Format = infoOut.nearestFormat(m_Format);
}
qDebug() << "Output device is: " << infoOut.deviceName();
m_AudioOutput = new QAudioOutput(infoOut, m_Format, this);
// This data accumulates and dumps data to output
m_DataForOutput.clear();
// Now Start playing
// m_Output gets written to to send data to speakers
m_Output = m_AudioOutput->start();
What in the world is going on? How come the same configuration works with 5.3.2 and not 5.4.1. Assigning the default audio device doesn't work... What can I do here and how can I make it work? Thanks!
The answer was to run in session mode ( not a system-wide PulseAudio daemon ) and edit default.pa to look like this:
## Create the default output device
#load-module module-udev-detect tsched=0
load-module module-alsa-card device_id=0
#load-module module-alsa-card device_id=0 tsched=0 fragments=10 fragment_size=640 tsched_buffer_size=4194384 tsched_buffer_watermark=262144
#load-module module-alsa-card device_id=0 tsched=0 fragments=6 fragment_size=16 tsched_buffer_size=4194384 tsched_buffer_watermark=262144
load-module module-suspend-on-idle timeout=86400
### Load several protocols
load-module module-native-protocol-unix
### Make sure we always have a sink around, even if it is a null sink.
#load-module module-always-sink

Resources