Showing posts with label Qt Creator. Show all posts
Showing posts with label Qt Creator. Show all posts

Sunday, March 17, 2013

Raspberry Pi Wheezy Image With Qt and Wayland Support

According to what I read around, it should be possible to install some build of Qt 5 using apt on Raspberry by adding the Qt repo: read here.

However, some asked for a version of Qt compiled for Pi, so, if that was not ok for you for some reason, this is an entire image with many packages for which Qt has support and includes wayland and QtMultimedia (what is working oob).
This is the configuration of the build:

Bulding on: linux-g++
Building for: devices/linux-rasp-pi-g++
Architecture: arm, features:
Host architecture: i386, features:
Platform notes:

- Also available for Linux: linux-kcc linux-icc linux-cxx

Build .................. libs examples
Configuration .......... cross_compile qpa largefile neon pcre minimal-config small-config medium-config large-config full-config fontconfig libudev evdev linuxfb c++11 accessibility egl eglfs opengl opengles2 shared qpa reduce_exports reduce_relocations clock-gettime clock-monotonic mremap getaddrinfo ipv6ifname getifaddrs inotify system-jpeg png system-freetype system-zlib nis iconv glib gstreamer dbus openssl rpath alsa icu concurrent audio-backend v8 v8snapshot release
Debug .................. no
C++11 support .......... yes
pkg-config ............. yes
Qt D-Bus module ........ yes (run-time)
Qt Concurrent code ..... yes
Qt GUI module .......... yes
Qt Widgets module ...... yes
JavaScriptCore JIT ..... To be decided by JavaScriptCore
QML debugging .......... yes
PCH support ............ no
iWMMXt support ......... no
NEON support ........... yes
IPv6 ifname support .... yes
getaddrinfo support .... yes
getifaddrs support ..... yes
Accessibility .......... yes
NIS support ............ yes
CUPS support ........... no
Iconv support .......... yes
Glib support ........... yes
GStreamer support ...... yes
PulseAudio support ..... no
Large File support ..... yes
GIF support ............ plugin
JPEG support ........... plugin (system)
PNG support ............ yes (qt)
zlib support ........... system
Session management ..... auto
libudev support ........ yes
Use system proxies ..... no
OpenGL support ......... yes (OpenGL ES 2.x)
OpenVG support ......... no
XShape support ......... auto
XVideo support ......... auto
XSync support .......... auto
Xinerama support ....... runtime
Xcursor support ........ runtime
Xfixes support ......... runtime
Xrandr support ......... runtime
Xi support ............. runtime
Xi2 support ............ auto
MIT-SHM support ........ auto
FontConfig support ..... yes
XKB Support ............ auto
GTK theme support ...... no
SQLite support ......... plugin (qt)
OpenSSL support ........ yes (run-time)
Alsa support ........... yes
libICU support ......... yes
PCRE support ........... qt
Xcb support ............ no
Xrender support ........ no
EGLFS support .......... yes
DirectFB support ....... no
LinuxFB support ........ yes
KMS support ............ no


The modules I compiled are:
  1. qtbase
  2. qtscript
  3. qtjsbackend
  4. qtdeclarative
  5. qtgraphicaleffects
  6. qtimageformats
  7. qtmultimedia
  8. qtquick1
  9. qtsvg
  10. qtwayland
  11. qtwebkit
  12. qtwebkit-examples-and-demos
  13. qtxmlpatterns
  14. qt3d

How to Use to Build

To build code with this you need to dd the image to an SD card (4GB at least), and setup your system to cross-compile using the same libs.
First transfer the image to the SD:

tar xvfp wheezy_qt5_20130310.tar
tar xvfpj wheeze_image_20130310_qt5.tar.bz2
sudo dd if=wheezy_image_20130310.img of=your_sd_dev

Then transfer all the libs you need to cross-compile in your sysroot, which must be located in /opt/rpi/sysroot.

sudo mkdir /opt/rpi
sudo mkdir /opt/rpi/sysroot
cd /opt/rpi/sysroot
sudo scp -r root@rpi_ip:/lib root@rpi_ip:/opt .
sudo mkdir usr
sudo scp -r root@rpi_ip:/usr/lib root@rpi_ip:/usr/include root@rpi_ip:/usr/local usr


Now place the Qt tools into your system:

tar xvfpj Qt-rasp-5.0.2_build_rools.tar.bz2
sudo mv Qt-rasp-5.0.2 /usr/local

Setup Qt Creator to Cross-Compile

You should now be able to setup Qt Creator to cross-compile. Open Qt Creator, got to the Window -> Options -> Build & Run. Open the "Compilers" tab and add the new cross-compiler.
Setup the Qt version by selecting the qmake binary from /usr/local/Qt-rasp-5.0.2/bin/qmake.
Setup a new kit by setting both the compiler and the Qt version you just added.
You should be done.

