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

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.

Related

Qt: Use QAudioRecorder to return buffer

I want to use QAudioRecorder to record an audio and save as a file and display the filepath to the user. I had tried using the the example from Qt but there's no feed on the buffer value when I tested it on Android. It works on my Desktop though. Below are part of my codes:
AudioRecord::AudioRecord(QWidget *parent)
{
audioRecorder = new QAudioRecorder(this);
probe = new QAudioProbe;
connect(probe, SIGNAL(audioBufferProbed(QAudioBuffer)),
this, SLOT(processBuffer(QAudioBuffer)));
probe->setSource(audioRecorder);
}
void AudioRecord::processBuffer(const QAudioBuffer& buffer)
{
qDebug()<<"Testing Successful";
}
The processBuffer function does not seems to be called. What should I do to get the buffer value work? Is there any other way around?
Thanks!

Change font of contents in QTextEdit from my application resource

I have Qt Resource file (res.qrc) in my Qt Application. I imported my custom font in resource as below:
:/fonts/aa_marcus_east_syriac.ttf
Also i define in header file:
private:
QFont assyrianEventsAAMarcusEastSyriac;
I used QTextEdit in mainwindow. When user click on a button, my application read a text file. every row in text file should be imported in QTextEdit but some lines should be has aa_marcus_east_syriac.ttf font from my resource. So I wrote this codes:
void Widget::readMonthAssyrianEvents()
{
QStringList eventsList;
eventsList = readEventFile();
ui->notificationTextEdit->setCurrentFont(assyrianEventsAAMarcusEastSyriac);
for (int index = 0; index < eventsList.length(); index++)
{
QString eventType, eventContent;
QStringList tempStringList = eventsList[index].split('|');
eventType = tempStringList[0];
eventContent = tempStringList[1];
if (eventType == "0")
ui->notificationTextEdit->append(eventContent);
}
}
readEventFile() function works fine. It read text file and get all lines as QStringList. the "assyrianEventsAAMarcusEastSyriac" variable initialized in another function called init(). this is init() function:
int id = QFontDatabase::addApplicationFont(":/fonts/aa_marcus_east_syriac.ttf");
QString family = QFontDatabase::applicationFontFamilies(id).at(0);
assyrianEventsAAMarcusEastSyriac.setFamily(family);
assyrianEventsAAMarcusEastSyriac.setPointSize(20);
My problem is that QTextEdit doesn't change font of it's contents to my custom font.
How can I solve this problem? Please help me guys.
Thanks
I think the error is in
QString family = QFontDatabase::applicationFontFamilies(id).at(0);
Have you checked that .at(0) is actually your custom font ?
Most likely you can solve this by calling assyrianEventsAAMarcusEastSyriac.setFamily
with an explicit string of the font family just like
assyrianEventsAAMarcusEastSyriac.setFamily("Marcus East Syriac");
If that doesn't work either, maybe your custom font is malformed or doesn't provide a font family name. Therefore I suggest you to try first with a working font and then eventually go back to custom stuff.

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.

Qt: opening qrc pdf with the poppler library

I'm having a bit of trouble with my function for displaying pdf's with the poppler library. The code below is the function in which the problem occurs.
const QString &file is the path to the file
int page is the page on which it has to open
When i set file to a real path (e.g. "/Users/User/Documents/xxx.pdf"), it is no problem to open it. But when i give the path to a qrc file (":/files/xxx.pdf"), it won't work. I want to use it for displaying a user manual for instance, within the application.
I've also tried first making a QFile out of it, opening it and doing readAll, then loading the QByteArray received by doingPoppler::Document::loadFromData(the qbytearray), but it errors already when opening the QFile in ReadOnly mode.
void class::setPdf(const QString &file, int page)
{
Poppler::Document *doc = Poppler::Document::load(file);
if (!doc) {
QMessageBox msgbox(QMessageBox::Critical, tr("Open Error"), tr("Please check preferences: cannot open:\n") + file,
QMessageBox::Ok, this);
msgbox.exec();
}
else{ /*Code for displaying the pdf, which works fine*/
}
}
I hope you can help me,
greetings,
Matt
I've also tried first making a QFile
out of it, opening it and doing
readAll, then loading the QByteArray
received by
doingPoppler::Document::loadFromData(the
qbytearray), but it errors already
when opening the QFile in ReadOnly
mode.
QFile f;
f.setFileName(":/skin/AppIcon16.png");
f.open(QIODevice::ReadOnly);
QByteArray r=f.readAll();
Perfectly reads all data from the resource, have checked it. So i suggest you did something wrong when tried that. Maybe path errors, maybe something else...

To connect Gstreamer with Qt in order to play a gstreamer video in the Qt Widget

