Transferring a video file (.mp4) through Ethernet port.
-
I'm transferring a video file (.mp4) from server to client PC through ethernet port. my goal is to transfer the complete video file data to client, and play it on a QWidget in the client side GUI. I'm facing two problems here:
1)the complete video data is not tranferring to the client. the video size is 1206855 bytes. but the client is receiving only 1205960 bytes. i modified the code to receive the remaining bytes but it is not working.
2)I'm encountering "Error:failed to seek" error. I dont know whether it is due to incomplete data transfer or due to video format issue. I tried with transferring different videos, but still the error persists.
connect(socket, &QTcpSocket::disconnected, this, &MainWindow::receiveVideo); connect(socket, &QTcpSocket::readyRead, this, &MainWindow::receive_data);
//this function is for receiving the video data and storing in a QByteArray void MainWindow::receive_data() { // Ensure that the sender is indeed a QTcpSocket if (QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender())) { count += 1; if (received_data.size() < 1206855) { qDebug() << count << " receiving video data"<<received_data.size(); received_data.append(socket->readAll()); resetTimer(); } else { qDebug() << "Data size exceeds threshold. Closing socket."; socket->close(); } } } void MainWindow::resetTimer() { // Reset the timer whenever data is received if (dataTimer->isActive()) { dataTimer->stop(); } dataTimer->start(5000); // Restart the timer for 5 seconds } void MainWindow::onTimeout() { qDebug() << "No data received for 5 seconds. Closing socket."; socket->disconnected(); }
//this function is to process the received data into video and display it on the GUI. This function is called when the program emits "disconnected" signal. void MainWindow::receiveVideo() { // qDebug()<<"processing received data .."; if (!received_data.isEmpty()) { // Convert QByteArray to QBuffer QBuffer buffer(&received_data); buffer.open(QIODevice::ReadOnly); // Create a QMediaPlayer object QMediaPlayer *player = new QMediaPlayer; // Connect to the mediaStatusChanged signal connect(player, &QMediaPlayer::mediaStatusChanged, [&](QMediaPlayer::MediaStatus status){ if (status == QMediaPlayer::LoadedMedia) { // Check if seeking is supported for the current media bool isSeekable = player->isSeekable(); if (isSeekable) { qDebug() << "Seeking is supported for the current media."; } else { qDebug() << "Seeking is not supported for the current media."; } } }); // Set the media content of the QMediaPlayer player->setMedia(QMediaContent(), &buffer); // Create a QVideoWidget to display the video QVideoWidget *videoWidget = new QVideoWidget; player->setVideoOutput(videoWidget); // Set the video output to the QLabel // ui->label->setGeometry(videoWidget->geometry()); // player->setVideoOutput(videoWidget); // Set the layout of ui->widget to a vertical layout (only needed if not already set) if (!ui->widget->layout()) { QVBoxLayout *layout = new QVBoxLayout(ui->widget); ui->widget->setLayout(layout); } // Add the videoWidget to the layout of ui->widget ui->widget->layout()->addWidget(videoWidget); // Set the videoContainer as the central widget of the MainWindow setCentralWidget(ui->widget); // Play the video player->play(); } else{ qDebug()<<"Received data is empty.."; } }
-
@Prakash08 said in Transferring a video file (.mp4) through Ethernet port.:
QBuffer buffer(&received_data);
How long does this object live?
-
@Christian-Ehrlicher which object do you mean, buffer or received_data?
the buffer object is created when receiveVideo() is called and exists until the function returns ... -
@Prakash08 said in Transferring a video file (.mp4) through Ethernet port.:
the buffer object is created when receiveVideo() is called and exists until the function returns ...
right, you're almost there !
how long does
QVideoWidget *videoWidget = new QVideoWidget;
live ? -
@Prakash08 said in Transferring a video file (.mp4) through Ethernet port.:
// Set the media content of the QMediaPlayer player->setMedia(QMediaContent(), &buffer);
player
is using&buffer
as its buffer. Compare the lifetimes ofplayer
andbuffer
. -
exists until the function returns ...
immediately.
How long would the video take to play in real time if the data existed?
@Prakash08 said in Transferring a video file (.mp4) through Ethernet port.:
i modified the code to receive the remaining bytes but it is not working.
You cannot receive bytes not sent. Are you certain the sender is sending more? Are you seeing the client disconnect signals? Apart from a gross error check, i.e. are we in danger of exhausting memory, why are you looking for a size anyway? Presumably the sender will close the connection when they are done and you can go then.
-
@Prakash08 no, it's on the heap and you actually never delete it, so it exists forever.
Maybe QVideoWidgets takes ownership of it? I would have to look that up
either way the core issue stays, you're trying to play data that is destroyed as soon as it's created
-
@Prakash08 said in Transferring a video file (.mp4) through Ethernet port.:
how to solve this ? any idea ?
Fix your code - 4 people told you what's wrong...
-
@Christian-Ehrlicher I'm sorry, I did not get where the issue is, can you please elaborate, which part of code should be modified ?
-
@Christian-Ehrlicher said in Transferring a video file (.mp4) through Ethernet port.:
QBuffer buffer(&received_data);
How long does this object live?
@JonB said in Transferring a video file (.mp4) through Ethernet port.:
player
is using&buffer
as its buffer. Compare the lifetimes ofplayer
andbuffer
. -
@Prakash08 said in Transferring a video file (.mp4) through Ethernet port.:
And how to give the condition in sender to code to disconnect the connection when its done sending data ..?
When the sender runs out of file content, or send its entire in-memory buffer, then it should call close() on its socket. Exactly how that looks depends on your sender code.
-
@ChrisW67 how to send its in-memory buffer ? And here is the sender code ..
void MainWindow::send_video() { qDebug()<<"Connected to Server:"<<socket->peerAddress()<<" on port:"<<socket->peerPort()<<" name:"<<socket->peerName(); // QFile file("C:/Users/Intel/Pictures/sunset.png"); // Replace with the actual video path QFile file("C:/Users/Intel/Desktop/video_2.mp4"); if (!file.open(QIODevice::ReadOnly)) { qDebug() << "Unable to open file:" << file.errorString(); return; } while (!file.atEnd()) { QByteArray imageData = file.readAll(); // Read data in chunks socket->write(imageData); // Send data to server qDebug()<<" video data .."; } // QByteArray imageData = file.read(16955); // Read data in chunks // socket->write(imageData); qDebug()<<" video data sent.."; file.close(); socket->disconnectFromHost(); }
-
@Prakash08
Sorry, but you're wrong. @Christian-Ehrlicher & I have both tried to point this out to you.First of all,
QMediaPlayer *player = new QMediaPlayer
is a pointer to an allocated object on the heap. That means it persists until somethingdelete
s it. The fact thatQMediaPlayer *player
is itself a local variable is neither here nor there, when it goes out of scope that does not destroy the object it points to. That is quite different fromQBuffer buffer(&received_data)
, which is a local stack variable, not a pointer to an object. That does get destroyed at the end of theif
.Secondly,
player->setMedia(QMediaContent(), &buffer)
means thatplayer
is using the stackbuffer
, so as soon as theif
exitsbuffer
is destroyed but theQMediaPlayer
is still using it as its buffer. When you goplayer->play()
at the end that only starts playing the video, it does not finish playing it. It carries on playing after the function exits. But it's reading from a buffer which has now been destroyed. Not good! Lucky it does not "crash". Your "Error:failed to seek" error may be from code trying to access it when it is no longer valid.This is all standard C++ stuff.