Download the Package

The package is large since it contains the entire image, including all the needed packages. Try to download from here (sorry, I experienced too much traffic so I had to remove it, you can try with this torrent or this ftp, but both will take long; please let me know if you experience troubles).
The userid is pi and the passwords are rasp for both the user pi and root.

Edit 04.16.2013 

I see that many are still trying to download and the server is permanently at full upload speed, I suppose it is better to start using p2p: use this ed2k link to download. I'm sharing this with priority. If you're already downloading via FTP, then please complete the download as quickly as possible; I'll remove the file in a couple of days. In case you experienced issues, please leave a message.

Saturday, February 23, 2013

QML Components for Video Decoding and Rendering POC Code Available

As requested I shared the sources of the demo videos I posted recently. I tested these components with a few videos and I saw that it seems to work "reasonably well" also for 1080p h264 high profile with 5.1 audio. The current implementation uses a player class which decodes data and a surface class that renders. Rendering the video on more surfaces seems to work.

Beware that the code is not complete, it is only a proof of concept of how to implement. If you need to use it in production code, you'll have to work pretty much on it. There are many TODO's left and no testing has been run on the classes. The cleanup code must be completely rewritten and only pause/resume/stop commands are implemented at the moment. Also consider going through the relevant code for leaks, I didn't pay much attention when implementing because it was my idea to refactor, sorry.

Only 1080p resolution is currently supported, never even tried anything different, you'll probably have to look around and see where I hardcoded those values (I was in a hurry :-))
There are many unused classes in the code, I left those there only because those might be useful for new implementations.

I started to work on other things recently, so I really have few time to work on this. But still I see that many are interested, so I decided that incomplete code is better than no code. Also, I have to say I have no practical need of these components, I only worked on this as a challenge in my spare time. Now that there is no challenge anymore, I have to say I lost some interest and I'm looking for a new one :-D

This is the github URL of the repo (PiOmxTextures is the project directory):

https://github.com/carlonluca/pi

The current implementation of the OMX_MediaProcessor class uses the components implemented in the omxplayer code, with modifications to some of those. Those modified sources are placed in the omxplayer_lib directory in the project sources: I chose this architecture to make it relatively simple to merge the changes from the omxplayer sources.

How to build

To build the project, you'll need a build of the Qt libraries, version 5.0.0 at least. Instructions on how to build can be found around the web. I also wrote a quick article on that if you need it (this is the updated version for 5.0.1).

Once you have your Qt build and Qt Creator setup, you can open the .pro file. You should also have the Raspberry sysroot somewhere in your system, and that should be known by Qt Creator. The project is based on the same dependencies of omxplayer, so you need those as well. I tested this only against a specific build of ffmpeg, which is the one omxplayer was using when I last merged: to compile you can use this script, which is included in the source tree. Just running it passing the number of compilation thread to use should be sufficient:

git clone https://github.com/carlonluca/pi
cd pi/PiOmxTextures/tools
./compile_ffmpeg.sh n
cd ../../
mkdir PiOmxTextures-build-rasp-release

cd PiOmxTextures-build-rasp-release 
path_to_qmake/qmake "DEFINES+=CONFIG_APP" ../PiOmxTextures
make -jn


Pay attention that the sample application renders a file whose path is hardcoded in the qml file. Change that if you want to test the sample code.

As said, this is just a proof of concept and I do not have much time to maintain it. If you want to help to fix the code and to merge new changes, issue a merge request!
Hope this code might be of help for other open source project! Feel free to leave a comment if you have any! Bye!

Friday, August 17, 2012

Programming using the Android NDK with Qt Creator

I recently had to implement libraries for the Android OS using the Android NDK, or implementing JNI bindings for others to leverage C++ libraries from the Java layer. I commonly did this using simple toold like kate or similar text editors. To be sincere, it was not a completely satisfying approach.
During one of my projects, I had to port a Qt application to Android, using the excellent necessitas SDK. This excellent SDK made it possible to implement for Android using C++, the NDK and Qt Creator as the preferred IDE. I started from here to think I could use Qt Creator to more generally program in C++/JNI to implement libraries for Android, with or without the Qt libraries. This is how I did it.