I tried using phonon to play the video but could not succeed. Off-late came to know through the Qt forums that even the latest version of Qt does not support phonon. That's when I started using Gstreamer. Any suggestions as to how to connect the Gstreamer window with the Qt widget? My aim is to play a video using Gstreamer on the Qt widget. So how do I link the Gstreamer window and the Qt widget?
I am successful in getting the Id of the widget through winid().
Further with the help of Gregory Pakosz, I have added the below 2 lines of code in my application -
QApplication::syncX();
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), widget->winId());
However am not able to link the Qt widget with the gstreamer video window.
This is what my sample code would look like :-
int main(int argc, char *argv[])
{
printf("winid=%d\n", w.winId());
gst_init (NULL,NULL);
/* create a new bin to hold the elements */
bin = gst_pipeline_new ("pipeline");
/* create a disk reader */
filesrc = gst_element_factory_make ("filesrc", "disk_source");
g_assert (filesrc);
g_object_set (G_OBJECT (filesrc), "location", "PATH_TO_THE_EXECUTABLE", NULL);
demux = gst_element_factory_make ("mpegtsdemux", "demuxer");
if (!demux) {
g_print ("could not find plugin \"mpegtsmux\"");
return -1;
}
vdecoder = gst_element_factory_make ("mpeg2dec", "decode");
if (!vdecoder) {
g_print ("could not find plugin \"mpeg2dec\"");
return -1;
}
videosink = gst_element_factory_make ("xvimagesink", "play_video");
g_assert (videosink);
/* add objects to the main pipeline */
gst_bin_add_many (GST_BIN (bin), filesrc, demux, vdecoder, videosink, NULL);
/* link the elements */
gst_element_link_many (filesrc, demux, vdecoder, videosink, NULL);
gst_element_set_state(videosink, GST_STATE_READY);
QApplication::syncX();
gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(videosink), w.winId());
/* start playing */
gst_element_set_state (bin, GST_STATE_PLAYING);
}
Could you explain more in detail about the usage of gst_x_overlay_set_xwindow_id() wrt my context?
Could I get any hint as to how I can integrate gstreamer under Qt?
Please help me solve this problem.
I just did this same thing using python. What I had to do was connect to 'sync-message::element' on the bus and listen for a message called 'prepare-xwindow-id' (disregard the name as it works on all platforms, not just X11) sent after the video sink is setup. It sends you the sink inside that message, and that is where you pass it the window id.
The sample code given above will link GStreamer video window to QtWidget provided the elements are linked correctly.
filesrc should be linked to the demuxer
decoder should be linked to the filesink
Finally, the demuxer should be linked to the decoder at runtime
// link filesrc to demuxer
gst_element_link(filesrc,demux)
// link vdecoder to filesink
gst_element_link_many(vdecoder,filesink,NULL)
/*
The demuxer will be linked to the decoder dynamically.
The source pad(s) will be created at run time,
by the demuxer when it detects the amount and nature of streams.
Connect a callback function which will be executed
when the "pad-added" is emitted.
*/
g_signal_connect(demux,"pad-added",G_CALLBACK(on_pad_added),vdecoder);
// callback definition
static void on_pad_added(GstElement* element,GstPad* pad,gpointer* data)
{
GstPad* sinkpad;
GstElement * decoder = (GstElement*)data;
GstCaps* caps;
GstStructure* str;
gchar* tex;
caps = gst_pad_get_caps(pad);
str = gst_caps_get_structure(caps,0);
tex = (gchar*)gst_structure_get_name(str);
if(g_strrstr(tex,"video"))
{
sinkpad = gst_element_get_static_pad(decoder,"sink");
gst_pad_link(pad,sinkpad);
gst_object_unref(sinkpad);
}
}
http://cgit.freedesktop.org/gstreamer/gst-plugins-base/tree/tests/examples/overlay
has a minimal Qt example.
In your code, you should probably set the window ID before you do the state change to ready (I'm not 100% sure this is the problem though).
For playback, you should idally use the playbin2 element, something like this (completely untested):
GstElement *playbin, *videosink;
gchar *uri;
playbin = gst_element_factory_make ("playbin2", "myplaybin");
videosink = gst_element_factory_make ("xvimagesink", NULL);
g_object_set (playbin, "video-sink", videosink, NULL);
uri = g_filename_to_uri ("/path/to/file", NULL, NULL);
g_object_set (playbin, "uri", uri, NULL);
g_free (uri);
/* NOTE: at this point your main window needs to be realized,
* ie visible on the screen, and you might need to make sure
* that your widget w indeed has a 'native window' (just some
* things to check for if it doesn't work; there should be Qt
* API for this kind of thing if needed) */
QApplication::syncX();
 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(videosink), w.winId());
gst_element_set_state (playbin, GST_STATE_PLAYING);
.. check for messages like error/statechanges/tags/eos on pipeline/playbin bus
A project wrapping gstreamer into usable C++/Qt classes including example code:
http://code.google.com/p/qbtgstreamer/
I don't know about a direct approach, as I am not familiar with gstreamer itself.

Resources