I am new to libqmi and wanted to start by just opening a new device. But the callback function is never getting called and therefore no device object returned.
I running the code on Ubuntu 64 Bit.
On this website: https://developer.gnome.org/gio/stable/GAsyncResult.html
I found how this should be handled and programmed it that way, but it still doesn't work.
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
using namespace std;
void device_create_start(const char* device_file);
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
cout << "Start\n";
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
GCancellable* cancellable = g_cancellable_new();
GAsyncReadyCallback callback = device_create_stop;
gpointer user_data = NULL;
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, cancellable, callback, user_data);
cout << "INFO: qmi_device_new started!\n";
cout << "INFO: Waiting!\n";
usleep(10000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
cout << "INFO: canceling!\n";
g_cancellable_cancel(cancellable);
cout << "INFO: Waiting again!\n";
usleep(100000);
cout << "INFO: Is cancelled?: " << g_cancellable_is_cancelled(cancellable) << "\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device file!\n";
}
}
void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
cout << "INFO: device_create_stop\n";
something = 2;
cout << "INFO: qmi_device_new_finish starting\n";
GError *error;
QmiDevice* device = qmi_device_new_finish(res, &error);
cout << "INFO: qmi_device_new_finish started\n";
if(device == NULL)
{
cout << "ERROR: Could not create device!\n";
}
else
{
cout << "INFO: Device created!\n";
//device_open(device);
}
}
When I run this code the output is:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
INFO: Waiting!
INFO: Is cancelled?: 0
INFO: canceling!
INFO: Waiting again!
INFO: Is cancelled?: 1
DEBUG: Something: 1
Stop
The code in the callback function is never called.
Update 1
I simplified the code and changed some things that I oversaw on the gnome reference site, like a static callback function. But this doesn't work either
#include <iostream>
#include <libqmi-glib/libqmi-glib.h>
#include <gio/gio.h>
#include <glib/gprintf.h>
using namespace std;
void device_create_start(const char* device_file);
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data);
int something = 0;
int main()
{
g_printf ("Start\n");
device_create_start("/dev/cdc-wdm0");
cout << "DEBUG: Something: " << something << "\n";
while(true)
{
;
}
cout << "Stop\n";
return 0;
}
void device_create_start(const char* device_file)
{
GFile* file = g_file_new_for_path(device_file);
if(file)
{
cout << "INFO: qmi_device_new starting!\n";
qmi_device_new(file, NULL, device_create_stop, NULL);
cout << "INFO: qmi_device_new started!\n";
something = 1;
}
else
{
cout << "ERROR: Could not create device!\n";
}
}
static void device_create_stop(GObject* obj, GAsyncResult* res, gpointer data)
{
g_printf ("Hurray!\n");
something = 2;
}
The new output:
Start
INFO: qmi_device_new starting!
INFO: qmi_device_new started!
DEBUG: Something: 1
Does anyone has a clue why this is not working?
As Philip said (hey Philip!), you're missing the main loop. The qmi_device_new() function is an method that finishes asynchronously, and once finished, the result of the operation is provided in the callback function you provide. In order for the asynchronous function to even do something, you need to have a GMainLoop running for as long as your program logic runs.
So many type of questions like this has been asked, and i have pass through most of them but cant still get a solution to my problem, this is the error code though: error (-215:Assertion failed) size.width>0 && size.height>0 in function 'cv::imshow'
bool try_use_gpu = false;
vector<Mat>imgs;
Mat image, pano;
image = imread("moscow1.jpg");
if (image.empty())
{
cout << "check your input image" << endl;
return EXIT_FAILURE;
}
imgs.push_back(imread("moscow1.jpg"));
image = imread("moscow2.jpg");
if (image.empty())
{
cout << "check your input image" << endl;
return EXIT_FAILURE;
}
imgs.push_back(imread("moscow2.jpg"));
Stitcher::Mode mode = Stitcher::PANORAMA;
Ptr<Stitcher> stitcher = Stitcher::create(mode, try_use_gpu);
//Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
Stitcher::Status status = stitcher->stitch(imgs, pano);
if (status != Stitcher::OK)
{
cout << "Panorama unsuccessful" << endl;
}
imshow("panorama", pano);
waitKey(0);
imwrite("panoramaimg.jpg", pano);
}
am also thinking if am not implementing the stitcher class well, any help will do...
The images you want to stitch must have common point, for the program to use, use two different images is just not going to work if the images have no common point..
I need to read and inject XMP metadatas in an mp4 container.
I know this is possible on android with the "mp4parser" library, but I couldn't find an equivalent for iOS.
For the read part, is it possible to read every footage from the camera roll to inspect their 360 XMP metadatas quickly ?
For the writing, I'm trying to use Adobe's XMP toolkit. I have an mp4 video in a folder, and I want to inject into it some 360 metadatas.
After injecting the metadatas (I suppose it works), I export the video to the camera roll, but it looks like the video is converted to m4v and it lost every metadata I've written. Is it expected, or is my code wrong ?
Here's the code :
MetadataManager.mm
#import "MetadataManager.h"
#define IOS_ENV 1
#include <string>
#define TXMP_STRING_TYPE std::string
#define XMP_INCLUDE_XMPFILES 1
#include "XMP.incl_cpp"
#include "XMP.hpp"
#include <iostream>
#include <fstream>
using namespace std;
#implementation MetadataManager {
}
+ (void)write360Metadatas:(NSString *)filePath {
if (!SXMPMeta::Initialize())
exit(1);
if (!SXMPFiles::Initialize())
exit(1);
SXMPFiles myFile;
XMP_OptionBits opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUseSmartHandler;
std::string status = "";
std::string filePathStd = std::string([filePath UTF8String]);
// First, try to open the file
bool ok = myFile.OpenFile(filePathStd, kXMP_UnknownFile, opts);
if( ! ok ){
status += "No smart handler available for " + filePathStd + "\n";
status += "Trying packet scanning.\n";
// Now try using packet scanning
opts = kXMPFiles_OpenForUpdate | kXMPFiles_OpenUsePacketScanning;
ok = myFile.OpenFile(filePathStd, kXMP_UnknownFile, opts);
}
if(ok){
SXMPMeta meta;
myFile.GetXMP( &meta );
displayPropertyValues(&meta);
injectMetadatas(&meta);
// Check we can put the XMP packet back into the file
if(myFile.CanPutXMP(meta))
{
// If so then update the file with the modified XMP
myFile.PutXMP(meta);
}
// Close the SXMPFile. This *must* be called. The XMP is not
// actually written and the disk file is not closed until this call is made.
myFile.CloseFile();
}
}
SXMPMeta createXMPFromRDF()
{
const char * rdf =
"<rdf:SphericalVideo xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'"
" xmlns:GSpherical='http://ns.google.com/videos/1.0/spherical/'>"
"<GSpherical:Spherical>true</GSpherical:Spherical>"
"<GSpherical:Stitched>true</GSpherical:Stitched>"
"<GSpherical:StitchingSoftware>Spherical Metadata Tool</GSpherical:StitchingSoftware>"
"<GSpherical:ProjectionType>equirectangular</GSpherical:ProjectionType>"
"</rdf:SphericalVideo>";
SXMPMeta meta;
// Loop over the rdf string and create the XMP object
// 10 characters at a time
int i;
for (i = 0; i < (long)strlen(rdf) - 10; i += 10 )
{
meta.ParseFromBuffer ( &rdf[i], 10, kXMP_ParseMoreBuffers );
}
// The last call has no kXMP_ParseMoreBuffers options, signifying
// this is the last input buffer
meta.ParseFromBuffer ( &rdf[i], (XMP_StringLen) strlen(rdf) - i );
return meta;
}
void injectMetadatas(SXMPMeta * meta)
{
// Add an item onto the dc:creator array
// Note the options used, kXMP_PropArrayIsOrdered, if the array does not exist it will be created
meta->AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Author Name", 0);
meta->AppendArrayItem(kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered, "Another Author Name", 0);
// Now update alt-text properties
meta->SetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", "An English title");
meta->SetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", "Un titre Francais");
// Display the properties again to show changes
cout << "After update:" << endl;
displayPropertyValues(meta);
// Create a new XMP object from an RDF string
SXMPMeta rdfMeta = createXMPFromRDF();
// Append the newly created properties onto the original XMP object
// This will:
// a) Add ANY new TOP LEVEL properties in the source (rdfMeta) to the destination (meta)
// b) Replace any top level properties in the source with the matching properties from the destination
SXMPUtils::ApplyTemplate(meta, rdfMeta, kXMPTemplate_AddNewProperties | kXMPTemplate_ReplaceExistingProperties | kXMPTemplate_IncludeInternalProperties);
// Display the properties again to show changes
cout << "After Appending Properties:" << endl;
displayPropertyValues(meta);
}
void displayPropertyValues(SXMPMeta * meta)
{
// Read a simple property
string simpleValue; //Stores the value for the property
meta->GetProperty(kXMP_NS_XMP, "CreatorTool", &simpleValue, 0);
cout << "meta:CreatorTool = " << simpleValue << endl;
// Get the first and second element in the dc:creator array
string elementValue;
meta->GetArrayItem(kXMP_NS_DC, "creator", 1, &elementValue, 0);
if(elementValue != "")
{
cout << "dc:creator[1] = " << elementValue << endl;
meta->GetArrayItem(kXMP_NS_DC, "creator", 2, &elementValue, 0);
cout << "dc:creator[2] = " << elementValue << endl;
}
// Get the the entire dc:subject array
string propValue;
int arrSize = meta->CountArrayItems(kXMP_NS_DC, "subject");
for(int i = 1; i <= arrSize;i++)
{
meta->GetArrayItem(kXMP_NS_DC, "subject", i, &propValue, 0);
cout << "dc:subject[" << i << "] = " << propValue << endl;
}
// Get the dc:title for English and French
string itemValue;
string actualLang;
meta->GetLocalizedText(kXMP_NS_DC, "title", "en", "en-US", 0, &itemValue, 0);
cout << "dc:title in English = " << itemValue << endl;
meta->GetLocalizedText(kXMP_NS_DC, "title", "fr", "fr-FR", 0, &itemValue, 0);
cout << "dc:title in French = " << itemValue << endl;
// Get dc:MetadataDate
XMP_DateTime myDate;
if(meta->GetProperty_Date(kXMP_NS_XMP, "MetadataDate", &myDate, 0))
{
// Convert the date struct into a convenient string and display it
string myDateStr;
SXMPUtils::ConvertFromDate(myDate, &myDateStr);
cout << "meta:MetadataDate = " << myDateStr << endl;
}
cout << "----------------------------------------" << endl;
}
#end
Any help would be appreciated, thanks.
I've finally succeeded, using the c++ port of "spatial-media" instead of Adobe's xmp toolkit.
spatial-media (github repository)
I want to use Google protocol buffer in c++ on Ubuntu in first step I created .proto file
package business;
message Employee
{
required string first_name = 1;
required string last_name = 2;
required string email = 3;
}
message Company
{
required string name = 1;
optional string url = 2;
repeated Employee employee = 3;
}
I can easily translate it to the C++ data access classes by calling:
protoc -I=. --cpp_out=. business.proto
after this step protoc create to file
business.pb.h
business.pb.cc
when I want compile this code I see error
#include <iostream>
#include <fstream>
#include "business.pb.h"
using namespace std;
/// Saves a demo company object to 'company.bin'.
void save()
{
business::Company company;
company.set_name("Example Ltd.");
company.set_url("http://www.example.com");
// 1st employee
{
business::Employee *employee = company.add_employee();
employee->set_first_name("John");
employee->set_last_name("Doe");
employee->set_email("john.doe#example.com");
}
// 2nd employee
{
business::Employee *employee = company.add_employee();
employee->set_first_name("Jane");
employee->set_last_name("Roe");
employee->set_email("jane.roe#example.com");
}
fstream output("company.bin", ios::out | ios::trunc | ios::binary);
company.SerializeToOstream(&output);
}
/// Loads a demo company object from 'company.bin' and dumps its data.
void load()
{
business::Company company;
fstream input("company.bin", ios::in | ios::binary);
company.ParseFromIstream(&input);
cout << "Company: " << company.name() << "\n";
cout << "URL: " << (company.has_url() ? company.url() : "N/A") << "\n";
cout << "\nEmployees: \n\n";
for(int i = 0, n = company.employee_size(); i < n; ++i)
{
const business::Employee &employee = company.employee(i);
cout << "First name: " << employee.first_name() << "\n";
cout << "Last name: " << employee.last_name() << "\n";
cout << "Email: " << employee.email() << "\n";
cout << "\n";
}
}
int main()
{
save();
load();
return 0;
}
for compile I use this command
g++ p1.cpp business.pb.cc `pkg-config --cflags --libs protobuf`
but I see this error
https://i.stack.imgur.com/soQ3Z.png
i solved the problem
1)uninstall old version Google Protocol Buffer
2) instal new version Google Protocol Buffer
I am reading a avi file, and do some background subtrcation work. The wierd thing is when I use cvRetrieveFrame, I got a strange image, like below:
origin:
cvRetrieveFrame returns:
I don't know what's the problem. Here is my code snippet.
CvCapture* readerAvi = cvCaptureFromAVI( filename.c_str() );
if(readerAvi == NULL)
{
std::cerr << "Could not open AVI file." << std::endl;
return 0;
}
// retrieve information about AVI file
cvQueryFrame(readerAvi); //....get some information, width, height, ....
// grad next frame from input video stream
if(!cvGrabFrame(readerAvi))
{
std::cerr << "Could not grab AVI frame." << std::endl;
return 0;
}
frame_data = cvRetrieveFrame(readerAvi);