Downloading Windows 7 Beta 32-bit

I decided to download a beta of Windows 7, so many people shared their positive impressions of. I am not quite sure I will have time to actually evaluate it, but for the case I would feel like, it is always nice to have the .ISO image ready for a try.

There was nothing worth a word until I reached the download screen which opened an extremely awful Java applet that pretended to be a download manager. It seemed to be a new spin of technology and sort of I don’t need a nice download manager anymore because direct HTTP links are out of fashion. It started pumping bytes (actually thanks for that) and I my attempt to copy/paste a direct link into my DownThemAll FireFox plugin was vain.

At some 20% the download froze without a notice. The download did not even ungray the resume buttons before I restarted FireFox process and then any attempt to resume led to weird message boxes. Frankly at this point I almost lost the desire to actually complete the download. But left a last chance to have it completed by IE. Internet Explorer (expectedly!) preferred ActiveX control to Java applet. It’s GUI was a bit less scary and it took over incomplete download and…

An attached debugger showed a call stack (oops, I did not save exact call stack) in Manager.exe process in C runtime module, in a CString class method… It went no further than this crashing at exactly the same point until I manually deleted the incomplete download, when it again repeated a weird message box and then finally restart the download from the start. That was enough for me and found a .torrent with the exactly the same file on thepiratebay.org, which I am quite sure will download without a problem.

Isn’t it incredibly stupid that significant amount of work was invested into unnecessary task, ugly user interface, buggy implementation (freeze, incapable download manager, weird messages, crash) with a solid residual of inability to conveniently download the thing, while the file could be just put onto regular MS download service?

DirectShow Filter Graph Spy – CLSID_FilterGraphNoThread

At the time of original implementation I intentionally left off a variation of Filter Graph Manager that runs on application thread, CLSID_FilterGraphNoThread. MSDN says:

CLSID_FilterGraphNoThread creates the Filter Graph Manager on the application’s thread. If you use this CLSID, the thread that calls CoCreateInstance must have a message loop that dispatches messages; otherwise, deadlocks can occur. Also, before the application thread exits, it must release the Filter Graph Manager and all graph objects (such as filters, pins, reference clocks, and so forth).

I have never needed to use this CLSID (by the way Windows SDK has one more CLSID – CLSID_FilterGraphPrivateThread – but it does not seem to be documented) and for this reason I left it for the time a need in it comes up. However it appeared that this CLSID was not created just for fun, there was a need in it. Filter graphs of Windows Media Player playing well known Windows’ clock.avi appeared to be not published on Running Object Table. Why?

Process Monitor showed clearly that Windows Media Player created filter graph through CLSID_FilterGraphNoThread and quite obviously it was not intercepted by Filter Graph Spy (still I wonder what made it different previous time when I could see WMP’s graph).

Continue reading →

DirectShow Filter Graph Spy

Inspired by a post on DirectShow Development Forum, it is sometimes useful to find out how certain application is using DirectShow to capture live video and/or audio, or play certain file etc. Filter graph topology, details about media types on the pins, used interfaces and call order. There is quite an easy step for the developer to spy over running filter graphs system wide by connecting Component Object Model (COM) “Treat As” feature with filter graph remoting through Running Object Table and connecting to remote process graphs using GraphEdit utility. Who could imagine Windows Media Player to build such a filter graph for a video and audio Windows Media file? SRS Wow DMO, equalizer, analyzer and stuff? Continue reading →

The easiest yet user-friendly WTL way to Minimize Application to System Tray Icon

A good old task to easily minimize to system tray icon to not clog the application bar and without too much thinking about it. How To with WTL?

The key points are:

  • manage NOTIFYICONDATA structure (obviously!), where non-zero .cbSize will be an indication of created icon
  • create an icon in WM_SYSCOMMAND/SC_MINIMIZE handler and hide instead default minimization
  • handle icon’s WM_LBUTTONDBLCLK to restore and WM_RBUTTONUP to pop up a menu
  • use default dialog menu to avoid having private one, handle SC_RESTORE and SC_CLOSE system commands to restore and close from system tray icon popup menu

Relevant source code from application main window (dialog) class:

Continue reading →

JPEG Multi File Video Capture Source Filter, a virtual DirectShow camera

Provided that there already is a JPEG Multi File Source Filter that can act as a video source streaming video from local JPEG files, it looked to be useful to build a virtual camera on top of this filter. This is the main difference: an existing filter is generic and customizable: it requires to be provided a directory with the files, other settings may also apply. A virtual camera is the filter that has to work out of the box: a video enabled application, such as AMCap Sample, Media Player Classic, VideoLAN, Skype, Windows Media Encoder enumerates video capture sources, instantiate the one of the interest and it should already be ready to stream.