Download the necessary tools

  1. Download the Qt libraries (I won't use the libraries, I only need the environment).
  2. Download Qt Creator.
  3. Download the Android NDK for your platform.

Add the Android platform specification

I took the platform specification used in the necessitas project and modified it a bit. Look for the directory containing the platform specifications (<qt_libs>/mkspecs), and place in there the platform specification file and the qmake configuration file. You'll have to define at least the ANDROID_NDK_ROOT to the root of the NDK you downloaded.

Setup Qt Creator

In Qt Creator you can specify a new toolchain to use: go to the preferences, "Build & Run", "Toolchains", "Add" and choose "GCC". Then, select the gcc compile from the Android NDK (I see it under <ndk_root>/toolchains/arm-linux-androideabi-4.4.3/prebuilt/darwin-x86/bin/arm-linux-androideabi-g++).
You'll have to create a new build configuration in the project properties: add a new specification with the default build specification and name it differently. Also, under "Build Steps", add "-spec android-g++" to the additional arguments. This will tell Qt Creator to build according to the Android specifications we added before. Also, select the Android toolchain in the "General" section.

Additional setup

Consider that I also had to remove QMAKE_INCDIR_QT in some cases because it was adding /usr/include to the include paths, thus making the build fail. You may want to add that to the qmake.conf file.

Creating native executables for Android using qmake and Qt Creator

It is sometime useful to creato native executables for Android. You can use this technique to do it very simply. For instance, this is a test I created in a minute (you can use Qt Creator or the command line directly):

nano TestProject.pro

QT              -= core gui
TEMPLATE        = app
SOURCES         = main.cpp
QMAKE_INCDIR_QT =

Now write a simple "Hello Android!" application:

nano main.cpp

#include <stdio.h>

int main(int argc, char** argv)
{
   printf("Hello Android!\n");
   return 0;
}

Now create the Makefile using qmake and the android platform specification:

qmake -spec android-g++
make

You'll get a TestProject execuable compiled for arm platform using the Android bionic C libraries. You can try uploading to an Android emulator:

luca-macbook:test_project luca$ adb remount
remount succeeded
luca-macbook:test_project luca$ adb push TestProject /data
173 KB/s (34639 bytes in 0.195s)
luca-macbook:test_project luca$ adb shell
# cd /data
# ./TestProject
Hello Android!
# rm TestProject

I used this approach on both Mac OS X and Linux. Never tried on Windows.

Wednesday, May 2, 2012

Embedded cross-platform development for Android, iOS and Linux Embedded

I recently came across a new problem: cross-platform development of libraries on iOS, Android and Linux Embedded devices. What I wanted was a cross-platform way of writing a library letting me perform as much non-GUI work as possible.

The only reasonable solution I could think of was developing the library entirely in C/C++ language. This can be quite long, but simple to recompile for all these platforms. Linux Embedded should commonly support entire C/C++ toolchains (like Codesourcery toolchains), iOS supports standard C/C++ quite well and can be used very simply from Objective-C using Objective-C++ and Android can make use of C/C++ libraries through a JNI interface (not as much quick as the others, but possible).

Ok, then C/C++ is my choice. Anyway, would it possible to increase my productivity by using some kind of general purpose C/C++ library instead of relying only on the standard library? There are many possible solutions to this, one of which is the Neptune library.

During the last months anyway, I've come to be very close to the Qt libraries. I started to love the completeness, the flexibility and the comfortable API Qt provides.

I've been looking with interest for months to the new development of the Qt porting to Android (thanks to BogDan Vatra) and iOS but I never had the chance to try. Anyway, those ports make use of the QPA build of Qt, which started with the Lighthouse project to provide Qt portability on the GUI level to other platforms. This is not exactly what I needed: I'm not interested at the moment on the GUI development. What I need is simpler. Anyway, I found this very useful to start working.

The environment I'm currently working with allows me to create a common Qt Makefile to be parsed by qmake to generate a Makefile for any platform I need: for Android the toolchain provided by the NDK and for iOS the toolchain provided by Apple.

After this introduction, I explain the steps I followed to setup the environment.

Setting up for Android development

First thing to do is to download the Android NDK from the official website. Uncompress it somewhere.

Download and compile the Android port of Qt: it might be good to compile a specification file for the build, it is quite simple, but the Android's toolchain is not a complete toolchain. This implies that some modifications to the Qt sources are needed. I started to do it, but for the moment simply downloading from the git the last sources from Necessitas is good enough.

Now you have both the Android toolchain and the Qt sources compiled for Android. You can select the new Qt platform and compile directly from Qt Creator. This is damn good, cause it makes it quite simple to implement the JNI interface also, which I've never found a way to write comfortably from Eclipse.

Once the library is compiled, you can place it into an Android project as instructed in the manual of the Android NDK and all is done. You have C/C++ sources with Qt support ready to be used in an Android project. You can also implement the JNI interface and include the sources only when building for android using the qmake scopes.

Setting up for iOS development

It might seem a paradox, but I found it more difficult to compile for iOS than for Android... What you can do is use the QPA specification for iOS that can be found in <Qt sources>/mkspecs/qpa/macx-iphone*. By using qmake from the command line you can create a Makefile for iOS and then compile it on a Mac:

qmake -spec qpa/macx-iphonesimulator-g++


you can also directly include Objective-C and Objective-C++ sources directly into the Qt project file by using the variable:

OBJECTIVE_SOURCES += source_list


Just remember that only static libraries are allowed on iOS, so include something like:


ios {
CONFIG += static
}

 

to compile statically when on iOS.

When I tried this for the first time it didn't work. It seems that for some reason there is a difference between my XCode setup and the one used as a reference for the platform specification. What I had to do is to fix the qmake.conf specification for the iOS platform so that I compiles correctly. I found this article very useful to see what needed to be changed.
In particular, for recent versions of Xcode, I had to change the variable QMAKE_IOS_DEV_PATH (in mkspecs/qpa/macx-iphonesimulator-g++/qmake.conf) from:

QMAKE_IOS_DEV_PATH = /Developer/Platforms/iPhoneSimulator.platform/Developer


to:

QMAKE_IOS_DEV_PATH = /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer

and the QMAKE_IOS_SDK_VERSION (in mkspecs/qpa/common/g++-base-macx-iphone.conf) to 5.1.

Using Qt libraries on Android and iOS

There is one other point when implementing libraries using Qt: many Qt features require an event loop to be running and that an instance of QCoreApplication to be instantiated somehow. To do this, it might be sufficient to run the event loop and instantiate QCoreApplication in a thread of the library: in the init function, just spawn a new thread and exec the event loop.
This is an example of what I tried: first I created a Java class like this:

package com.lukeshq.android.test.qt;

/**
 * Author Luca Carlon
 * Date: 05.10.2012
 */

public class QtTest {
   // Static initializer.
   static {
      System.loadLibrary("QtCore");
      System.loadLibrary("AndroidTest");
   }

   public QtTest() {
      new Thread(new Runnable() {
         @Override
         public void run() {
            while (true) {
               try {
                  Thread.sleep(1000);
               }
               catch (InterruptedException e) {
                  e.printStackTrace();
               }
               mySlot();
            }
         }
      }).start();
   }

   // Native interface.
   public native boolean mySlot();
}

then, in my library, I created a simple object like this:

class MyQObject : public QObject
{
   Q_OBJECT
public:
   explicit MyQObject(QObject* parent = 0);

public slots:
   void mySlot();
};

and this is the implementation of the bindings:

/*----------------------------------------------------------------------
|    includes
+---------------------------------------------------------------------*/
#include <QString>
#include <QtConcurrentRun>
#include <QCoreApplication>
#include <QTimer>
#include <jni.h>
#include <android/log.h>
#include "myqobject.h"

/*----------------------------------------------------------------------
|    declarations
+---------------------------------------------------------------------*/
MyQObject* myQObject;

/*----------------------------------------------------------------------
|    runQCoreApplication
+---------------------------------------------------------------------*/
void runQCoreApplication()
{
   // Instantiate QCoreApplication.
   int i = 1;
   char* c[1] = {"MyLib"};
   QCoreApplication a(i, c);

   // Start the QTimer.
   __android_log_print(ANDROID_LOG_INFO, "LibTag", "Starting QTimer!");
   QTimer* t = new QTimer();
   myQObject = new MyQObject();
   QObject::connect(t, SIGNAL(timeout()), myQObject, SLOT(mySlot()));
   t->setInterval(1000);
   t->setSingleShot(false);
   t->start();

   // Start the event loop.
   a.exec();
}

/*----------------------------------------------------------------------
|    JNI_OnLoad
+---------------------------------------------------------------------*/
extern "C" JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM* vm, void* reserved)
{
   Q_UNUSED(vm);
   Q_UNUSED(reserved);

   // Test QString.
   QString myString = QString("My QString!");
   __android_log_print(ANDROID_LOG_INFO, "LibTag", "%s", qPrintable(myString));

   // Start the QCoreApplication event loop.
   QtConcurrent::run(&runQCoreApplication);

   return JNI_VERSION_1_6;

}

/*----------------------------------------------------------------------
|    JNI_OnUnload
+---------------------------------------------------------------------*/
extern "C" JNIEXPORT void JNICALL
JNI_OnUnload(JavaVM* vm, void* reserved)
{
   Q_UNUSED(vm);
   Q_UNUSED(reserved);

   __android_log_print(ANDROID_LOG_INFO, "LibTag", "Unloading!");
}

/*----------------------------------------------------------------------
|    Java_com_lukeshq_android_test_qt_QtTest_myslot
+---------------------------------------------------------------------*/
extern "C" JNIEXPORT void JNICALL
Java_com_lukeshq_android_test_qt_QtTest_mySlot(JNIEnv* env, jobject thiz)
{
   Q_UNUSED(env);
   Q_UNUSED(thiz);

   QMetaObject::invokeMethod(myQObject, "mySlot");
}