Saturday, March 28, 2015

More SQLite C API

In previous instalment we used sqlite3_open and sqlite3_prepare to connect to db file and execute select statement. Let us take a better look at it again. Those functions are legacy interface, we could use new sqlite3_open_v2 and sqlite3_prepare_v2 which are allowing us more control over execution and they are also recommended by SQLite development team. Let us look at sqlite3_open. This is from SQLite documentation:


In all three cases, the first argument is name of database file to be opened and the second one is handle:

typedef struct sqlite3 sqlite3;


We will need that handle to manipulate db and close it at the end. From comment we see that string with name of db file could be UTF-8 or UTF-16 encoded. What are flags? Here are definitions:


I will wisely skip last four, for now. If we specify SQLITE_OPEN_READWRITE we should be able to read and write, unless OS have marked file as read only, file must exist or error is returned. In order to simulate behavior of sqlite3_open we should use  SQLITE_OPEN_READWRITE |  SQLITE_OPEN_CREATE. The fourth argument of sqlite3_open_v2 function is name of the sqlit3_vfs object that defines the operating system interface that the new database connection should use. If we pass NULL as the fourth argument we get default sqlit3_vfs object.
If  sqlite3_open_v2 doesn't return SQLITE_OK, we have error and we should exit. We still may have proper db handle or NULL handle, calling sqlite3_close with NULL pointer is not problem.
So, we have something like this as template:


Call to sqlite3_errmsg should return string with description of message. We want to do resource management and to match  sqlite3_open with sqlite3_close. If we compile this and we do not have some.db file, after execution we should see descriptive error message.

./test
Failure to open database: unable to open database file


While passing to sqlite3_close NULL pointer is not problem, passing to it handle of already closed connection is problem.
Situation with sqlite3_prepare_v2 is similar to  sqlite3_open_v2, new API is preferable to legacy one and it should be used. Here both new and legacy functions are accepting the same number of arguments but behavior is different. Please check in documentation how they differ.


There is also UTF-16 version with about the same arguments. It prepares statement, compiles it to bytecode  and if successful returns pointer to compiled  sqlite3_stmt.


After statement is successfully prepared we iterate using sqlite3_step and at the end we finalize statement. In the case of sqlite3_prepare  returning error, we in general want to check is statement handle points to something and do cleanup if it does.
There is convenience wrapper around  prepare_v2-step-finalize, it is sqlite3_exec.


If we are doing insert, we do not really need callback, so we pass NULL pointer as the third and fourth argument.


If we don't have table jane in test.db exec will return error.

Exec failure: no such table: jane

or if we execute it more than once:

Exec failure: PRIMARY KEY must be unique

Error message is allocated using sqlite3_malloc and we have to free it using sqlite3_free.

Friday, March 27, 2015

SQLite C API introduction

I guess you are already using some kind of Linux if you are reading this. Install SQLite libraries and dev libraries, on my box they are called libsqlite3-0 and libsqlite3-dev. On your Linux packages may be called slightly differently. For example if your distro is Debian based you will check for packages executing in terminal:

apt-cache search sqlite

You do not need elevated privileges to execute that.
Also install sqlite3 command line interface for SQLite 3.
SQLite is embedded relational database engine. It was popular before but then Android made it part of OS and now it is like totally popular. There is no server and consequently no SQLite database administrator.
In order to build examples we need to specify linker switch, like this:

gcc testme.c -lsqlite3 -o test

Everything should be in path. Also we need to include appropriate header file in example:


We open database file, if it doesn't exist it will create it, if it can't we report error and exit. Next, we prepare statement, using legacy interface, and again check for error. Function sqlite3_step evaluates prepared statement, similarly we retrieve some metadata and print that to standard output.
Before we run example we will create table so that we can show some kind of output from our program. All that in the same folder where is binary, so that we don't have to fiddle with full path.



Now we can run our test program and see output like this.

type    name    tbl_name    rootpage    sql   
------------------------------------------------------
table    jane    jane    2    CREATE TABLE jane ( id INTEGER PRIMARY KEY NOT NULL, title TEXT, full_name TEXT NOT NULL )   


That was simple connect to database and select, there will be more in next instalment.

Wednesday, March 25, 2015

PostgreSQL C++ tutorial

Installation and configuration

This tutorial is done on LinuxMint 12 and it will work on Ubuntu 11.10. I tested it tonight on Linux Mint 13 Maya and can confirm that it still works here, that is Ubuntu Precise based Linux Mint.
Using terminal we find what is available:

apt-cache search postgresql

those are results we are interested in:

libpqxx-3.0 - C++ library to connect to PostgreSQL
libpqxx-3.0-dbg - C++ library to connect to PostgreSQL (debugging symbols)
libpqxx3-dev - C++ library to connect to PostgreSQL (development files)
libpqxx3-doc - C++ library to connect to PostgreSQL (documentation)
postgresql-9.1 - object-relational SQL database, version 9.1 server
postgresql-client - front-end programs for PostgreSQL (supported version)
postgresql-client-9.1 - front-end programs for PostgreSQL 9.1
postgresql-client-common - manager for multiple PostgreSQL client versions
postgresql-common - PostgreSQL database-cluster manager
postgresql-contrib - additional facilities for PostgreSQL (supported version)
postgresql-contrib-9.1 - additional facilities for PostgreSQL


It will return much more but we do not need them all. On Linux Mint 13 we have slightly fesher libs:

libpqxx-3.1 - C++ library to connect to PostgreSQL
libpqxx-3.1-dbg - C++ library to connect to PostgreSQL (debugging symbols)


Now in terminal we do

sudo apt-get install postgresql-9.1 postgresql-client postgresql-client-9.1 postgresql-client-common postgresql-common postgresql-contrib postgresql-contrib-9.1

or if one like gui, Software Manager or Synaptic will also do. Do not forget contrib packages, you will need them for pgAdmin III.
Again in terminal do:

sudo su postgres

afer entering password you are postgres. As postgres:

psql template1
psql (9.1.3)
Type "help" for help.
template1=# create role testuser login password 'testpass' superuser valid until 'infinity';
CREATE ROLE
template1=#\q


That escaped q quits psql and after one exit you are back to your login. If you like install now pgAdmin III or using psql create DB and table where you are going to practice.
To allow remote connections do:

sudo gedit /etc/postgresql/9.1/main/postgresql.conf

and modify listen_addresses, something like this:

listen_addresses = 'localhost, 192.168.0.42, 192.168.0.111'

Also in pg_hba.conf we need to enable remote users:

sudo gedit /etc/postgresql/9.1/main/pg_hba.conf

it should look something like this, all the way towards bottom of the file:

# IPv4 local connections:
host    all             all             127.0.0.1/32            md5
host    template1       testuser        192.168.0.0/24           md5
host    testpgdb        testuser        192.168.0.0/24           md5

There is number of commented lines in file but I ignored them to save space. After saving changes restart PostgreSQL server:

sudo /etc/init.d/postgresql restart

Please create DB testpgdb with sufficient rights for testuser or rename DB in C++ example.
Now it is time to install libpqxx. From terminal execute:

sudo apt-get install libpqxx-3.0 libpqxx-3.0-dbg libpqxx3-dev libpqxx3-doc

and installation is done. As already mentioned on newer versions of Linux it may be newer version of libpxx, so please adjust accordingly.

C++ example

Code is slightly adjusted test 005 which comes with libpqxx3-doc, to see where is what use:

dpkg -L libpqxx3-doc

It connects to local instance of PostgreSQL, if you want remote – please edit connection string. If connection succeeds creates table, inserts data and at the end does one non-transactional select.


In order to compile code you will need to tell to g++ where are libpqxx headers (they are not on the path) and also to linker what libs must be used for linking. Something like this:

g++ hello.cxx -o hello -I/usr/local/include/ -lpqxx -lpq


If your libpqxx or libpq are on unusual place you will use -L[path to where they are], there is lot of that on CentOS or Fedora ;-)
 After executing hello (./hello) you should be rewarded with the following output:

We are connected totestpgdb
NOTICE:  ALTER TABLE / ADD PRIMARY KEY will create implicit index "PK_IDT" for table "tabletwo"
        1       John    0
        2       Jane    1
        3       Rosa    2
        4       Danica  3


I can write more on subject if there is interest in it, will see from number of hits.

Monday, March 23, 2015

Few filters from ffmpeg filter library

If you are using WinFF with Display Cmd Line option, then from DVD preset you already know how scaling look like. For example

-vf scale=720:480

That would be width and height of output. With Additional Options activated WinFF will allow you to specify crop values. Unfortunately it will place them in wrong order if you are doing crop and scale. Placing crop in front of scale is preferable.