Implementation Details

The very first question is embedding of an existing filter into new filter. The two most common methods are:

  • COM aggregation
  • embedding a fully featured graph with a sink/renderer that intercepts media samples downstream and forwards to a higher level filter so that it streams them as a source filter

The COM aggregation methods is much easier in implementation but it is subject to a few constraints, the two most important of which are:

  • embedded filter should support instantiation as an aggregated object
  • it is the only underlying filter, not a chain of filters, which can produce required data

COM aggregation is quite fitting for the purpose, so the second embedding method is being left for another topic (with a certain luck to be appear very soon, a DirectShow video capture source filter for a real network/IP camera).

The next step is a check of sufficient implementation in an underlying filter. Obviously, a video source that pretends to be a live video capture source needs an endless stream of media samples, while original implementation streams JPEG files as media samples once only, we need an option to loop the streaming and automatically repeat the sequence.

Playback looping is added to the original JPEG Multi File Source Filter and its controlling private interface IJpegMultiFileSourceFilter received additional properties:

interface IJpegMultiFileSourceFilter : IDispatch
{
...
    [propget, id(2)] HRESULT AutoRepeat([out, retval] VARIANT_BOOL* pbAutoRepeat);
    [propput, id(2)] HRESULT AutoRepeat([in] VARIANT_BOOL bAutoRepeat);
    [propget, id(3)] HRESULT RepeatDelay([out, retval] LONG* pnRepeatDelay);
    [propput, id(3)] HRESULT RepeatDelay([in] LONG nRepeatDelay)

as well the new property page:

Continue reading →

AMCap issue

While playing around with a camera DirectShow video source filter, AMCap, which is widely used sample and which I believed to be very stable, started crashing in an inner call CDeviceMoniker::IsEqual:

 	devenum.dll!CDeviceMoniker::IsEqual()  + 0x13 bytes
>	AmCap.exe!ChooseDevices(IMoniker * pmVideo=0x003e9a38, IMoniker * pmAudio=0x00000000)  Line 2672 + 0x2a bytes	C++
 	AmCap.exe!ChooseDevices(wchar_t * szVideo=0x0013f5b8, wchar_t * szAudio=0x0013edb0)  Line 2753 + 0x13 bytes	C++
 	AmCap.exe!AppInit(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * hPrev=0x00000000, int sw=1)  Line 379 + 0x13 bytes	C++
 	AmCap.exe!WinMain(HINSTANCE__ * hInst=0x00400000, HINSTANCE__ * hPrev=0x00000000, char * szCmdLine=0x00161f32, int sw=1)  Line 453 + 0x11 bytes	C++
 	AmCap.exe!__tmainCRTStartup()  Line 578 + 0x35 bytes	C
 	AmCap.exe!WinMainCRTStartup()  Line 403	C
 	kernel32.dll!_BaseProcessStart@4()  + 0x23 bytes

It appeared that while setting a checkmark on proper menu item the code does not check for the moniker tobe not NULL and a NULL IMoniker pointer passed as an argument into IMoniker::IsEqual is not checked inside devenum.dll (which is obviously a bug for an API entry).

To hotfix the problem, it is necessary to add an extra check near line 2650 of amcap.cpp:

    int i;
    for(i = 0; i < NUMELMS(gcap.rgpmVideoMenu); i++)
    {
        if(gcap.rgpmVideoMenu[i] == NULL)
            break;
        // HOTFIX: Avoid calling IMoniker::IsEqual(NULL) due to possible memory access violation
        if(!gcap.pmVideo)
            continue;
        CheckMenuItem(GetMenu(ghwndApp),
            MENU_VDEVICE0 + i,
            (S_OK == gcap.rgpmVideoMenu[i]->IsEqual(gcap.pmVideo)) ? MF_CHECKED : MF_UNCHECKED);
    }

