VMware Workstation 7 Released

VMware just released version 7 of their well known Workstation application. Here’s an interesting new feature many have been waiting for:

Aero Glass — A new Windows Display Driver Model (WDDM) graphics driver has been developed for Windows Vista and Windows 7 virtual machines. The WDDM driver can display the Windows Aero user interface, OpenGL 1.4, and Shader Model 3.0. For more information on the VMware recommended graphics hardware, see the VMware Workstation User’s Manual.

Full release notes can be found here.
Downloads are here.

Windows 7 x64 - VMware Workstation

Statically Linked Qt On Win32 Using MSVC

I have been trying to compile a statically linked version of Qt on Windows using MSVC for some time now but never found my way through until recently. There is a lot of information on the web about how to do this however I haven’t found one that actually worked for me (some information can be found on Trolltech’s website). So here’s yet another howto for using a static version of Qt with Visual Studio 2008!

What you need:

What you do (assuming VS2008 is already installed):

  1. Unpack the Qt sources. I used C:\Qt\4.5.3-win32-msvc2008 as target (%QTDIR%)
  2. If you have a multicore CPU you might want to speedup things by modifying %QTDIR%\mkspecs\win32-msvc2008\qmake.conf and adding those two lines (change 2 for the no. of CPUs you have):
    QMAKE_CXXFLAGS_RELEASE += -MP2
    QMAKE_CXXFLAGS_DEBUG += -MP2
  3. Next, open a Visual Studio 2008 Command Prompt (under the Start menu), go to %QTDIR% and run configure.exe with at least -static as option. I used the following (minimal build):
  4. configure.exe -debug-and-release -opensource -static -no-exceptions -no-accessibility -no-stl -no-qt3support -no-opengl -platform win32-msvc2008 -qt-zlib -qt-gif -qt-libpng -qt-libmng -qt-libtiff -qt-libjpeg -no-openssl -no-dbus -no-phonon -no-webkit -no-scripttools

  5. Once configured, start the build:
    nmake sub-src
  6. Install the Qt Visual Studio Addin
  7. In Visual Studio, under the Qt menu choose Qt Options. Under the Qt Versions tab click Add and type 4.5.3_win32-msvc2008 (or whatever you want) and fill in the path where you extracted the Qt sources
  8. Optionally you can test your installation by creating a new Qt Project, compiling it and running it.

Easy enough?! Happy Qt’ing!

UPDATE 15/10/2009: This also works with MS Visual Studio C++ Express Edition!

HD-PVR Post-production

As already posted, last year I bought the Hauppauge HD-PVR. Since I’m a geek (am I?!) and I like doing things my way, using all the software provided with the device wasn’t an option I was going to choose. Also, since I always want maximum picture quality I always set the HD-PVR to record at full bitrate (13.5Mpbs CBR).

As you can imagine recording at 13.5Mpbs will produce some quite big files, but thats all good as I have plenty of disk space to waste (temporarily). For example, a 1 1/2 hour recording will take approx. 9.7GB. That’s big, even with lots of disk space to waste. So, I convert the recording to at least an MKV (AVC/AAC) as an archive/computer playable version and sometimes a DVD (to watch on the TV set, which only has a DVD player, for now).

Now since I’m a command line freak (did I say I was a geek?!), here’s how I do it. In order to do the same you will need at least the following software (all free):

1. The first step is is to load the .TS (or M2TS) file in DGAVCIndex:

DGAVCDec

And save the whole stream into a DGA project (File -> Save Project or F4). This will also demux the audio and create a [filename] PID 1100 DELAY [delay]ms.aac file.

2. Then I create an Avisynth script to load the DGA project in VirtualDub to make a stream selection (strip the beginning/end and commercials). The script looks like this:

LoadPlugin("DGAVCDecode.dll")
V=AVCSource("Project.dga")
A=DirectShowSource("Project PID 1100 DELAY -180ms.aac", video=false, seek=false)
AudioDub(V, A)
DelayAudio(-0.180)

[UPDATE 1/3/2010: You may want to use seekzero=true instead of seek=false as some seeking may be required depending on the context.]

Make sure to match the DelayAudio() with the delay from the AAC file then load the AVS into VirtualDub. This part can be time consuming as this is where I seek through the whole stream to find commercials and other parts I want to strip. For every part to strip I write down the first frame and last frame numbers to insert into the AVS. Once this is done you simply trim all the frames you want to keep like this:

Trim(29, 13187)+Trim(19031, 57183)+Trim(60138, 62091)

This strips the following frame ranges: 0-28, 13188-19030, 57184-60137 and 62092 to the end. Basically, Trim tells Avisynth to keep the specified frame range.

3. Now is the time to start encoding. First you will need to calculate your bitrate to make sure the newly encoded stream will fit your target media. Open the Bitrate Calculator and input your stream length and audio bitrate (I use 128Kpbs) and select your target media. Keep in mind the target bitrate is an average bitrate therefore you may want to bring it down by 1-2% to make sure you won’t have to re-encode the stream a second time.

For encoding the video, I use the following 2-pass encode:

x264.exe --profile high --pass 1 --bitrate 16000 --threads auto --thread-input --output Project.ts.avs.264 Project.ts.avs
x264.exe --profile high --pass 2 --bitrate 16000 --threads auto --thread-input --output Project.ts.avs.264 Project.ts.avs

For the audio, I use the following 1-pass encode:

wavi Project.ts.avs - | faac.exe -b 128 -o Project.ts.avs.aac -