-vf crop=iw-50-10:ih-20-20:50:20,scale=720:480

Crop parameters are width, height and start point. It calculates it from input with, height and parameters which you have entered. BTW if you need to crop and scale inside complex filter that looks like this:

ffmpeg -i input.mpg -i detail.mpg -filter_complex\
 "[0:v] setpts=PTS-STARTPTS, crop=iw-6-6:ih-0-0:6:0,scale=800x640 [big];\
 [1:v] setpts=PTS-STARTPTS, crop=iw-50-10:ih-20-20:50:20,scale=240x192 [detail];\
 [big][detail] overlay=shortest=1:x=560" -c:v libx264 out.mkv


Filter expressions are separated with coma as in non complex case.
Beside size and crop, commonly used filter is unsharp. With unsharp filter output may be sharper or softer, blured. It accepts six parameters and those are default values:

-vf unsharp=5:5:1.0:5:5:0.0

Parameters are, in order of aperance, luma matrix size, horizontal and vertical, odd integers between 3 and 63. Next we have luma effect strength which is float. Then we have the same but for chroma. Positive values for effect strength will sharpen image, negative will blur it and zero will disable effect. For example scale and make it sharper:

-vf scale=960:540,unsharp=9:9:0.75:9:9:0.75

If we want to blur image we will make floats negative.
Another filter which we may want to use is curves. Those are the same ones which we know from GIMP, Curves Tool under Colors. While describing curves may be somewhat complicated, there is number of presets available and they are:

none
color_negative
cross_process
darker
increase_contrast
lighter
linear_contrast
medium_contrast
negative
strong_contrast
vintage


We can even chain them if required. So, if we want lighter output image:

-vf scale=960:540,curves=lighter

More ambitious users will take a look at man pages and maybe decide to create their own presets. According to documentation ffmpeg can import curves from photoshop but I can not confirm that since I am not using it.

Sunday, March 22, 2015

Join two videos using ffmpeg and fade filter

Imagine that you retrieved your video from your camera, tablet, mobile phone, Internet and converted it to mpeg. After resizing and encoding of 43.8 Mbps 1920x1080 input video produced by Canon camera we can end up with some more modest resolution. Using Avidemux we can precisely find and cut segments from one keyframe to another. You can append those segments like this:

ffmpeg -i sa0.mpg -i sa1.mpg -filter_complex \
 "[0:0] [0:1] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]" \
 -map '[v]' -map '[a]' -c:v mpeg2video -q:v 2 out.mpg


We want video quality 2, we want mpeg video codecs, and we want both video and audio to be in output. Audio will be default mp2 to match video, since we didn't specify any. ffmpeg will print to standard output how it “understands” our instructions:

Output #0, mpeg, to 'out.mpg':
  Metadata:
    encoder         : Lavf55.3.100
    Stream #0:0: Video: mpeg2video, yuv420p, 960x540 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 90k tbn, 29.97 tbc
    Stream #0:1: Audio: mp2, 44100 Hz, stereo, s16, 128 kb/s


Whatever we didn't specify ffmpeg will or pick up from input video or adjust to match output container. I assume here that both videos are from the same original video and for that reason I didn't resize or resample videos, if that is required one can do it as preprocessing. That will append our two videos but it will be rather abrupt and not very smooth event. Luckily ffmpeg got rich library of filters and we can fade out and in to make smooth transition between two segments. We can fade just video or we can fade both, video and audio.

ffmpeg -i sa0.mpg\
 -vf fade=out:8928:36 -af afade=t=out:st=297.5:d=1.5\
 -c:v mpeg2video -q:v 2 output1.mpg


This is the first segment and we want to fade out last 36 frames and also last 1,5 seconds of audio. Video fade parameters are expressed in frames, start at frame and fade duration in frames, audio afade is about the same but in seconds. If we do not want to fade audio track we will omit audio filter story. Now we want to fade in next segment:

ffmpeg -i sa1.mpg\
 -vf fade=in:0:36 -af afade=t=in:st=0:d=1.5\
 -vcodec mpeg2video -q:v 2 output2.mpg


Starting from zero we fade in 36 frames of video and 1,5 seconds of audio signal. After we join those two segments we will have smooth fade out and in transition:

ffmpeg -i output1.mpg -i output2.mpg -filter_complex \
 "[0:0] [0:1] [1:0] [1:1] concat=n=2:v=1:a=1 [v] [a]" \
 -map '[v]' -map '[a]' -c:v mpeg2video -q:v 2 out.mpg


The same as we did without fading.

Saturday, March 21, 2015

Encoding with ffmpeg

Join two videos

Unless one have production ambitions, encoding on Linux is rather simple and user friendly. Install ffmpeg, WinFF and get presets for WinFF. Thanks to WinFF menu option Display Cmd Line one can see what arguments are passed to ffmpeg to achieve this or that. For example you want 30 seconds from one and 30 seconds from another place in video.

ffmpeg -i input.mp4 -filter_complex \
"[0:v]trim=500:530,setpts=PTS-STARTPTS[v0]; \
 [0:a]atrim=500:530,asetpts=PTS-STARTPTS[a0]; \
 [0:v]trim=900:930,setpts=PTS-STARTPTS[v1]; \
 [0:a]atrim=900:930,asetpts=PTS-STARTPTS[a1]; \
 [v0][a0][v1][a1]concat=n=2:v=1:a=1" \
 -c:v libx264 output.mkv

 Start at 500 seconds, use 30 seconds of video and audio and then from 900 seconds do the same. Concat output and encode using lib264. Filters trim and atrim will help you with ref frames, the first is video and the second one is audio version. Next we have setpts and asetpts, again video and audio version. We want PTS Presentation Time Stamp to start from zero. Finally we have concat filter where we specify two parts to be concatenated into one video and one audio. What are square brackets? Those at the start of line are saying take video or audio from input array at position zero. Since we have only one video all left tags are zero. Right tags are our friendly names to segments, we use them at the end to say how to concat segments to output.
If you see something like this, when you try concating two segments:

[AVFilterGraph @ 0x2e9be00] No such filter: 'trim'
Error configuring filters.


Then you download source, build and install ffmpeg. For more precise editing one may want to use Avidemux and for that video files must be converted to mpeg. WinFF have DVD settings which you are going to use. It will not specify audio conversion parameters, if you do not want default ones you just append this to what WinFF says:

-acodec mp2 -ar 44100 -ab 128k -ac 2

That is use mp2 codec, sampling 44.1KHz, bit rate 128Kbps and number of channels. With Avidemux you can do frame by frame, variable speed searching and so on.

Video in video

In existing video you want to insert some kind of detail in upper right corner.

ffmpeg -i input.mpg -i detail.mpg -filter_complex \
  "[0:v] setpts=PTS-STARTPTS, scale=800x640 [big];\
  [1:v] setpts=PTS-STARTPTS, scale=240x192 [detail];\
  [big][detail] overlay=shortest=1:x=560" -c:v libx264 out.mkv


Here we resize both videos, tag them with friendly names and for overlay specify where we want detail to start. Since we didn't specify y it will be zero. That shortest=1 means when end of shortest input is reached, stop encoding. Audio signal will be copied from the first video input.

Mosaic of several videos

This one is nicely explained at Create a mosaic out of several input videos at ffmpeg site. I will not bother you with explanation which you can read there but I am going to give you command to create 6x2 mosaic:

ffmpeg -i a.mpg -i b.mpg -i c.mpg -i d.mpg -i e.mpg -i f.mpg -filter_complex\
 "nullsrc=size=1920x960 [base];\
 [0:v] setpts=PTS-STARTPTS, scale=640x480 [upperleft];\
 [1:v] setpts=PTS-STARTPTS, scale=640x480 [uppermiddle];\
 [2:v] setpts=PTS-STARTPTS, scale=640x480 [upperright];\
 [3:v] setpts=PTS-STARTPTS, scale=640x480 [lowerleft];\
 [4:v] setpts=PTS-STARTPTS, scale=640x480 [lowermiddle];\
 [5:v] setpts=PTS-STARTPTS, scale=640x480 [lowerright];\
 [base][upperleft] overlay=shortest=1 [tmp1];\
 [tmp1][uppermiddle] overlay=shortest=1:x=640 [tmp2];
 [tmp2][upperright] overlay=shortest=1:x=1280 [tmp3];\
 [tmp3][lowerleft] overlay=shortest=1:y=480 [tmp4];\
 [tmp4][lowermiddle] overlay=shortest=1:x=640:y=480 [tmp5];\
 [tmp5][lowerright] overlay=shortest=1:x=1280:y=480"\
 -c:v libx264 output.mkv


