Video not playing on startup - qt

I am trying to play a video in Qt using OpenCV. I am using the following code.
CvCapture *capture;
IplImge *frame;
cv::Mat source_image;
cv::Mat dest_image;
QTimer *imageTimer;
void MainWindow::onButtonClick()
{
capture = cvCaptureFromFile("/mp.mp4");
while(capture)
{
frame = cvQueryFrame((capture);
source_image = frame;
cv::resize(source_image,source_image,cv::Size(420,180),0,0);
cv::cvtColor(source_image,source_image,CV_BGR2RGB);
QImage qimg = QImage((const unsigned char*) source_image.data,source_image.cols,source_imge.rows,QImage::Format_RGB888);
label->setPixmap(QPixmap::fromImage(qimg));
label->resize(label->pixmap()->size());
qapp->processEvents();
}
}
When I try to play it on button click it is working fine. However when I write the same code in MainWindow constructor it gets finished unexpectedly. I want that the video should be displayed on screen start up and not when I click a button. What should I do for the same?
Thank You :)

Related

How can I simulate mouse clicks by posting events to the Qt event system?

I would like to do a rudimentary automation test of my Qt application. It records mouse events and writes them to a file (f.e. mousepress(300, 400)). When starting the automation, it reads the coordinates from the file, sends the appropriate mouse events and would do a pixel comparison with a previously saved screenshot.
Currently, I have an overlay widget that spans the app and has transparent mouse events. All it does is track the coordinates.
When reading the data back in, that overlay paints a rectangle on the mouse press location.
I need help when sending mousePressEvents to Qt's event system. It draws the points on the correct location but never actually does the physical click.
Is there a way to do this with Qt or would I have to use Window's SendInput()?
Is there a way to pause and wait until the mouse event has finished? I would need to know when the event is complete in order to start the pixel by pixel comparison.
Widget::Widget( QWidget *parent )
: QFrame( parent )
, mPoint(QPoint(0,0))
{
setWindowFlags(Qt::WindowStaysOnTopHint);
setStyleSheet("background-color: rgba(0, 0,255, 2%);");
setAttribute(Qt::WA_TransparentForMouseEvents, true);
setGeometry(parent->geometry());
...
}
void Widget::run()
{
QFile file( "coordinates.txt", NULL );
if(!file.open( QIODevice::ReadOnly ))
return;
QTextStream in(&file);
int i = 0;
while (!in.atEnd())
{
QString line = in.readLine();
if(line.startsWith("mousepress"))
{
int startIndex = line.indexOf('(');
int endIndex = line.indexOf(')');
QString coord = line.mid(startIndex+1, line.size() - startIndex - 2);
QStringList nbr = coord.split(',');
mPoint = QPoint(nbr[0].toInt(), nbr[1].toInt());
QWidget *receiver = QApplication::widgetAt(mPoint);
QMouseEvent *event = new QMouseEvent(QEvent::MouseButtonPress, mPoint, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QCoreApplication::postEvent(receiver, event); // same result with sendEvent()
QCoreApplication::processEvents();
update();
// wait till the event finished, then continue with next point
}
}
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter p( this );
QPen pen;
pen.setBrush(Qt::NoBrush);
if(!mPoint.isNull())
{
pen.setColor(Qt::red);
pen.setWidth( 2 );
p.setPen(pen);
p.drawRoundRect(mPoint.x(), mPoint.y(), 10, 10, 25, 25);
p.drawText(mPoint, QString::number(mPoint.x()) + ", " + QString::number(mPoint.y()));
}
}
[Edited]
I followed ddriver's suggestion and it works after a few changes: I save global and local positions in the file, to send to the QMouseEvent.
How could I be sure that the mouse click is complete before doing a screenshot and comparing it to a saved image?
void Widget::DoStep()
{
if(!mInStream.atEnd())
{
QString line = mInStream.readLine();
if(line.startsWith("MouseButtonPress"))
{
QPoint pos = parseGlobalPos();
QPoint localPos = parseLocalPos();
QWidget *receiver = QApplication::widgetAt(pos);
QMouseEvent *event = new QMouseEvent(QEvent::MouseButtonPress,localPos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::postEvent(receiver, event);
QMouseEvent *eventRelease = new QMouseEvent(QEvent::MouseButtonRelease, localPos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::postEvent(receiver, eventRelease);
// after successful click, take screenshot and compare them
}
}
if (!mInStream.atEnd())
QMetaObject::invokeMethod(this, "DoStep", Qt::QueuedConnection);
else
file.close();
}
If I understand the problem correctly, its source is the blocking while loop, which blocks the thread and doesn't allow the event loop to spin and process events. There is no way to "pause" as that would block the event loop as well, and it wouldn't be able to do the work either, but there is a way to split the work to be done one step at a time, one event loop cycle at a time.
The solution is to not use a blocking while loop but implement an event system driven loop. Then you process one line on every event loop cycle until you run out of work.
Move the file, stream and all that stuff outside of the function, make them class members so they persist. Then in run() you simply setup the input for reading, and move all the event posting stuff to a new function, for example doStep(), and in run() after you setup you have a:
QMetaObject::invokeMethod(this, "doStep", Qt::QueuedConnection);
In doStep(), aside from the event stuff, at the end you also do scheduling:
if (!in.atEnd()) QMetaObject::invokeMethod(this, "doStep", Qt::QueuedConnection);
else // we are done, close file, cleanup, whatever
This way only one step will be executed per event loop cycle, allowing the event loop to spin and process the events. While there is work, a step will be scheduled for the next event loop cycle. You can also use a single shot timer to do this, or even a queued connection, which you can trigger by emitting overloading the event to emit a signal on completed. You do not, and should not force events to be processed, using this approach there will be no need to.
The concept in general is about a non-blocking async event driven self scheduling worker, I have posted a fully implemented one here. The upsides are you can track progress, pause, cancel and all that good stuff.
Try sending event to QGraphicsView's viewport:
qApp->sendEvent(view->viewport(), &mousePressEvent);

Qt Creator Disable push button when precessed

I'm new using Qt and I'm having some troubles with it.
I'm doing a simple terminal application and I need to disable the buttons for a few seconds after they are selected.
I'm doing something like this:
void MainWindow::on_readcard_clicked(){
this->setEnabled(false);
//Send Command
QString commandString = "";
commandString.append('1');
commandString.append("\n");
QByteArray commandArray = commandString.toLocal8Bit();
serial->write(commandArray);
//Read Card
QByteArray data = serial->readLine(12);
QString dataString = 0;
dataString.append(data);
ui->cardnumber->setText(dataString);
dataString.clear();
data.clear();
QByteArray saldo = serial->readAll();
QString saldoString = 0;
saldoString.append(saldo);
ui->balance->setText(saldoString);
saldoString.clear();
saldo.clear();
this->setEnabled(true);}
I need this because if someone press the button twice before it finished processing the first tap I will get a "crazy" array with lots of trash.
I also tried use "waitForBytesWritten" and "waitForReadyRead" but it hasn't blocked the connection until everything was processed.
Regards
Try with QTimer::SingleShot() :
this->setEnabled(false);
QTimer::singleShot(2000, this, SLOT(enableMyButton()));
// you code
void enableMyButton()
{
this->setEnabled(true);
}
It'll enable the button 2secs after the call

How to play QAudioBuffer by QIODevice?

I want to make an audio streaming program (like phone) using the QMediaPlayer, QAudioProbe and QAudioOutput classes in Qt 5.3.0 MSVC2012 OpenGL 32bit.
This is my code:
musicPlayer = new QMediaPlayer();
musicProbe = new QAudioProbe();
musicProbe->setSource(musicPlayer);
connect(musicProbe, SIGNAL(audioBufferProbed(QAudioBuffer)),
this, SLOT(slotGetMusicData(QAudioBuffer)));
If audio data probed, the slot is actived.
void MusicPlayer::slotGetMusicData(QAudioBuffer musicBuffer)
{
/*QAudioBuffer to QByteArray*/
*musicDataBuffer = musicDataBuffer->fromRawData((char *)musicBuffer.data(),
,musicBuffer.byteCount());
/*Send Music Data*/
musicSocket->sendMudicData(*musicDataBuffer);
qDebug("send complete");
}
Using a socket, I send the data to another program.
The other program plays the music received.
QAudioOutput *audioOutput = new QAudioOutput(format, this);
QIoDevice *audioDevice = audioOutput->start();
and then, data received this slot is actived.
void BgmSocket::slotPlayBgm(QByteArray data)
{
audioDevice->write(data.data(), data.size());
}
The audio is playing well, but the sounds have a lot of static (pause sound).
How can I solve this problem?
The problem was a different frequency between the network and the playback buffer.
I solved this problem by creating a buffer with double buffering.

How can I get a video meta data using Qt phonon?

I want to get the bitrate of a video. And I use Qt Phonon to achieve this goal.
Since there is a class called Phonon::MediaObject and provide a method called metaData(),I use that method but the result shows zero. Here is my code, I wonder why and how can I get the metadata such as bitrate in qt with Phonon
QString source="E:\\sh.mp4";
Phonon::MediaObject media;
media.setCurrentSource(Phonon::MediaSource(source));
QMap <QString, QString> metaData = media.metaData();
int trackBitrate = metaData.value("bitrate").toInt();
qDebug()<<trackBitrate;
The result is 0 all the time
I just figured this out myself.
Meta data in video files do not contain bitrate. It only contains extra information about the media that don't have any effect on playback. So even if Phonon::MediaObject::metaData() worked without loading the video, it will not help you.
I ended up using libformat, part of ffmpeg library to get the bitrate. Here's the code.
If you copy and paste this, it should work.
Download FFMpeg here: http://dranger.com/ffmpeg/tutorial01.html
This first tutorial will tell you how to link: http://dranger.com/ffmpeg/tutorial01.html
#include <QString>
#include <QMultiMap>
#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
void processMedia(const char* mediaFile)
{
AVFormatContext *pFormatCtx = NULL;
AVDictionaryEntry *tag = NULL;
// Register all formats and codecs
av_register_all();
// Open video file
if(avformat_open_input(&pFormatCtx, mediaFile, NULL, NULL)!=0)
return;
// Retrieve stream information
if(av_find_stream_info(pFormatCtx)<0)
return;
//Get Bitrate
float bitRate = pFormatCtx->bit_rate;
//Get Meta
QMultiMap<QString, QString> metaData;
while ((tag = av_dict_get(pFormatCtx->metadata, "", tag,
AV_DICT_IGNORE_SUFFIX)))
{
QString keyString(tag->key);
QString valueString(tag->value);
metaData.insert(keyString, valueString);
printf("%s=%s\n", tag->key, tag->value);
}
// Close the video file
av_close_input_file(pFormatCtx);
}
When you set the data source, the MediaObject enters the LoadingState. At that point, metadata might not yet be available.
The object emits a metaDataChanged signal when the metadata is ready. You should react to that signal and only attempt accessing the metadata once it has been emitted.

view an image in qt for symbian

I have an application that I implemented, and want to display an image in a widget, but I get an error SIGSEGV, I view it from a directory, but in reality after heave from a buffer
not what the problem is I leave my code here:
void Image:: on_pushButton_clicked ()
{
this-> conn-> connect (this-> ui-> lineEdit_2-> text (),
this-> ui-> lineEdit-> text (). Toint ()); QLayout* layout;
QString fileName = QFileDialog:: GetOpenFileName (this,
tr ("Open File"), QDir:: currentPath (),
"files (*. jpg *. png)");
QImage image (fileName);
QLabel * label = new QLabel (this);
label-> setPixmap (QPixmap:: FromImage (image));
label-> setScaledContents (true);
layout-> addWidget (label);
label-> show ();
}
I can leave if you want to help my application link for the download
thank you very much
thank you very much and I managed to see the image, I want to load from a buffer like this: QBuffer * buffer = new QBuffer (conex);
QImage * image = new QImage ();
image-> loadFromData (buffer-> buffer ());
I tried this to make my image but I get errors
QBuffer * buffer = new QBuffer (conn);
QImage image = new QImage ();
image-> loadFromData (buffer-> buffer ());
errors are as follows:
C:\ejemplos_qt\teratermobile-build-simulator..\teratermobile\imagen.cpp:81: error: conversion from 'QImage*' to non-scalar type 'QImage' requested
C:\ejemplos_qt\teratermobile-build-simulator..\teratermobile\imagen.cpp:82: error: base operand of '->' has non-pointer type 'QImage'
You didn't initialize your layout variable before using it with something like this:
layout = new QVBoxLayout(widget); // widget is where you want to put the QLabel
or you can reuse an already created layout.
If you want to show the QLabel as a top-level window, remove completely the two lines about the layout.

Resources