Published by alax on 19 Nov 2008

Multiple Windowless Video Mixing Renderers (VMR9) Sample

This is a begged MFC code for multiple windowless video renderers. MFC project, two independent video renderers hosted by the same parent window (actually through owned controls but this makes no major difference), VMR9 in windowless mode.

There are no WM_PAINT/WM_ERASEBKGND handlers, IVMRWindowlessControl9::RepaintVideo calls and other basically required code, instead a minimalistic snippet to make video rendered the requested way.

A Visual C++ .NET 2008 source code is available from SVN, release binary included.

Published by alax on 13 Nov 2008

Crap Around the World - PICVideo MJPEG Decompressor

Yesterday I received a complaint from a Most Important Customer about a weird problem on a few of their digital video recording servers. The problem was that a new version of software, client part, would out of a sudden auto-close without any notice. The problem was quite persistent and basically of not a difficult kind because such fatal problems are automatically logged with a descriptive enough log to identify the cause in an extremely effective way. However the log files appeared to be empty. Another unexpected part was that a few systems showed the issue while the other did not and software worked in a quite expected and stable way there.

After a couple of phone calls and setting up remote access using TightVNC and port forwarding I could see this myself and it was obvious that there is an exception, such as memory access vioaltion, which takes place however on a thread created outside of my code and runnning without a proper guarding section to at the very least catch the exception and log its call stack. The visual symptoms led to supposition that it is something DirectShow related and chances are high that it is either a hardware acceleration issue, or a software compatibility issue. Luckily, hardware acceleration assumption is easy to eliminate by switching off, letting it run without and seeing if there is any difference. There was not.

Then it appeared that while these system were close to clean installation state, there was another DVR software installed also, to be used for tasks not covered by our software. And my first guess was if it installed certain DriectShow filter of the crappy kind, which could interfere with our award winning software, the best of the best. A quick test of renaming “C:\Program Files\Another-DVR” into a different name making all contained binaries unopenable by path showed that nothing changed essentially. So it was GraphEdit, which was downloaded there and a list of installed filters was insepected visually.

There were a few filters that was present in the system but which were obviously installed additionally to the system, as a part of Another-DVR product or in a different way. There was a few filters by I. and then my look stumbled on something which I immediately thought of “That’s It!”. Well, taking into consideration time spent on the problem it was rather “That’s Fucking It!”.

A rename of the hosting file pvmjpg21.dll in %WINDIR%\system32 immediately fixed the problem! Oo-omm-m “PICVideo MJPEG Decompressor” by Pegasus Imaging Corporation, crap! It was one of those moments sung of by Fort Minor:

This is twenty percent crap, eighty percent lame
And a hundred percent reason to remember the name!

However, let us what was going on there. A quick look at the registration information makes it clear the video decoding bastard registered itself under MERIT_PREFERRED (0×00800000) merit and generic MEDIATYPE_Video/MEDIASUBTYPE_NULL media type. Why on earth a properly made codec would claim to be able to decode any video as prefered software? It obviously adds overhead to the entire DirectShow subworld on that system by poking its pin into anything that moves without a proper luck to actually connect.

However, it would be just an overhead, maybe even unnoticable, if the bastard was a thread safe library. But it was unfortunately not. Since my software starts showing multiple video feeds simultaneously, this piece of junk was simultaneously instantiated in multiple threads and just crashed the entire process.

P.S. Bonus: “pvmjpg21.dll crash” on Google

Published by alax on 24 Aug 2008

How To: Save image to BMP file from IBasicVideo or VMR windowless interface

A simple question being asked all over again. Given IBasicVideo, IBasicVideo2, IVMRWindowlessControl or IVMRWindowlessControl9, how to save image to file? It is easy. It is a bit easier with IBasicVideo because it is possible to query this interface directly from graph’s interface, such asĀ  IGraphBuilder, and the call will be forwarded to video renderer. This code assumes internal bitmap format is non-paletted, which I believe is always the case.

LONG nBufferSize = 0;
ATLENSURE_SUCCEEDED(pBasicVideo->GetCurrentImage(&nBufferSize, NULL));
CHeapPtr<BITMAPINFO> pBitmapInfo;
ATLENSURE_THROW(pBitmapInfo.AllocateBytes(nBufferSize), E_OUTOFMEMORY);
ATLENSURE_SUCCEEDED(pBasicVideo->GetCurrentImage(&nBufferSize, (LONG*) (BITMAPINFO*) pBitmapInfo));
const BYTE* pnData = (const BYTE*) (&pBitmapInfo->bmiHeader + 1);
// NOTE: You might wish to handle <=8 bpp bitmaps here
ATLASSERT(pBitmapInfo->bmiHeader.biBitCount > 8);
ATLASSERT(pBitmapInfo->bmiHeader.biCompression == BI_RGB);
ATLASSERT(pBitmapInfo->bmiHeader.biSizeImage);
BITMAPFILEHEADER BitmapFileHeader;
ZeroMemory(&BitmapFileHeader, sizeof BitmapFileHeader);
BitmapFileHeader.bfType = 'MB';
BitmapFileHeader.bfSize = (DWORD) (sizeof (BITMAPFILEHEADER) + pBitmapInfo->bmiHeader.biSize + pBitmapInfo->bmiHeader.biSizeImage);
BitmapFileHeader.bfOffBits = (DWORD) (sizeof (BITMAPFILEHEADER) + pBitmapInfo->bmiHeader.biSize);
ATLENSURE_SUCCEEDED(File.Write(&BitmapFileHeader, sizeof BitmapFileHeader));
ATLENSURE_SUCCEEDED(File.Write(&pBitmapInfo->bmiHeader, pBitmapInfo->bmiHeader.biSize));
ATLENSURE_SUCCEEDED(File.Write(pnData, (DWORD) pBitmapInfo->bmiHeader.biSizeImage));

Published by alax on 20 Aug 2008

Mobotix cameras online (updated)

Mobotix cameras online, various models discovered by web spider bot, see previous list here:

Basic

D10D-Secure

D12D-Sec

Continue Reading »

Published by alax on 06 Aug 2008

How To: Wrap an existing DirectShow filter with a private video source filter (COM aggregation)

See beginning in microsoft.public.win32.programmer.directx.video newsgroup.

This sample is demonstrating COM aggregation to embed an existing filter an re-expose it as a new filter having inner filter pre-initialized.

The Visual Studio C++.NET 2008 projects contains a DirectShow filter class that registers itself under Video Capture Sources category and embeds File Source (Async) Filter inside initialized to stream clock.avi file from Windows directory.

Continue Reading »

Published by alax on 24 Jul 2008

Video Conversion: YUY2 to YV12

See topic on MSDN Forums about coloring issue.

This is a demo of YUY2 to YV12 conversion as suggested copying Y values and averaging U and V.

Original image is on the right.

Code snippet to perform the transformation:

Continue Reading »