You will need large monitor to enjoy your mosaic. Again you will have audio from the first video in input. If combining audio makes sense, I would rather extract audio and mix tracks in Audacity where levels can be adjusted. Now with example at ffmpeg wiki and this one I guess one can easily create different overlays like large video left and two half size ones on the right and similar.

Saturday, May 31, 2014

About ffmpeg tutorial

If you want to work with ffmpeg from your code, you may want to build it from source. How to build it on your Linux distro, or possibly some other operating system, is described in Compilation Guide at ffmpeg wiki. For updated tutorial code one will also want to install git. I was working on LinuxMint, so commands used in this article are Debian-centric.
Latest ffmpeg tutorial is written by Dranger and it is severely outdated. If you visit his website you will see that his tutorial is remake of older tutorial written by Martin Bohme. Few programmers have made attempts to keep code for this tutorial in sync with current ffmpeg API. One can find updated code in git repository git@github.com:chelyaev/ffmpeg-tutorial.git. So, open terminal, cd where you want to clone repo and execute

git clone git@github.com:chelyaev/ffmpeg-tutorial.git
cd ffmpeg-tutorial
git log


Last line will print log and it will start from freshest commits, to advance towards oldest ones we press space. In order to see what changes have been made on tutorial01.c between initial import and working version we execute in terminal:

git log -u 3e1426115418ae50cb9a4357d57afbcec69342fe..69b7f32f5edb38cc4e9c47711f100998404485d1 tutorial01.c

Those hashes separated by double dot we got from previously executed git log and what set of changes is hash for we know from comment bellow hash. This one I used to see what was changed in tutorial01.c to make it work.
If we go through commits we will find in few comments that sound is not being decoded as expected, that is actually main reason why I am fiddling with this tutorials. You go through only available tutorial for ffmpeg and end up debugging sound problems, not very encouraging.

SDL

Original Dranger tutorial is called An ffmpeg and SDL Tutorial, so let us take a look at SDL. We will output our video to SDL and I prefer to familiarize with SDL before I use it.
If we have done what Compilation Guide for ffmpeg says, we already have SDL 1.2 installed. In order to find header files, man pages and similar we use:

dpkg -L libsdl1.2-dev

That will list installed files and help with includes for our hello world code.


There is uninitialized SDL_Surface pointer, why I didn’t set it to NULL? Because SDL_SetVideoMode will set it to NULL if it fails. Path to include file is sorted out within code, linker instructions are added and we can build it and run it.

gcc helloSDL.c -lSDL -o helloSDL
./helloSDL


And half painted window should show up. Simple use API program where SDL is initialized, later surfice created and quit event handler resource cleanup is done. To better understand what code does please execute in terminal man followed by function name.

Building ffplay

Tutorial relies on ffplay.c which is part of ffmpeg source and currently only (partly) working example how to use ffmpeg to create simple video player. That is very simple but there may be some of us who are not very familiar with GNU make. We follow Compilation Guide and set environment variables, cd to ffmpeg source directory and in terminal execute:

PKG_CONFIG_PATH="$HOME/work/ffmpeg_build/lib/pkgconfig"
export PKG_CONFIG_PATH
./configure --prefix="$HOME/work/ffmpeg_build" --extra-cflags="-I$HOME/work/ffmpeg_build/include" \
   --extra-ldflags="-L$HOME/work/ffmpeg_build/lib" --bindir="$HOME/work/bin" --extra-libs="-ldl" --enable-gpl \
   --enable-libass --enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus \
   --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-nonfree --enable-x11grab


Config will take a while and doesn’t provide feedback about progress, so be patient. I decided to build it and install it in ~/work folder instead in suggested $HOME, if you like to follow original just grep and remove work/. Now to get commands required to compile and link cmdutils.c and ffplay.c execute in terminal:

make -n > ~/dry_run

I outputed it to file since it produces quite large output and it may be interesting to look at it again. Simple grep for cmdutils.c and ffplay.c will return required instructions. Skip start of the line:

printf "CC\t%s\n" cmdutils.o;
printf "CC\t%s\n" ffplay.o;
printf "LD\t%s\n" ffplay_g;


and use compile commands from gcc -I. -I./ ... and link command from gcc -Llibavcodec -Llibavdevice ...
Link command will produce executable ffplay_g and it is located right under compile command for ffplay.o. Now you can nicely modify, build and debug ffplay.