PDA

View Full Version : Qt Data transfer



Shibby284
18th July 2015, 16:48
hello! I have 2 unrelated questions:
1. Is there a way to hold the main in a wait mode?
meaning the main will pass the return a.exec(); (a is a Qapplication) and enter a wait mode until his subprocesses will end(the gui for example).
2. I'm streaming a video through netcat to a socket. from that socket I need to stream the data to an mplayer process.
I've managed to do that through this code:


void ClientVidless::run()
{
socket = new QTcpSocket(this);
QStringList args1;


args1 += "-fps";
args1 += "60";
args1 += "-cache";
args1 += "1024";
args1 += "-slave";
args1 += "-wid";
args1 += QString::number((int)ui->widget->winId());
args1 += "-";

process1 = new QProcess(0);

process1->start("C:\\Program Files (x86)\\MPlayer for Windows\\mplayer.exe",args1);

qDebug() << "Connecting...";

socket->connectToHost("192.168.1.109",5001);

if (!socket->waitForConnected(1000))
qDebug() << "Error:" << socket->errorString();

connect(socket,SIGNAL(connected()),this,SLOT(conne cted()));
connect(socket,SIGNAL(disconnected()),this,SLOT(di sconnected()));
connect(socket,SIGNAL(bytesWritten(qint64)),this,S LOT(bytesWritten(qint64)));
connect(socket,SIGNAL(readyRead()),this,SLOT(ready Read()));

}


void ClientVidless::readyRead()
{

Data = socket->readAll(); //Data is a QByteArray

qDebug() << " Data in: " << Data;

process1->write(Data);

}

simply when ready read is emitted the socket is read and then writing to the process.
The problem is that the video is really slow with a lot of lag.
What is the best and fastest way in transferring data into a process?
What is the difference between read/write to readdata/writedata functions, and how to use them(they're virtual protected)?
Thanks for the helpers.

anda_skoa
18th July 2015, 17:36
hello! I have 2 unrelated questions:
1. Is there a way to hold the main in a wait mode?
meaning the main will pass the return a.exec(); (a is a Qapplication) and enter a wait mode until his subprocesses will end(the gui for example).

The GUI has ended after exec() returns.
If you want to keep the event loop running until all event based jobs are finished, have a look at QEventLoopLocker.



The problem is that the video is really slow with a lot of lag.
What is the best and fastest way in transferring data into a process?

Well, obviously the best solution would involve not having to copy the data from one process to another.

But you could try avoiding the continuous allocation and deallocation of memory.
I.e. allocate a buffer once and then use it to read from the socket and write to the process using the read/write methods that take char* for the data.

Cheers,
_

Shibby284
18th July 2015, 22:35
Thanks for the quick reply.
Could you be more specific what causes that memory allocation? becuase when I tried to write it in one line:

process1->write(socket->readAll());

it didn't change anything so I'm missing something here. you have any link with an example or a place to read about it?

thank you.

anda_skoa
18th July 2015, 23:30
Well, QIODevice::readAll() needs to allocate memory for the available data. I.e. it creates a QByteArray with the appropriate size and reads the data into that buffer, then returns the object.

That behavior is implied by the method signature. It has no arguments and has to return the data. Its only option is to create the return object.

Once the data has been sent by QIODevice::write(), the memory is no longer needed and deallocated, i.e. the reference count on the QByteArray that was allocated in readAll() decrements to 0 and triggers the memory deallocation.

Writing it in one line or several lines doesn't change a lot. the compiler can potentially avoid some copying on the QByteArray.
But since copying of reference counted classes, such as QByteArray, is a relatively cheap operation, there is not likely much difference in runtime behavior.

Cheers,
_

Shibby284
24th July 2015, 11:29
Hi,
I understand the concept but having trouble implementing.

I defined Data as a char * and allocated memory:

Data = (char *) malloc(1024*sizeof(qint64));

then read from the socket and wrote to the process similar to before:

socket->read(Data,1024);

process1->write(Data);

nothing happens..I guess something is wrong with the number and types there. any idea?

thanks.

anda_skoa
24th July 2015, 11:50
First, why use malloc and not new?

Second, a char is not likely 64 bits long.

Third, you need to check how many bytes you read (return value of read) and then use this to tell write how much of the buffer is actual data.

Cheers,
_

Shibby284
24th July 2015, 13:05
1+2. Data = new char(0); is this good?what is the optimal size ,if there is such a thing, in defining the buffer? is leaving it zero is ok?

BytesRead = socket->read(Data,5);

qDebug() << " Data in: " << Data;

qDebug() << "how much Data in: " << BytesRead;

BytesWritten = process1->write(Data,BytesRead);

qDebug() << "how much Data OUT: " << BytesRead;

now the video doesn't appear and when i try to read(and write) more than around 20 bytes the program collapses.

thanks.

d_stranz
25th July 2015, 01:55
Data = new char(0); is this good?

No. With this statement, you are allocating memory for a single char, setting the char's value to zero, and assigning the resulting pointer to your variable Data. And when you later use that variable and tell the read() method that it points to enough memory to hold 5 bytes, well, that's a lie. It points to memory big enough to hold one byte, and so read() cheerfully overwrites the memory for whatever is allocated after the Data pointer. Do that enough times or for a large enough read and you're bound to trash something critical, and there goes your program.

If you want to dynamically allocate the buffer, then you should use QAbstractSocket::bytesAvailable() to find out what is waiting, then allocate your array to that size before calling read().

Shibby284
25th July 2015, 10:14
well, this is what i wrote:

buffer_size = socket->bytesAvailable();

Data = (char *)malloc(sizeof(char)*buffer_size);

BytesRead = socket->read(Data,buffer_size);

BytesWritten = process1->write(Data,BytesRead);

free(Data);

the thing is i got back to the starting point where i allocate memroy and release it every time i read/write. Due to this(or some other reason i still don't understand)
the video that is being recieved is very very slow.

Could it be the gui that slows it down? i checked the cpu performance and it doesn't take a lot of it..

thanks.

anda_skoa
25th July 2015, 11:06
If you want to dynamically allocate the buffer, then you should use QAbstractSocket::bytesAvailable() to find out what is waiting, then allocate your array to that size before calling read().

Sure, but dynamically allocating memory is what we are trying to avoid here :-)
If that would be OK the easiest way would be to use use the original code.


1+2. Data = new char(0); is this good?what is the optimal size ,if there is such a thing, in defining the buffer? is leaving it zero is ok?

As already mentioned, this allocates a single char.



char *buffer = new char[1024]; // allocate 124 chars

or simply have a QByteArray member in your class and either initialize it with the buffer size or call reserve() with the buffer size.
Nice side effect of this is that you don't have to take care about deleting the memory later on.

Cheers,
_

ChrisW67
26th July 2015, 06:24
Dumb question, is your program doing anything to the data coming from netcat before you send it to mplayer?