    for(i = 0; i < NUMELMS(gcap.rgpmAudioMenu); i++)
    {
        if(gcap.rgpmAudioMenu[i] == NULL)
            break;
        // HOTFIX: Avoid calling IMoniker::IsEqual(NULL) due to possible memory access violation
        if(!gcap.pmAudio)
            continue;
        CheckMenuItem(GetMenu(ghwndApp), MENU_ADEVICE0 + i,
            (S_OK == gcap.rgpmAudioMenu[i]->IsEqual(gcap.pmAudio)) ? MF_CHECKED : MF_UNCHECKED);
    }

MediaTools to deliver video from network/IP cameras and video servers into DirectShow environment

I decided to gather DirectShow code and filters related to processing video from network/IP cameras and video servers into a library (in fact, a few libraries) so that it could be easily used for testing, research and other purposes. As time is going to permit, documentation and sample code will be provided, further development will be carried out.

This initial post publishes two libraries (DLLs) which host DirectShow filters to receive JPEG or M-JPEG video from network using HTTP based protocol, decode video with the help of Intel IPP 6.0 library (UMC version of the JPEG implementation), as well as perform additional helpful features, including writing series of frames into .JPG files and emulating video feed from saved .JPG files, conversion filters to obtain video in 24-bit and 32-bit RGB formats, YUY2 and YV12 formats.

File and Class Summary

Acqusition.dll

Acqusition.dll (download) hosts the following classes:

  • DirectShow Filters
    • HTTP Stream Source Filter, to receive HTTP content and deliver into DirectShow environment through output pin
    • JPEG HTTP Stream Parser Filter, to parse HTTP content (typically received from HTTP Stream Source Filter) of image/jpeg and multipart/x-mixed-replace types and output JPEG frames
    • JPEG Multi File Renderer Filter, to write parsed JPEG frames (typically received from JPEG HTTP Stream Parser Filter) into files
    • JPEG Multi File Source Filter, to read JPEG files (typically written by JPEG Multi File Renderer Filter) and stream video into DirectShow environmentto emulate video feed

Acqusition.dll is dependent only on well known DLLs and does not require presence/redistribution of specific dependency files.

CodingI.dll

CodingI.dll (download) hosts the following classes:

  • DirectShow Filters
    • JPEG Frame Decoder Filter, to parse JPEG data and pass frames downstream with a corresponding mediatype provided with VIDEOINFOHEADER format and correct resolution; in case of resolution changes the filter is capable of dynamically re-agreeing media type with downstream peer
    • JPEG Decoder Filter, to decode JPEG data into 24-bit/32-bit RGB (unfortunately Intel IPP codec has limited capabilities of decoding video into YUV pixel formats)
    • YUY2 Encoder Filter, to convert RGB data into YUY2 pixel format
    • YV12 Encoder Filter, to convert RGB data into YV12 pixel format
  • Shell Extensions
    • JPEG File Resolution Shell Property Page, to provide additional information (such as sampling, color format, resolution) about .JPG and .JPEG files through a shell property page

CodingI.dll is dependent on Intel IPP 6.0 library DLLs and relies on availability of these dependencies in the system. For the CodingI.dll to be operationable, it is required to have a free, trial or registered version of Intel IPP library installed. In particular, the files that are sufficient to be present/redistributed are:

  • libguide40.dll, libiomp5md.dll
  • ippcore-6.0.dll
  • ippi-6.0.dll, ippj-6.0.dll, ipps-6.0.dll, ippcc-6.0.dll, ippvc-6.0.dll
  • ippipx-6.0.dll, ippjpx-6.0.dll, ippspx-6.0.dll, ippccpx-6.0.dll, ippvcpx-6.0.dll

Quick Usage Example

Given a M-JPEG compatible network camera on IP address 98.76.54.32, the graph constructed as shown below is capable to deliver video data and render it through standard Video Mixing Renderer Filter.

Assume the camera is StarDot NetCam SC series, with /jpeg.cgi HTTP request to query for JPEG image and /nph-mjpeg.cgi HTTP request to query for M-JPEG video feed.

To construct the graph in GraphEdit (GraphStudio), first it is required to manually add Alax.Info HTTP Stream Source Filter and provide HTTP URL for the request in the property page:

Then an Alax.Info JPEG HTTP Stream Parser Filter is added and connected downstream to the previously added source filter:

A this point it is possible to automatically render output pin and DirectShow intelligent connect will add the rest of required filters, Alax.Info JPEG Frame Decoder (I), Alax.Info JPEG Decoder (I) and Video Renderer.

However, in order for the graph to run in GraphEdit it is required to manually provide correct video resolution in the properties of JPEG Frame Decoder Filter and once applied reconnect all downstream connections up to video renderer in order to enforce new media type.

Running the graph will start streaming video.

Class Overview

HTTP Stream Source Filter

The filter sends one or series of HTTP requests to receive data from network location and stream received data into DirectShow environment.

Continue reading →