Then I end up with 2 files, Project.ts.avs.264 and Project.ts.avs.aac which I multiplex in MKVToolnix to produce an MKV file. Make sure to select your video framerate in mmg.exe as .264 files do not store that information (you should get a warning after adding the .264 into mmg). Optionally, you can also select the language for both streams. That’s it for the high quality archive copy!

4. To create a DVD compliant structure, I use mencoder (lavcodec) for encoding both the video and audio. Here’s the command line I use for a high quality encode:

mencoder.exe -mc 0 -noskip -ovc lavc -nosound -lavcopts threads=2:vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=9668:keyint=15:vpass=1:trell:mbd=2:precmp=2:subcmp=2:cmp=2:dia=-10:predia=-10:cbp:mv0:vqmin=1:lmin=1:dc=10:vstrict=0:aspect=16/9 Project.ts.avs -o Project.ts.avs.mpg -ofps 30000/1001 -of mpeg -mpegopts format=dvd:tsaf
mencoder.exe -mc 0 -noskip -ovc lavc -nosound -lavcopts threads=2:vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=9668:keyint=15:vpass=3:trell:mbd=2:precmp=2:subcmp=2:cmp=2:dia=-10:predia=-10:cbp:mv0:vqmin=1:lmin=1:dc=10:vstrict=0:aspect=16/9 Project.ts.avs -o Project.ts.avs.mpg -ofps 30000/1001 -of mpeg -mpegopts format=dvd:tsaf
mencoder.exe -mc 0 -noskip -ovc lavc -oac lavc -lavcopts acodec=ac3:abitrate=128:threads=2:vcodec=mpeg2video:vrc_buf_size=1835:vrc_maxrate=9800:vbitrate=9668:keyint=15:vpass=3:trell:mbd=2:precmp=2:subcmp=2:cmp=2:dia=-10:predia=-10:cbp:mv0:vqmin=1:lmin=1:dc=10:vstrict=0:aspect=16/9 -srate 48000 -af lavcresample=48000 Project.ts.avs -o Project.ts.avs.mpg -ofps 30000/1001 -of mpeg -mpegopts format=dvd:tsaf

Here you could tweak the first and 2nd pass for better performance (remove CPU intensive switches). Also, vpass=3 isn’t a mistake for pass no. 2 (you can read mencoder’s manpage for more details). Now at this point if everything went fine with the encode you should end up with a Project.ts.avs.mpg file.

5. Time to create the DVD structure with DVDAuthor. This is as simple as this:

dvdauthor.exe -t -o PROJECT Project.ts.avs.mpg
dvdauthor.exe -T -o PROJECT

Here, PROJECT is an output folder containing the DVD structure (AUDIO_TS and VIDEO_TS folders). The -t switch creates the titleset and the -T switch creates the table of content (which contains only the single titleset created from -t).

6. The last step to create the DVD is to burn the disc. Just fire up ImgBurn and select Create image file from files/folders and under the Output menu select Device to burn the result to disc.

Et voilà. Of course there is always a thousand ways of re-encoding a stream so keep in mind this is only one way of doing it… 🙂

Simulating .NET events in native C++

My last post talks about simulating delegates in native C++ and using them asynchronously. This is all nice, but its far from having all the same features as the equivalent from the CLR. For example, its missing events.

An event is basically like a multicast delegate but it is defined but subscriber objects. An event with no subscribers is basically useless, in fact it will even raise an exception if you call it with no subscriptions.

So as a starter to mimic this behavior in native C++ I created a tiny class to follow my previous design (using IDelegate):

class CEvent
{
public:
	CEvent(BOOL bAutoClean = TRUE) :
		m_bAutoClean(bAutoClean)
	{ }

	virtual ~CEvent()
	{
		if (m_bAutoClean)
			for (INT i = 0; i < m_cDelegates.GetSize(); i++)
				delete m_cDelegates[i];
	}

	VOID operator()(ULONG_PTR ulParam)
	{
		for (INT i = 0; i < m_cDelegates.GetSize(); i++)
 			m_cDelegates[i]->Invoke(ulParam);
	}

	const CEvent &operator+=(IDelegate *pDelegate)
	{
		BOOL bRes = m_cDelegates.Add(pDelegate);
		ATLASSERT(bRes != FALSE);
		return *this;
	}

	const CEvent &operator-=(IDelegate *pDelegate)
	{
		BOOL bRes = m_cDelegates.Remove(pDelegate);
		ATLASSERT(bRes != FALSE);
		return *this;
	}

private:
	BOOL m_bAutoClean;
	CSimpleArray m_cDelegates;
};

As we see there is much resemblance between a delegate and an event as they both can be invoked. In fact, in the CLR an event is a type modifier while a delegate is a reference type meaning events are based on delegates.

So to use the above class you can now do something like this:

class X
{
public:
        CEvent Processed;
        ...
};

class Y
{
public:
        VOID Initialize()
        {
                m_x.Processed += MAKECLSDELEGATE(Y, OnProcessed);
                ...
        }

        ULONG_PTR OnProcessed(ULONG_PTR ulParam)
        {
                ...
                return 0;
        }

private:
        X m_x;
};

I find it pretty neat as it makes code more readable and improves decoupling.

Asynchronous Programming Design Patterns

The .NET Framework includes a lot of asynchronous design patterns such as IAsyncResult and event based asynchronous calls. This is all very nice but unfortunately native C++ programmer are left behind to implement their own solutions for dealing with async calls.

In that line of thought I decided I would implement a piece of the asynchronous patterns in native C++, the IAsyncResult based pattern and since I use WTL to code native Windows applications I adopted the same coding style as WTL.

So here comes my first Code Project article.